Files
PRC8/nwn/nwnprc/trunk/scripts/prc_onmodload.nss
Jaysyn904 4026b6af2c 2026/02/08 Update
Archived Spellman's Project content.
Added missing Diamond Dragon stat feats.
Hospitaler's should be able to take Extra Turning.
Dodge proxies should allow entry into Champion of Corellon.
Mounted Combat is a prereq for Champion of Corellon.
Only Clerics have Domain reqs to enter Morninglord.
Verdant Lord was missing BAB 4 entry requirement.
Diamond Dragons don't get spellcraft.
Re-added Korobokuru race.
Added .ltr tables for Korobokuru.
Capped Blood in the Water at +20.
Capped Pearl of Black Doubt at +20.
Added json_GetFirstKnownSpell() and json_GetNextKnownSpell().
Updated all old NWNx functions to work with NWNxEE.
Added new switch to enable optional PRCX / NWNxEE shims.
Commented out ConvoCC switches on inc_switch_setup.nss
Diamond Dragon's stat increases are intrinsic when using NWNxEE.
Forsaker's stat increases are intrinsic when using NWNxEE.
Vow of Poverty's stat increases are intrinsic when using NWNxEE.
Cloud Dragon summon should be Neutral Good.
Fixed Verdant Lord's regen.
Fixed Forest Master's regen.
Morninglord's Creative Fire should affect Alchemy.
Added yes/no dialog when choosing Vow of Poverty bonus Exalted Feats.
Racial natural AC should be intrinsic when NWNxEE is enabled.
Transcendent Vitality's CON bonus is intrinsic when NWNxEE is enabled.
2026-02-08 00:44:28 -05:00

330 lines
12 KiB
Plaintext

