Event Scripts Not Firing in Module

Hey all, I have updated a module in the toolset to fire a script on heartbeat in module properties, saved it, but the script does not fire in-game. I’ve done this in several other modules and it always works, but not this time. Is there any way module event scripts can be overridden from the campaign folder or something?

Edit: I know the scripts themselves can be overridden directly, I am talking about what the event scripts are set to. As in inside module.ifo.

the scriptnames that you see in Module.Ifo can (possibly) be overwritten with the function

///////////////////////////////////////////////////////////////////////////////
// SetEventHandler
///////////////////////////////////////////////////////////////////////////////
// Created By: Brock Heinz - OEI
// Created On: 12/20/05
//
// Description: These commands will allow you to bind any script to the
//              to an exisiting event for a given object.
// Arguments:
//  oObject -  The object to which you want to bind a new script
//  iEventID - The event ID which you are binding the script to.
//  sScriptName - The name of the script that you want to bind to the event.
//              Note that it is valid to pass "" to have this creature ignore
//              the event.
///////////////////////////////////////////////////////////////////////////////
void SetEventHandler(object oObject, int iEventID, string sScriptName);

… not likely but possible. So the usual checklist: Is module saved? Is script compiled and someplace accessible to the engine when the module is loaded?

 
ps. note that if your custom script is in the Module directory, it won’t be used when loading a saved game …

2 Likes

Thanks for the reply!

Script is set in module properties correctly (confirmed set in module.ifo), module is saved, script is in override (tossed it in the campaign directory too for good measure), no duplicate script is in any of the associated haks. I grepped the campaign folder for SetEventHandler earlier and nothing came up. I will check the module folder for it too.

Checked for SetEventScript as well. Not sure if that is a thing anymore in NWN2.

This one has got me a bit stumped!

hm, idk

I use a console script to get/print eventhandlers (just to see that they are what i think they are). It uses →

///////////////////////////////////////////////////////////////////////////////
// GetEventHandler
///////////////////////////////////////////////////////////////////////////////
// Created By: Brock Heinz - OEI
// Created On: 12/20/05
//
// Description: Retrieves the name of a script bound to a given event ID
// Arguments
//  oObject -  The object to which you want to bind a new script
//  iEventID - The event ID which you are binding the script to.
//
// Returns: Returns a string with the script name which the object has bound
//          to the event. This will be empty if the creature or event ID is
//          invalid.
///////////////////////////////////////////////////////////////////////////////
string GetEventHandler(object oObject, int iEventID);

but while it works for most objects (creatures, placeables) it only returns blank strings (for me) when passed the Module or an Area …

 
ps. SetEventScript() doesn’t seem to be a thing in Nwn2.

and no dupe in /override? … it’s gotta be something silly :)

you could try forcing the script from the console …

void main()
{
    object oModule = GetModule();
    SetEventHandler(oModule, SCRIPT_MODULE_ON_HEARTBEAT, "script");
}

I know, it is always something silly. The Development folder is both my best friend and worst enemy in NWN1 as I am always leaving conflicting things in there. I’m sure it is something similar here as well.

1 Like

Does SetEventHandler work on the module?

huh apparently not. Just tested with these:

// 'setmodulehb'
/*
	Console script.

	Sets the Module OnHeartbeat script.
*/

void main()
{
	SetEventHandler(GetModule(), SCRIPT_MODULE_ON_HEARTBEAT, "testmodulehb");
}
 // 'testmodulehb'
 /*
 	Module OnHeartbeat script.
 */

 void main()
 {
 	SendMessageToPC(GetFirstPC(FALSE), "testmodulehb");
 }

The heartbeat script is just not firing. I made a brand new script to wrap and fire the hb script I am trying to run (and signal that it is running), added it to the module heartbeat event script and saved:

void main()
{
	SendMessageToPC(GetFirstPC(), "myk_mod_hb running");

	ExecuteScript("cmi_mod_hb", OBJECT_SELF);
}

Nothing.

I thought maybe it was an issue with GetFirstPC not working, but I made a script to test it and it worked like a charm when I ran it from the debug console:

void main()
{
	object oPC = GetFirstPC();
	
	SendMessageToPC(oPC, "You are the first PC");
}

Am I losing my mind? Can the module heartbeat event just be disabled completely?

Also, I thought triple single quotes made it appear as a code block on this forum, is that incorrect?

That depends - there are 2 different types. Use

