OnModuleLoad can't run functions?

So it seems I am unable to initialize events such as CreateObject via OnModuleLoad. I checked the same script on the OnHeartBeat and it worked every 6 seconds.

I’m not sure what OnModuleLoad is meant for, but are there known limitations for it? Can I use something else for my CreateObject randomizer function instead?

I have no explanation for what is happening there, but have you tried putting the spawns in a custom script, and executing that script from within the OnModuleLoad one at a delay?

    DelayCommand(1.0, ExecuteScript("spawnsypants", OBJECT_SELF));

:thinking:

That didn’t work.

Just to make sure I’m clear, what I do is add #include MyScript on the OnModuleLoad event
and then use
MyScriptFunction();
to execute it
Whenever I run it via OnHeartBeat it works, and I’m using a “GetObjectByTag” for debugging to see if the function created the necessary objects. On the OnModuleLoad event it never creates them.

Here is my actual script, which spawns in random locations various creatures and placeables:

#include "x0_i0_position"

//function for random location
location RandomLocation()
{
    int nAreas = GetLocalInt(GetModule(), "itotalareas");
    int iRandom = Random(nAreas);
    string sRandom = IntToString(iRandom);
    object oArea  = GetObjectByTag("area"+sRandom);
    location lTargetArea = GetRandomLocation(oArea);
    return lTargetArea;
}

void Launch_EcoSystem()
{
int i;
string sHornBeetle = "beetle_horn_1";
string sStinkBeetle = "beetle_stnk_1";
string sWolfSpider = "wolf_spider_1";
string sHarpy = "haze__harpy_1";
string sMushroomBrown = "brownmushrooms";
string sMushroomGrey = "greymushrooms";
string sMushroomSpotted = "spottedmushrooms";

while (i < 20) //this loop spawns all the initial placeables and creatures necessary for the eco_system
{
    CreateObject(OBJECT_TYPE_CREATURE, sHornBeetle, RandomLocation());
    CreateObject(OBJECT_TYPE_CREATURE, sStinkBeetle, RandomLocation());
    CreateObject(OBJECT_TYPE_CREATURE, sWolfSpider, RandomLocation());
    CreateObject(OBJECT_TYPE_CREATURE, sMushroomBrown, RandomLocation());
    CreateObject(OBJECT_TYPE_CREATURE, sMushroomGrey, RandomLocation());
    CreateObject(OBJECT_TYPE_CREATURE, sMushroomSpotted, RandomLocation());
    CreateObject(OBJECT_TYPE_CREATURE, sHarpy, RandomLocation());
    i++;
}
}

If it’s

Launch_EcoSystem();

try delaying that:

DelayCommand(1.0, Launch_EcoSystem());

? I think maybe the objects (like the areas) might not officially exist yet at the time this is being called in OnModuleLoad.

Precisely. OnModuleLoad fires right at the beginning of the module, when some stuff, like areas and such may be uninitialized, hence a lot of calls regarding locations fail.

To get around this, try moving all your code to OnEnter of starting area (and again, make it run a second later).

EDIT: We had a thread that discussed similar issue. It may be a helpful read.

1 Like

Okay, I got it to work but not because of the DelayCommand (although I kept the DelayCommand there just in case). What made it work is putting it right after the void main, whereas last time I put it right before the last curly brackets.

For the record I’m also adding the full OnModuleLoad script, the last two Launch_EcoSystem commands in the following script don’t work, only the first one does.

Thanks a bunch, even just consulting with you is helpful/inspirational for finding solutions! :slight_smile:

// HCR v3.03b - added reworked DoA Gold Encumberance - CFX

