Area heartbeat
#1
Posté 26 novembre 2009 - 11:40
in NWN, heartbeat was pretty easy to implement.
It is a little more complicated with the event driven engine of DA.
I would like that when the PC is in an area, this area randomly spawns stuff every x seconds.
The "randomly spawn stuff" is ok, but I can't figure out the "every x seconds" part.
Any Idea?
#2
Posté 26 novembre 2009 - 02:01
Is this just a tiny room? Is it an area where you have to define where the monsters should come from? Is there anything else in the area? Should the monsters spawn relative to where the players are in a larger area?
From what I see, in DAO only players have heartbeat events, and they happen every 3s, and it also seems like the creature heartbeat is simply used to seed AI behavior changes based on time. There also appear to be engine level heartbeat events, but I doubt any script will be able to hook into those.
Even considering the following in player_core.nss
// -----------------------------------------------------------------
// Legacy Heartbeat event. Left for the consumption of modders.
// Be careful with it, it's not nice to run on a lot of creatures...
// -----------------------------------------------------------------
case EVENT_TYPE_HEARTBEAT:
{
bEventHandled = TRUE;
break;
}
There is no certanty that the area or module itself is passed this event. As per events.xls, there are 3 heatbeat events:
EVENT_TYPE_AOE_HEARTBEAT
EVENT_TYPE_HEARTBEAT2
EVENT_TYPE_HEARTBEAT
The first two are engine events, and the 3rd is not called anywhere outside of player_core. Which leads me to the start of my post, in that you will likey have to seek out another method. A simple test would be to make a script that hooks EVENT_TYPE_HEARTBEAT and put it in your module script, and see if it gets run (make it give you gold or something, so you can see it every few seconds).
#3
Posté 26 novembre 2009 - 03:32
Actually, my NWN2 system works on the area HB, and spawns critters through WP.
And I checked, there are no "delay" functions either.
Another function I imagined is that, as EVENT_TYPE_HEARTBEAT2 goes on creature, I could change the WP with an invisible immortal immobile creature, that would be the spawning point of the system, with an initiateheartbeat() when the PC comes close, or enters the area...
But I will give a try to the module HB, as you propose.
Modifié par mj crom, 26 novembre 2009 - 03:33 .
#4
Posté 26 novembre 2009 - 03:37
Modifié par DavidSims, 26 novembre 2009 - 04:11 .
#5
Posté 26 novembre 2009 - 03:44
#6
Posté 26 novembre 2009 - 03:44
#7
Posté 26 novembre 2009 - 03:50
#8
Posté 26 novembre 2009 - 04:04
Edit: I'm not finding a good explanation for this on the wiki (though I may just be missing it), so I'll see about putting one up a bit later today.
Modifié par Craig Graff, 26 novembre 2009 - 04:08 .
#9
Posté 26 novembre 2009 - 11:27
#10
Posté 03 décembre 2009 - 05:00
#11
Posté 03 décembre 2009 - 05:06
#12
Posté 03 décembre 2009 - 05:57
mj crom wrote...
So I can DelayEvent a function, like CreateObject ? I thought DelayEvent was for event ...
No, there is no way to delay a function call.
DelayEvent signals the event to the specified object after the delay.
You can make an area heartbeat this way by first sending a heartbeat event to the area, then within the area's script have a case for the heartbeat event, and within that handling delay a heartbeat event sent back to the area. Every time the heartbeat is run, it queues up the next one.
#13
Posté 03 décembre 2009 - 06:29
So you would call
DelayEvent(5f, null, EVENT_BOGUS_DO_NOTHING, null);
??
#14
Posté 03 décembre 2009 - 06:41
Hoagsie wrote...
Wouldn't be possible to make a new and empty event to fire?
So you would call
DelayEvent(5f, null, EVENT_BOGUS_DO_NOTHING, null);
??
Yes, but what would be the point? It would do nothing.
Although some events are sent by the engine, many are entirely scripted. The event type is just an integer. You can make whatever events you want with whatever event type you want and with whatever parameters stored on the event you want. You can send these events to any object you want. The event handling is done entirely through scripting, so you can see exactly what will happen by tracing through the object's script. You do however have to be very careful about overlapping event type IDs. For safety, using the EVENT_TYPE_CUSTOM_EVENT_1 is a good idea.
#15
Posté 03 décembre 2009 - 07:01
#16
Posté 04 décembre 2009 - 07:11
my_custom_area_script.nss
#begin psuedo code
EventType(Event_area_load)
{
DelayEvent(10.0f, myarea, myevent, "my_custom_area_script.ncs")
}
EventType(myevent)
{
SpawnMonster()
DelayEvent(10.0f, myarea, myevent, "my_custom_area_script.ncs")
}
#end psuedo codeThough that assumes an area is classified as an object, which should be as per Script.ldf:
int OBJECT_TYPE_INVALID = 0;
int OBJECT_TYPE_GUI = 1;
int OBJECT_TYPE_TILE = 2;
int OBJECT_TYPE_MODULE = 4;
int OBJECT_TYPE_AREA = 8;
int OBJECT_TYPE_STORE = 16;
int OBJECT_TYPE_CREATURE = 32;
int OBJECT_TYPE_ITEM = 64;
int OBJECT_TYPE_TRIGGER = 128;
int OBJECT_TYPE_PROJECTILE = 256;
int OBJECT_TYPE_PLACEABLE = 512;
int OBJECT_TYPE_AREAOFEFFECTOBJECT= 2048;
int OBJECT_TYPE_WAYPOINT = 4096;
int OBJECT_TYPE_SOUND = 16384;
int OBJECT_TYPE_PARTY = 32768;
int OBJECT_TYPE_MAPPATCH = 65536;
int OBJECT_TYPE_VFX = 131072;
int OBJECT_TYPE_MAP = 262144;
Modifié par Nodrak, 04 décembre 2009 - 07:13 .
#17
Posté 05 décembre 2009 - 10:28
And this heartbeat stuff is quit crucial for my mod .
#18
Posté 08 décembre 2009 - 08:34
//script named 'my_heartbeat'
#include "utility_h"
#include "wrappers_h"
#include "events_h"
void main()
{
object oPC=GetMainControlled();
object oMod=GetModule();
//////////////////////////
//simple counter for testing, be sure to declare variable 'Heartbeat' in var_modname 2DA
if(IsObjectValid(oPC))
{
int iCounter=GetLocalInt(oMod,"Heartbeat");
iCounter++;
SetLocalInt(oMod,"Heartbeat",iCounter);
DisplayFloatyMessage(oPC, "Heartbeat="+IntToString(GetLocalInt(oMod,"Heartbeat")), FLOATY_MESSAGE, 14654488, 1.0);
}
DelayEvent(6.0f,oPC,Event(EVENT_TYPE_HEARTBEAT),"my_heartbeat");
}
To kick things off you can do several things, the easiest for testing is to draw a trigger around the module startpoint and put this on it.
void main()
{
if(GetLocalInt(OBJECT_SELF,"TRIGGER_DO_ONCE_A")==0)
{
SetLocalInt(OBJECT_SELF,"TRIGGER_DO_ONCE_A",1);
DelayEvent(6.0f,oPC,Event(EVENT_TYPE_HEARTBEAT),"my_heartbeat");
}
}
Modifié par georage, 08 décembre 2009 - 08:36 .
#19
Posté 09 décembre 2009 - 07:24
#20
Posté 09 décembre 2009 - 12:44
Additionally there is an issue when using DelayEvent with an area object: the scriptname parameter does not appear to have any effect and so you must use the area's assigned script to handle the delayed event.
#21
Posté 09 décembre 2009 - 04:18
The point of my post being to show you can make a master heartbeat which is quite flexible.
Simply check if various objects (creatures, areas, etc) are valid, and if so, execute a certain portion of code.
To work more like NESS, the popular spawn script from NWN, you would simply check for the PC as above, but also check to see which area the PC is in. Then you execute the portion of code you need to spawn creatures in that particular area.
Of course, adding a Spawn() function to each area would work too.
#22
Posté 09 décembre 2009 - 04:32
And the "kicker" lacks the "event_h" include.
But it certainly achieved its goal for me :-)
#23
Posté 09 décembre 2009 - 07:28
Which would do what exactly? In your "area" heartbeat OBJECT_SELF is the PC and in order to get a reference to the area you're suggesting GetModule?georage wrote...
True, but you can replace OBJECT_SELF with GetModule()
To correct the DelayEvent calls replace the reference oPC with GetArea in the kicker and OBJECT_SELF in the event script.
Modifié par Sunjammer, 09 décembre 2009 - 07:29 .
#24
Posté 09 décembre 2009 - 07:54
I understand you are the superior programmer Sunjammer. Thanks for your help.
Modifié par georage, 09 décembre 2009 - 07:57 .
#25
Posté 09 décembre 2009 - 07:58





Retour en haut