`

(on the UK keyboard that is the key immediately below the [Esc] key)

not

(on the UK keyboard that is the key with the @)

TR

Nice! Thank you.

not that i heard of. What module/campaign are you trying this with? if not your own, try setting things back to stock with a clean /override (under both install and MyDocs)

 
 
[edit] again on a longshot, an unusually long (or perhaps too short) custom hb-rate could be set

//RWT-OEI 02/27/08
//Sets a custom heartbeat interval on a creature or placeable.
//Note that speeding up the heartbeat rate on a lot of objects will impact
//performance. Also, in the case of creatures, there is still a random
//modifier of up to 1 second added to the heartbeat interval, so it
//won't be a precise interval.
// oTarget - creature or placeable
// nMSeconds - Number of milliseconds. 1000 = 1 second
void SetCustomHeartbeat(object oTarget, int nMSeconds);

//RWT-OEI 02/27/08
//Retrieve the custom heartbeat rate that was set via SetCustomHeartbeat.
//By default, is 0.
// oTarget - creature or placeable
// nMSeconds - Number of milliseconds. 1000 = 1 second
int GetCustomHeartbeat(object oTarget);

@ebonfowl

Just to clarify, do you mean you edited a copy of the module’s HB script, by adding an ExecuteScript function to call another script from the module’s HB script? EDIT: Also, if this is what you mean, does the executed script require any additional library include files? EDIT: Also, as an example, some “campaigns” may also have more than one module HB script involved, each one running depending upon which module is currently being played. i.e. The module HB script you are trying to alter may not be the one currently being run. (The OC has a number of module HB scripts.)

If so, I just tested with my own module (campaign structure) and, as expected, it worked in a saved game I had. I had placed an edited version of the module’s HB script and its accompanying script to be executed in the override folder.

Did you remember to copy the script you wish to execute into the override too? Were there any typos? Did you exit the game completely before testing? If you apply this kind of update with the game sitting at the Main Menu and then load the game, I have known it to not pick up the alterations you have made in the override folder. So, be sure to exit the game completely, make changes, then start test again.

I am also trying to understand what you are trying to do exactly, as it seems you recognise scripts can be directly overridden, but then appear to be asking something more specifically about object scripts.

Can you give a bit more detail about what you are trying to do? What is the module, and what script are your trying to run?

There may be an alternative means to do what you are trying to do.

1 Like

+1

a resource freshly created in /override requires that the game be shut down and restarted from the desktop.

a recompiled script that already exists in /override requires a restart, reload, or perhaps just an area transition

1 Like

@ebonfowl

Try having the ExecuteScript fire on the PC … (This worked for me.)

object oPC = GetFirstPC();
ExecuteScript("cmi_mod_hb", oPC);

This way, you can completely eliminate the original HB script and execute your own version, executed from the original.

Just remember that you will need to redefine the MODULE from the new script, as OBJECT_SELF will now be the PC.

NB: If you need other “existing” variables to fire from the module HB, then just edit stuff into the new executable, paying careful attention to what is the module and the PC within the new executed script called from the original module HB.

OK, to answer all the questions:

(Seriously thanks for the help - I am mostly doing this to test changes I have implemented to Kaedrin’s/Tome of Battle across many different modules/campaigns, but the fact that I cannot figure this one out is driving me nuts)

  1. the campaign is Wulverheim: Wulverheim | The Neverwinter Vault, and the module is Gallimere (starting module).

  2. Yes, I always apply module changes while I am exited out of the game completely.

  3. the module has no onheartbeat script by default. I added one in module properties and saved the module. When I open module.ifo with TlkEdit, it appears correctly in there. I have added cmi_mod_hb directly and tried adding that custom script I posted above that calls cmi_mod_hb after sending a message that it is running. Is there another step that needs to be completed after adding a new event script in module properties when one wasn’t already there besides adding it and saving the module? I am pretty certain I have added them from scratch before and did not have to do anything but add and save.

  4. Assuming the heartbeat is firing, the custom script should display the message telling me it is working even if there was another issue with cmi_mod_hb. But no message.

  5. no typos - when I click the script dropdown in module properties, it correctly displays the script’s NSS

  6. at this point the cmi_mod_hb script is in the module folder, the campaign folder and the main override folder in documents/Neverwinter Nights 2. All the exact same script.

  7. I have associated the script with EVERY module in the campaign.

  8. Regarding working in other modules: I have either added a new on heartbeat script (when one didn’t already exist) or added the ExecuteScript call for cmi_mod_hb to the existing heartbeat script to nearly fifty modules in like 7 or 8 different campaigns at this point, updated the cmi_mod_hb script in my override folder countless times and it works every time in those modules, just not this one.

  9. I know nothing is overriding it from an associated hak or from a higher priority in the override folder because I have checked a million times at this point and also the custom script I made (totally unique and exists only in the campaign folder) did not fire.

  10. No SetCustomHeartbeat in any of the scripts in the module or campaign. Also, based on the description I am not sure that one will work on the module object anyway.

2 Likes

Sry to say but for me worked fine first try …

steps used →
1 download Wulverheim
2 rename docs /nwn2
3 start nwn2 - let it write new docs /nwn2 folder - close nwn2
4 copy in my .ini files
5 install Wulverheim (manually)
6 open it in the toolset
7 open module Gallimere
8 goto module properties - OnHb is empty
9 write a small OnHb file in docs /override : mod_hb_gallimere
10 copy/paste its filename to module Gallimere OnHb slot
11 save module
12 load Wulverheim campaign
13 watch the debug message tick …

1 Like

Aside from the new documents folder, that is exactly my process. Your modules for that campaign are directories, correct. Not .mods?

yep, the manual install ships modules in directory format