// HCR v3.2.0 -
//::////////////////////////////////////////////////////////////////////////////
//:: FileName:  HC_On_Mod_Load
//::////////////////////////////////////////////////////////////////////////////
/*

*/
//::////////////////////////////////////////////////////////////////////////////
#include "HC_Inc"
#include "HC_Inc_On_Load"
#include "HC_Inc_HTF"
#include "X2_Inc_Switches"
#include "eco_launch"
//::////////////////////////////////////////////////////////////////////////////
void main()
{
    DelayCommand(5.0, Launch_EcoSystem());  //Works
    if (!preEvent())
        return;

    // Bioware Module Switches.
    if (GetGameDifficulty() >= GAME_DIFFICULTY_CORE_RULES)
    {
        // * Setting the switch below will enable a seperate Use Magic Device
        // * Skillcheck for rogues. This only applies to scrolls.
        //SetModuleSwitch(MODULE_SWITCH_ENABLE_UMD_SCROLLS, TRUE);

        // * Activating the switch below will make AOE spells hurt neutral NPCS by
        // * default.
        SetModuleSwitch(MODULE_SWITCH_AOE_HURT_NEUTRAL_NPCS, TRUE);
    }

    // * AI: Activating the switch below will make the creaures using the WalkWaypoint function
    // * able to walk across areas
    SetModuleSwitch(MODULE_SWITCH_ENABLE_CROSSAREA_WALKWAYPOINTS, TRUE);

    // * Spells: Activating the switch below will make the Glyph of Warding spell behave differently:
    // * The visual glyph will disappear after 6 seconds, making them impossible to spot
    //SetModuleSwitch(MODULE_SWITCH_ENABLE_INVISIBLE_GLYPH_OF_WARDING, TRUE);

    // * Craft Feats: Want 50 charges on a newly created wand? We found this unbalancing,
    // * but since it is described this way in the book, here is the switch to get it back...
    //SetModuleSwitch(MODULE_SWITCH_ENABLE_CRAFT_WAND_50_CHARGES, TRUE);

    // * Craft Feats: Use this to disable Item Creation Feats if you do not want
    // * them in your module
    //SetModuleSwitch(MODULE_SWITCH_DISABLE_ITEM_CREATION_FEATS, TRUE);

    // * Palemaster: Deathless master touch in PnP only affects creatures up to a certain size.
    // * We do not support this check for balancing reasons, but you can still activate it...
    //SetModuleSwitch(MODULE_SWITCH_SPELL_CORERULES_DMASTERTOUCH, TRUE);

    // * Epic Spellcasting: Some Epic spells feed on the liveforce of the caster. However this
    // * did not fit into NWNs spell system and was confusing, so we took it out...
    //SetModuleSwitch(MODULE_SWITCH_EPIC_SPELLS_HURT_CASTER, TRUE);

    // *
    //SetModuleSwitch(MODULE_SWITCH_RESTRICT_USE_POISON_TO_FEAT, TRUE);

    // * Spellcasting: Some people don't like caster's abusing expertise to raise their AC
    // * Uncommenting this line will drop expertise mode whenever a spell is cast by a player
    //SetModuleSwitch(MODULE_VAR_AI_STOP_EXPERTISE_ABUSE, TRUE);

    // * SpellScript: This is the name of the spell router script.
    SetModuleOverrideSpellscript("hc_spell_router");

    // Execute the default script and set the HTF area variables.
    ExecuteScript("hc_defaults", oMod);
    ExecuteScript("hc_setareavars", oMod);

    // Store the starting year, month, day and hour.
    if (!GetPersistentInt(oMod, "HourStart"))
        SetPersistentInt(oMod, "HourStart", GetTimeHour());
    if (!GetPersistentInt(oMod, "DayStart"))
        SetPersistentInt(oMod, "DayStart", GetCalendarDay());
    if (!GetPersistentInt(oMod, "MonthStart"))
        SetPersistentInt(oMod, "MonthStart", GetCalendarMonth());
    if (!GetPersistentInt(oMod, "YearStart"))
        SetPersistentInt(oMod, "YearStart", GetCalendarYear());

    // Restore the calendar if one was saved.
    int iCurYear = GetPersistentInt(oMod, "CurrentYear");
    if (iCurYear > 0)
    {
        int iCurMonth = GetPersistentInt(oMod, "CurrentMonth");
        int iCurDay   = GetPersistentInt(oMod, "CurrentDay");
        int iCurHour  = GetPersistentInt(oMod, "CurrentHour");
        int iCurMin   = GetPersistentInt(oMod, "CurrentMin");
        SetCalendar(iCurYear, iCurMonth, iCurDay);
        SetTime(iCurHour, iCurMin, 0, 0);
    }

    //added for reworked DoA Gold Encumberance - CFX
    {
    object oItem = GetModuleItemLost();
    if (!GetIsObjectValid(oItem)) return;
    object oPC = GetModuleItemLostBy();
    if (!GetIsPC(oPC)) return;
    string sItemResRef = GetResRef(oItem);

    /*  DOA Gold Encumbrance System 1.0
    + will only fire if there is not already gold in container */
    if (sItemResRef == "nw_it_gold001") ExecuteScript("doa_goldencum", oPC);
    }
    DelayCommand(5.0, Launch_EcoSystem()); //Doesn't work

    postEvent();

    DelayCommand(5.0, Launch_EcoSystem()); //Doesn't work



}
//::////////////////////////////////////////////////////////////////////////////
	//added for reworked DoA Gold Encumberance - CFX
	{
		object oItem = GetModuleItemLost();
		if (!GetIsObjectValid(oItem)) return;
		object oPC = GetModuleItemLostBy();
		if (!GetIsPC(oPC)) return;
		string sItemResRef = GetResRef(oItem);

		/*  DOA Gold Encumbrance System 1.0
		+ will only fire if there is not already gold in container */
		if (sItemResRef == "nw_it_gold001") ExecuteScript("doa_goldencum", oPC);
	}

It didn’t work cause of this block of code. Remove it competely, it’s not the right place for it. GetModuleItemLostBy() and GetModuleItemLost() are a part of the module OnUnAcquireItem event, not the module OnLoad one. These functions return invalid objects here, so the return statement ends the execution of your script prematurely.

I use loop all areas in OnModuleLoad and it works fine

I didn’t write that part of the code. I believe it’s from HCR 3.4 from nwvault, it’s the only thing that I imported that could’ve changed the OnModuleLoad event.

But yea, that darn return statement. Thank you for helping me see that!

In hindsight, the problem in that thread was related to PC’s location. Accessing non-PC data from OnModuleLoad or OnClientEnter seems to work fine indeed.