//::///////////////////////////////////////////////
//:: PRC On Module Load event handler
//:: prc_onmodload
//::///////////////////////////////////////////////
/** @file prc_onmodload
Things we need to happen upon a module being
loaded. For example, setting up caches and
switches.
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_alterations"
#include "prc_inc_leadersh"
#include "inc_switch_setup"
#include "inc_cache_setup"
#include "inc_sql"
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
void OnLoad_Always(object oModule);
void OnLoad_Save(object oModule);
void OnLoad_Fresh(object oModule);
void PersonalSwitch(object oModule);
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
void CheckDB()
{
string sDBName = GetBiowareDBName();
//check PRC version
if(GetCampaignString(sDBName, "version") != PRC_VERSION)
{
DoDebug("Removing old PRC version databases");
DestroyCampaignDatabase(sDBName);
DestroyCampaignDatabase(COHORT_DATABASE);
}
SetCampaignString(sDBName, "version", PRC_VERSION);
// 2da cache fingerprint handling
// This is for detecting a cache updated by someone else upon loading a saved game
// and avoiding clobbering it.
string sFingerprint;
// Generate the fingerprint from module name, current millisecond value and
// 31-bit random number.
sFingerprint = GetModuleName() + "_" + IntToString(GetTimeMillisecond()) + "_" + IntToString(Random(0x7fffffff));
DoDebug("Module 2da cache fingerprint: " + sFingerprint);
// Store the fingerprint on the module - it will be written to the DB upon cache storage
SetLocalString(GetModule(), "PRC_2DA_Cache_Fingerprint", sFingerprint);
// Also store the fingerprint of the DB we will be loading shortly
SetLocalString(GetModule(), "PRC_2DA_Cache_Fingerprint_LastAccessed", GetCampaignString(sDBName, "PRC_2DA_Cache_Fingerprint"));
location lLoc = GetLocation(GetObjectByTag("HEARTOFCHAOS"));
// only get it if one doesnt already exist (saved games)
// This never gets run on saved games due to the "prc_mod_load_done" check.
// However, it is still usefull cleanup in case some unforseen condition does
// leave a cache object present in a freshly loaded module - Ornedan 20061229
if(GetIsObjectValid(GetObjectByTag("Bioware2DACache")))
DestroyObject(GetObjectByTag("Bioware2DACache"));
DoDebug("Starting to load 2da cache object from " + sDBName);
object oChest = RetrieveCampaignObject(sDBName, "CacheChest", lLoc);
if(!GetIsObjectValid(oChest))
{
DoDebug("WARNING: Unable to load 2da cache object (CacheChest) from " + sDBName);
oChest = CreateObject(OBJECT_TYPE_CREATURE, "prc_2da_cache", lLoc, FALSE, "Bioware2DACache");
}
else
{
DoDebug("Finished loading 2da cache object from " + sDBName);
}
//DB is ready run 2da lookup stuff
DelayCommand(0.1f, RunLookupLoop());
}
/**
* Called when a saved game load is detected. Determines if the
* 2da cache DB has changed in the meanwhile. If it has, reload the
* cache creature from the DB.
*/
void CheckDBUpdate()
{
// Get last loaded (or saved) and DB fingerprints
string sDBName = GetBiowareDBName();
string sModuleFingerprint = GetLocalString(GetModule(), "PRC_2DA_Cache_Fingerprint_LastAccessed");
string sDBFingerprint = GetCampaignString(sDBName, "PRC_2DA_Cache_Fingerprint");
DoDebug("CheckDBUpdate():\n"
+ " Module last access fingerprint: " + sModuleFingerprint + "\n"
+ " Database fingerprint: " + sDBFingerprint
);
// If they differ, the DB has changed in meanwhile and we need to reload the cache chest
if(sModuleFingerprint != sDBFingerprint)
{
DoDebug("Fingerprint mismatch, reloading 2da cache from " + sDBName);
location lLoc = GetLocation(GetObjectByTag("HEARTOFCHAOS"));
DestroyObject(GetObjectByTag("Bioware2DACache"));
DoDebug("Starting to load 2da cache object from " + sDBName);
object oChest = RetrieveCampaignObject(sDBName, "CacheChest", lLoc);
if(!GetIsObjectValid(oChest))
DoDebug("ERROR: Unable to load 2da cache object (CacheChest) from " + sDBName);
else
{
DoDebug("Finished loading 2da cache object from " + sDBName);
//DB is ready run 2da lookup stuff
DelayCommand(0.1f, RunLookupLoop());
}
// Updated last access fingerprint
SetLocalString(GetModule(), "PRC_2DA_Cache_Fingerprint_LastAccessed", sDBFingerprint);
}
}
void CheckXPSwitches(object oModule)
{
if(!GetLocalInt(oModule, PRC_XP_PC_PARTY_COUNT_x100))//player will get 0 xp for kills - we assume that the XP system was not setup
{
SetLocalInt(oModule, PRC_XP_SLIDER_x100, 100);
SetLocalInt(oModule, PRC_XP_GROUP_BONUS, 10);
SetLocalInt(oModule, PRC_XP_PC_PARTY_COUNT_x100, 100);
SetLocalInt(oModule, PRC_XP_DOMINATED_PARTY_COUNT_x100, 0);
SetLocalInt(oModule, PRC_XP_HENCHMAN_PARTY_COUNT_x100, 50);
SetLocalInt(oModule, PRC_XP_UNKNOWN_PARTY_COUNT_x100, 0);
SetLocalInt(oModule, PRC_XP_SUMMONED_PARTY_COUNT_x100, 0);
SetLocalInt(oModule, PRC_XP_FAMILIAR_PARTY_COUNT_x100, 0);
SetLocalInt(oModule, PRC_XP_ANIMALCOMPANION_PARTY_COUNT_x100, 0);
SetLocalInt(oModule, PRC_XP_MUST_BE_IN_AREA, 1);
SetLocalInt(oModule, PRC_XP_MAX_PHYSICAL_DISTANCE, 100);
}
//
if(!GetLocalInt(oModule, PRC_XP_MAX_LEVEL_DIFF))
SetLocalInt(oModule, PRC_XP_MAX_LEVEL_DIFF, 5);
}
void main()
{
object oModule = GetModule();
PersonalSwitch(oModule);
SetAbilityBonusLimit(50);
OnLoad_Always(oModule);
// Determine if we are loading a saved game or entering a fresh module
// Some things should only be run in one situation or the other.
if(GetLocalInt(oModule, "prc_mod_load_done"))
{
OnLoad_Save(oModule);
}
else
{
SetLocalInt(oModule, "prc_mod_load_done", TRUE);
OnLoad_Fresh(oModule);
}
//:: NWNxEE Detection
int bNWNxEE = NWNXGetIsAvailable();
if (bNWNxEE)
{
SetPRCSwitch(PRC_NWNXEE_ENABLED, TRUE);
if(DEBUG) DoDebug("NWNxEE detected.");
}
//NWNX_Funcs plugin test:
//PRC_Funcs_Init(oModule);
}
/**
* Things that should always be run on loading a module,
* irrespective of whether it's a fresh load or a save.
*/
void OnLoad_Always(object oModule)
{
//this triggers NWNX on Linux
//SetLocalInt(oModule, "NWNX!INIT", 1);
//SetLocalString(oModule, "NWNX!INIT", "1");
}
/**
* Things that should be run only when a saved game is loaded.
*/
void OnLoad_Save(object oModule)
{
CheckDBUpdate();
}
/**
* Things that should only be run when a module is first loaded.
*/
void OnLoad_Fresh(object oModule)
{
// Set PRC presence & version marker. If plugins ever happen, this would be useful.
SetLocalString(oModule, "PRC_VERSION", PRC_VERSION);
SetModuleSwitch(MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS, TRUE); /// @todo This is somewhat intrusive, make it unnecessary and remove
// Run a script to determine if the PRC Companion is present
//ExecuteScript("hakmarker", OBJECT_SELF); //:: script no longer present in project - Jaysyn
//delay this to avoid TMIs
DelayCommand(0.01, CreateSwitchNameArray());
DelayCommand(0.01, DoEpicSpellDefaults());
DelayCommand(0.01, DoSamuraiBanDefaults());
SetDefaultFileEnds();
if(GetPRCSwitch(PRC_CONVOCC_ENABLE))
{
SetPRCSwitch(PRC_USE_DATABASE, TRUE);
//SetPRCSwitch(PRC_DB_PRECACHE, TRUE);
SetPRCSwitch(PRC_USE_LETOSCRIPT, TRUE);
// set up the convoCC combination switches
if(GetPRCSwitch(PRC_CONVOCC_ENFORCE_FEATS))
{
SetPRCSwitch(PRC_CONVOCC_ENFORCE_BLOOD_OF_THE_WARLORD, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_NIMBUSLIGHT, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_HOLYRADIANCE, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_SERVHEAVEN, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_SAC_VOW, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_VOW_OBED, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_THRALL_TO_DEMON, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_DISCIPLE_OF_DARKNESS, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_LICHLOVED, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_EVIL_BRANDS, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_VILE_WILL_DEFORM, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_VILE_DEFORM_OBESE, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_VILE_DEFORM_GAUNT, TRUE);
SetPRCSwitch(PRC_CONVOCC_ENFORCE_FEAT_LOLTHS_MEAT, TRUE);
}
if(GetPRCSwitch(PRC_CONVOCC_ENFORCE_PNP_RACIAL))
{
SetPRCSwitch(PRC_CONVOCC_RAKSHASA_FEMALE_APPEARANCE, TRUE);
SetPRCSwitch(PRC_CONVOCC_GENASI_ENFORCE_DOMAINS, TRUE);
SetPRCSwitch(PRC_CONVOCC_DROW_ENFORCE_GENDER, TRUE);
SetPRCSwitch(PRC_CONVOCC_TIEFLING_TAIL, TRUE);
SetPRCSwitch(PRC_CONVOCC_FEYRI_TAIL, TRUE);
SetPRCSwitch(PRC_CONVOCC_FEYRI_WINGS, TRUE);
SetPRCSwitch(PRC_CONVOCC_AVARIEL_WINGS, TRUE);
}
}
if(GetPRCSwitch(PRC_USE_BIOWARE_DATABASE) == 0)
SetPRCSwitch(PRC_USE_BIOWARE_DATABASE, 300);//100 HBs = 1800sec = 30min
if(GetPRCSwitch(PRC_USE_BIOWARE_DATABASE))
DelayCommand(0.1, CheckDB());
if(GetPRCSwitch(PRC_USE_DATABASE))
{
PRC_SQLInit();
if(GetPRCSwitch(PRC_DB_SQLITE))
{
StartSQLiteCommitHB();
CreateXChestDB_SQLite();
}
else if(GetPRCSwitch(PRC_DB_MYSQL))
CreateXChestDB_MySQL();
}
if(GetPRCSwitch(PRC_DB_PRECACHE))
Cache_2da_data();
// Disable Bioware XP as it's being handled by PRC
if(GetPRCSwitch(PRC_XP_USE_PNP_XP))
{
SetModuleXPScale(0);
DelayCommand(5.0f, CheckXPSwitches(oModule));
}
//pre-made cohorts
//DelayCommand(6.0, AddPremadeCohortsToDB());
//done differently now
//check for letoscript dir
/* if(GetLocalString(oModule, PRC_LETOSCRIPT_NWN_DIR) == "")
{
string sDir = Get2DACache("directory", "Dir", 0);
if(sDir != "")
SetLocalString(oModule, PRC_LETOSCRIPT_NWN_DIR, sDir);
} */
//mark server as loading
float fDelay = IntToFloat(GetPRCSwitch(PRC_PW_LOGON_DELAY))*60.0;
if(fDelay>0.0)
{
SetLocalInt(GetModule(), PRC_PW_LOGON_DELAY+"_TIMER", TRUE);
DelayCommand(fDelay, DeleteLocalInt(GetModule(), PRC_PW_LOGON_DELAY+"_TIMER"));
}
}
void PersonalSwitch(object oModule)
{
DoDebug("PersonalSwitch Running");
//load any default switch 2da
int i = 0;
string sSwitchName, sSwitchType, sSwitchValue;
// Use Get2DAString() instead of Get2DACache() to avoid caching.
// People might want to set different switch values when playing in different modules.
// Or just change the switch values midplay.
sSwitchName = Get2DAString("personal_switch", "SwitchName", i);
while(sSwitchName != "") // Brute force
{
DoDebug("SwitchName: "+sSwitchName);
// Read rest of the line
sSwitchType = Get2DAString("personal_switch", "SwitchType", i);
sSwitchValue = Get2DAString("personal_switch", "SwitchValue", i);
DoDebug("SwitchType: "+sSwitchType);
DoDebug("SwitchValue: "+sSwitchValue);
// Determine switch type and set the var
if (sSwitchType == "float")
SetLocalFloat(oModule, sSwitchName, StringToFloat(sSwitchValue));
else if(sSwitchType == "int")
SetPRCSwitch(sSwitchName, StringToInt(sSwitchValue));
else if(sSwitchType == "string")
SetLocalString(oModule, sSwitchName, sSwitchValue);
// Increment loop counter
i += 1;
sSwitchName = Get2DAString("personal_switch", "SwitchName", i);
}
}