Update for NWN .35

Update for NWN .35
This commit is contained in:
Jaysyn904
2023-08-01 20:16:07 -04:00
parent d4680a7df3
commit 1ddbeca4f1
1526 changed files with 68311 additions and 2534 deletions

BIN
_haks/poa_dev/default.ncs Normal file

Binary file not shown.

417
_haks/poa_dev/default.nss Normal file
View File

@@ -0,0 +1,417 @@
//::///////////////////////////////////////////////
//:: Default eventscript
//:: default
//:://////////////////////////////////////////////
/** @file
This script is executed by the engine for events
when a creature does not have a script defined
for the event in question. This includes PCs.
The purpose of this script is to determine
which particular event triggered it's execution
and to route execution to scripts dedicated to
that event.
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_alterations"
#include "prc_inc_leadersh"
const int LOCAL_DEBUG = FALSE; //DEBUG;
/**************************/
/* Declarations for Tests */
/**************************/
int IsBlocked(); // test GetBlockingDoor()
int IsCombatRoundEnd(); // Need to fake this
int IsConversation(); // test a local variable
int IsDamaged(); // test GetLastDamager()
int IsDeath(); // test GetIsDead(OBJECT_SELF)
int IsDisturbed(); // test GetLastDisturbed()
int IsHeartbeat(); // test game time
int IsPerception(); // test GetLastPerceived()
int IsPhysicalAttacked(); // test GetLastAttacker()
int IsRested(); // test GetIsResting(GetMaster())
int IsSpawn(); // run once, never again
int IsSpellCastAt(); // test GetLastSpellCaster()
int IsUserDefined(); // test GetUserDefinedEventNumber()
/*********************************/
/* Utility Function declarations */
/*********************************/
//void ForceAddHenchman(object oHenchman);
//int IsLinkboyAttached();
//void GetLinkboy();
int IsObjectChanged(object oTest, string sVarname);
int IsIntChanged(int iTest, string sVarname);
int IsStringChanged(string sTest, string sVarname);
void RunScript(int nEvent);
//void SpawnRecallLocals(object oPC);
//void StartGroupDiscussion();
/*****************************/
/* Implementation of Actions */
/*****************************/
void OnSpawn() { RunScript(EVENT_VIRTUAL_ONSPAWNED); }
void OnDeath() { RunScript(EVENT_VIRTUAL_ONDEATH); }
void OnRested() { RunScript(EVENT_VIRTUAL_ONRESTED); }
void OnHeartbeat() { RunScript(EVENT_VIRTUAL_ONHEARTBEAT); }
void OnPerception() { RunScript(EVENT_VIRTUAL_ONPERCEPTION); }
void OnBlocked() { RunScript(EVENT_VIRTUAL_ONBLOCKED); }
void OnCombatRoundEnd() { RunScript(EVENT_VIRTUAL_ONCOMBATROUNDEND); }
void OnDisturbed() { RunScript(EVENT_VIRTUAL_ONDISTURBED); }
void OnPhysicalAttacked() { RunScript(EVENT_VIRTUAL_ONPHYSICALATTACKED); }
void OnSpellCastAt() { RunScript(EVENT_VIRTUAL_ONSPELLCASTAT); }
void OnDamaged() { RunScript(EVENT_VIRTUAL_ONDAMAGED); }
void OnUserDefined() { RunScript(EVENT_VIRTUAL_ONUSERDEFINED); }
void OnConversation() { RunScript(EVENT_VIRTUAL_ONCONVERSATION); }
/******************/
/* Main Procedure */
/******************/
void main()
{
if(LOCAL_DEBUG) DoDebug("default running for " + DebugObject2Str(OBJECT_SELF));
// OnConversation is exclusive of everything else, since it is just routed through this script
if(IsConversation()) OnConversation();
else
{
if(IsBlocked()) OnBlocked();
if(IsCombatRoundEnd()) OnCombatRoundEnd();
if(IsDamaged()) OnDamaged();
if(IsDeath()) OnDeath();
if(IsDisturbed()) OnDisturbed();
if(IsHeartbeat()) OnHeartbeat();
if(IsPerception()) OnPerception();
if(IsPhysicalAttacked()) OnPhysicalAttacked();
if(IsRested()) OnRested();
if(IsSpawn()) OnSpawn();
if(IsSpellCastAt()) OnSpellCastAt();
if(IsUserDefined()) OnUserDefined();
}
}
/************************/
/* Tests for conditions */
/************************/
int IsBlocked()
{
return IsObjectChanged(GetBlockingDoor(), "BlockingDoor");
}
int IsCombatRoundEnd()
{
// Need to fake this.
// Return TRUE iff you are in combat and not doing anything useful
if(GetIsInCombat() ||
(GetIsObjectValid(GetMaster()) &&
GetIsInCombat(GetMaster())
)
)
{
int nGCA = GetCurrentAction();
if(nGCA == ACTION_ATTACKOBJECT ||
nGCA == ACTION_CASTSPELL ||
nGCA == ACTION_COUNTERSPELL ||
nGCA == ACTION_HEAL ||
nGCA == ACTION_FOLLOW ||
nGCA == ACTION_ITEMCASTSPELL ||
nGCA == ACTION_KIDAMAGE ||
nGCA == ACTION_OPENDOOR ||
nGCA == ACTION_SMITEGOOD
)
{
return FALSE;
}
else
{
return TRUE;
}
}
else
{
return FALSE;
}
}
int IsConversation()
{
object oCreature = OBJECT_SELF;
if(GetLocalInt(oCreature, "default_conversation_event"))
{
DeleteLocalInt(oCreature, "default_conversation_event");
return TRUE;
}
return FALSE;
}
int IsDamaged()
{
object oCreature = OBJECT_SELF;
object oDamager = GetLastDamager(oCreature);
// The damage source must be valid
if(GetIsObjectValid(oDamager))
{
// Get previous damage data
string sOldDamage = GetLocalString(oCreature, "PRC_Event_OnDamaged_Data");
// Create string based on current damage values
// Start with the damaging object
string sNewDamage = ObjectToString(oDamager);
// Catenate amount of damage of each damage type
int i;
for(i = DAMAGE_TYPE_BLUDGEONING; i <= DAMAGE_TYPE_BASE_WEAPON; i = i << 1)
sNewDamage += IntToString(GetDamageDealtByType(i));
// Determine if the damage dealt has changed
if(sOldDamage != sNewDamage)
{
if(LOCAL_DEBUG) DoDebug("default: Damage has changed:\n" + sNewDamage);
SetLocalString(oCreature, "PRC_Event_OnDamaged_Data", sNewDamage);
// Update damage counter
SetLocalInt(oCreature, "PRC_LastDamageTaken", GetTotalDamageDealt());
return TRUE;
}
}
return FALSE;
}
int IsDeath()
{
return GetIsDead(OBJECT_SELF);
}
int IsDisturbed()
{
object oCreature = OBJECT_SELF;
object oDisturber = GetLastDisturbed();
if(GetIsObjectValid(oDisturber)) // The creature has been disturbed at least once during the game
{
// Get previous disturb data
string sOldDisturb = GetLocalString(oCreature, "PRC_Event_OnDisturbed_Data");
// Create string based on current disturb values
string sNewDisturb = ObjectToString(oDisturber);
sNewDisturb += IntToString(GetInventoryDisturbType());
sNewDisturb += ObjectToString(GetInventoryDisturbItem());
// Determine if the data has changed
if(sOldDisturb != sNewDisturb)
{
if(LOCAL_DEBUG) DoDebug("default: Disturbed has changed:\n" + sNewDisturb);
SetLocalString(oCreature, "PRC_Event_OnDisturbed_Data", sNewDisturb);
return TRUE;
}
}
return FALSE;
}
int IsHeartbeat()
{
object oCreature = OBJECT_SELF;
// PCs use the module HB
if(!GetIsPC(oCreature))
{
// Check how long since last recorded heartbeat
int nSecsChange = (GetTimeSecond() - GetLocalInt(oCreature, "PRC_LastHeartbeatSeconds") + 60) % 60;
// See if the master clock has ticked or 9 seconds have elapsed anyway
if(nSecsChange >= 6)
{
SetLocalInt(oCreature, "PRC_LastHeartbeatSeconds", GetTimeSecond());
return TRUE;
}
}
return FALSE;
}
int IsPerception()
{
object oCreature = OBJECT_SELF;
object oPerceived = GetLastPerceived();
if(GetIsObjectValid(oPerceived)) // The creature has perceived something at least once during the game
{
// Get previous perception data
string sOldPerception = GetLocalString(oCreature, "PRC_Event_OnPerception_Data");
// Create string based on current perception values
string sNewPerception = ObjectToString(oPerceived);
sNewPerception += IntToString(GetLastPerceptionHeard());
sNewPerception += IntToString(GetLastPerceptionInaudible());
sNewPerception += IntToString(GetLastPerceptionSeen());
sNewPerception += IntToString(GetLastPerceptionVanished());;
// Determine if the data has changed
if(sOldPerception != sNewPerception)
{
if(LOCAL_DEBUG) DoDebug("default: Perception has changed:\n" + sNewPerception);
SetLocalString(oCreature, "PRC_Event_OnPerception_Data", sNewPerception);
return TRUE;
}
}
return FALSE;
}
int IsPhysicalAttacked()
{
object oCreature = OBJECT_SELF;
object oAttacker = GetLastAttacker();
// Recent enough event that the attacker is at least still valid
if(GetIsObjectValid(oAttacker))
{
// Get previous attack data
string sOldAttack = GetLocalString(oCreature, "PRC_Event_OnPhysicalAttacked_Data");
// Create string for the current attack data
string sNewAttack = ObjectToString(oAttacker);
sNewAttack += ObjectToString(GetLastWeaponUsed(oAttacker));
sNewAttack += IntToString(GetLastAttackMode(oAttacker));
sNewAttack += IntToString(GetLastAttackType(oAttacker));
// Determine if the data has changed
if(sOldAttack != sNewAttack)
{
if(LOCAL_DEBUG) DoDebug("default: Attack has changed:\n" + sNewAttack);
SetLocalString(oCreature, "PRC_Event_OnPhysicalAttacked_Data", sNewAttack);
return TRUE;
}
}
return FALSE;
}
int IsRested()
{
// PCs use the module OnRest events
if(!GetIsPC(OBJECT_SELF))
{
// Goes TRUE when Master starts resting
int bMasterIsResting = GetIsResting(GetMaster());
return IsIntChanged(bMasterIsResting,"MasterIsResting") && bMasterIsResting;
}
return FALSE;
}
int IsSpawn()
{
object oCreature = OBJECT_SELF;
if(!GetLocalInt(oCreature, "PRC_OnSpawn_Marker"))
{
SetLocalInt(oCreature, "PRC_OnSpawn_Marker", TRUE);
return TRUE;
}
return FALSE;
}
int IsSpellCastAt()
{
object oCreature = OBJECT_SELF;
if(LOCAL_DEBUG) DoDebug("default: IsSpellCastAt():\n"
+ "GetLastSpellCaster() = " + DebugObject2Str(GetLastSpellCaster()) + "\n"
+ "GetLastSpell() = " + IntToString(GetLastSpell()) + "\n"
+ "GetLastSpellHarmful() = " + IntToString(GetLastSpellHarmful()) + "\n"
);
// If the event data does not contain the fake value, a spell has been cast
if(GetLastSpell() != -1)
{
// Reset the event data to the fake value
DelayCommand(0.0f, SignalEvent(oCreature, EventSpellCastAt(oCreature, -1, FALSE)));
return TRUE;
}
return FALSE;
}
int IsUserDefined()
{
object oCreature = OBJECT_SELF;
if(LOCAL_DEBUG) DoDebug("default: IsUserDefined():\n"
+ "GetUserDefinedEventNumber() = " + IntToString(GetUserDefinedEventNumber()) + "\n"
);
if(GetUserDefinedEventNumber() != -1)
{
// Reset the event data to the fake value
DelayCommand(0.0f, SignalEvent(oCreature, EventUserDefined(-1)));
return TRUE;
}
return FALSE;
}
/*********************/
/* Utility Functions */
/*********************/
int IsObjectChanged(object oTest, string sName)
{
if(oTest != GetLocalObject(OBJECT_SELF, "PRC_Event_" + sName))
{
SetLocalObject(OBJECT_SELF, "PRC_Event_" + sName, oTest);
return TRUE;
}
else
{
return FALSE;
}
}
int IsIntChanged(int iTest, string sName)
{
if(iTest != GetLocalInt(OBJECT_SELF, "PRC_Event_" + sName))
{
SetLocalInt(OBJECT_SELF, "PRC_Event_" + sName, iTest);
return TRUE;
}
else
{
return FALSE;
}
}
int IsStringChanged(string sTest, string sName)
{
if(sTest != GetLocalString(OBJECT_SELF, "PRC_Event_" + sName))
{
SetLocalString(OBJECT_SELF, "PRC_Event_" + sName, sTest);
return TRUE;
}
else
{
return FALSE;
}
}
void RunScript(int nEvent)
{
object oSelf = OBJECT_SELF;
if(LOCAL_DEBUG) DoDebug("default, event = " + IntToString(nEvent));
if(nEvent == EVENT_VIRTUAL_ONDAMAGED)
SignalEvent(oSelf, EventUserDefined(EVENT_DAMAGED));
// Determine NPC script name and run generic eventhook
ExecuteAllScriptsHookedToEvent(oSelf, nEvent);
}

371
_haks/poa_dev/inc_ecl.nss Normal file
View File

@@ -0,0 +1,371 @@
/** @file
* ECL handling.
*
* @author Primogenitor
*
* @todo Primo, could you document this one? More details to header and comment function prototypes
*/
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
// returns oTarget's LA value, including their race and template(s) LA
int GetTotalLA(object oTarget);
// returns oTarget's level adjusted by their LA
int GetECL(object oTarget);
void GiveXPReward(object oCreature, int nXP, int bIsPC = TRUE);
void GiveXPRewardToParty(object oKiller, object oDead, int nCR = 0);
//////////////////////////////////////////////////
/* Include section */
//////////////////////////////////////////////////
//#include "inc_utility"
//#include "prc_inc_template"
#include "inc_npc"
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
int GetTotalLA(object oTarget)
{
int nLA;
int nRace = GetRacialType(oTarget);
if(GetPRCSwitch(PRC_XP_USE_SIMPLE_LA))
nLA += StringToInt(Get2DACache("ECL", "LA", nRace));
if(GetPRCSwitch(PRC_XP_INCLUDE_RACIAL_HIT_DIE_IN_LA))
nLA += StringToInt(Get2DACache("ECL", "RaceHD", nRace));
nLA += GetPersistantLocalInt(oTarget, "template_LA");
nLA -= GetPersistantLocalInt(oTarget, "LA_Buyoff");
return nLA;
}
int GetECL(object oTarget)
{
int nLevel;
// we need to use a derivation of the base xp formular to compute the
// pc level based on total XP.
//
// base XP formula (x = pc level, t = total xp):
//
// t = x * (x-1) * 500
//
// need to use some base math..
// transform for pq formula use (remove brackets with x inside and zero right side)
//
// x^2 - x - (t / 500) = 0
//
// use pq formula to solve it [ x^2 + px + q = 0, p = -1, q = -(t/500) ]...
//
// that's our new formula to get the level based on total xp:
// level = 0.5 + sqrt(0.25 + (t/500))
//
if(GetPRCSwitch(PRC_ECL_USES_XP_NOT_HD) && GetIsPC(oTarget))
nLevel = FloatToInt(0.5 + sqrt(0.25 + ( IntToFloat(GetXP(oTarget)) / 500 )));
else
nLevel = GetHitDice(oTarget);
nLevel += GetTotalLA(oTarget);
return nLevel;
}
int CheckDistance(object oDead, object oTest)
{
if(GetPRCSwitch(PRC_XP_MUST_BE_IN_AREA))
{
if(GetArea(oDead) != GetArea(oTest))
return FALSE;
if(GetDistanceBetween(oDead, oTest) > IntToFloat(GetPRCSwitch(PRC_XP_MAX_PHYSICAL_DISTANCE)))
return FALSE;
}
return TRUE;
}
float GetGroupBonusModifier(int nPartySize)
{
return 1 + ((nPartySize-1) * IntToFloat(GetPRCSwitch(PRC_XP_GROUP_BONUS))/100.0);
}
void GiveXPRewardToParty(object oKiller, object oDead, int nCR = 0)
{
//get prc switches
int bSPAM = GetPRCSwitch(PRC_XP_DISABLE_SPAM);
float fPRC_XP_DIVISOR_PC = IntToFloat(GetPRCSwitch(PRC_XP_PC_PARTY_COUNT_x100))/100.0;
float fPRC_XP_DIVISOR_HENCHMAN = IntToFloat(GetPRCSwitch(PRC_XP_HENCHMAN_PARTY_COUNT_x100))/100.0;
float fPRC_XP_DIVISOR_ANIMALCOMPANION = IntToFloat(GetPRCSwitch(PRC_XP_ANIMALCOMPANION_PARTY_COUNT_x100))/100.0;
float fPRC_XP_DIVISOR_FAMILIAR = IntToFloat(GetPRCSwitch(PRC_XP_FAMILIAR_PARTY_COUNT_x100))/100.0;
float fPRC_XP_DIVISOR_DOMINATED = IntToFloat(GetPRCSwitch(PRC_XP_DOMINATED_PARTY_COUNT_x100))/100.0;
float fPRC_XP_DIVISOR_SUMMONED = IntToFloat(GetPRCSwitch(PRC_XP_SUMMONED_PARTY_COUNT_x100))/100.0;
float fPRC_XP_DIVISOR_UNKNOWN = IntToFloat(GetPRCSwitch(PRC_XP_UNKNOWN_PARTY_COUNT_x100))/100.0;
//number of PCs in the party, average party level
int nPartySize, nAvgLevel;
//xp divisor
float fDivisor;
//get some basic group data like average PC level , PC group size, and XP divisor
object oTest = GetFirstFactionMember(oKiller, FALSE);
while(GetIsObjectValid(oTest))
{
if(CheckDistance(oDead, oTest))
{
if(GetIsPC(oTest))
{
nPartySize++;
nAvgLevel += GetECL(oTest);
fDivisor += fPRC_XP_DIVISOR_PC;
}
else
{
switch(GetAssociateTypeNPC(oTest))
{
case ASSOCIATE_TYPE_HENCHMAN: fDivisor += fPRC_XP_DIVISOR_HENCHMAN; break;
case ASSOCIATE_TYPE_ANIMALCOMPANION: fDivisor += fPRC_XP_DIVISOR_ANIMALCOMPANION; break;
case ASSOCIATE_TYPE_FAMILIAR: fDivisor += fPRC_XP_DIVISOR_FAMILIAR; break;
case ASSOCIATE_TYPE_DOMINATED: fDivisor += fPRC_XP_DIVISOR_DOMINATED; break;
case ASSOCIATE_TYPE_SUMMONED: fDivisor += fPRC_XP_DIVISOR_SUMMONED; break;
default: fDivisor += fPRC_XP_DIVISOR_UNKNOWN; break;
}
}
}
else if(!bSPAM && GetIsPC(oTest))
SendMessageToPC(oTest, "You are too far away from the combat to gain any experience.");
oTest = GetNextFactionMember(oKiller, FALSE);
}
//in case something weird is happenening
if(fDivisor == 0.0f)
return;
//calculate average partylevel
nAvgLevel /= nPartySize;
int nBaseXP;
if(!nCR) nCR = GetPRCSwitch(PRC_XP_USE_ECL_NOT_CR) ? GetECL(oDead) : FloatToInt(GetChallengeRating(oDead));
if(nCR < 1) nCR = 1;
if(GetPRCSwitch(PRC_XP_USE_BIOWARE_XPTABLE))
{
if(nCR > 40) nCR = 40;
if(nAvgLevel > 40) nAvgLevel = 40;
nBaseXP = StringToInt(Get2DACache("xptable", "C"+IntToString(nCR), nAvgLevel-1));
}
else
{
if(nCR > 70) nCR = 70;
if(nAvgLevel > 60) nAvgLevel = 60;
nBaseXP = StringToInt(Get2DACache("dmgxp", IntToString(nCR), nAvgLevel-1));
}
//average xp per party member
int nXPAward = FloatToInt(IntToFloat(nBaseXP)/fDivisor);
//now the module slider
nXPAward = FloatToInt(IntToFloat(nXPAward) * IntToFloat(GetPRCSwitch(PRC_XP_SLIDER_x100))/100.0);
//xp = 0, quit
if(!nXPAward)
return;
//group bonus
nXPAward = FloatToInt(IntToFloat(nXPAward) * GetGroupBonusModifier(nPartySize));
int nKillerLevel = GetECL(oKiller);
//calculate xp for each party member individually
oTest = GetFirstFactionMember(oKiller, FALSE);
float fPCAdjust;
int nMbrLevel;
while(GetIsObjectValid(oTest))
{
if(CheckDistance(oDead, oTest))
{
if(GetIsPC(oTest))
{
nMbrLevel = GetECL(oTest);
if(abs(nMbrLevel - nKillerLevel) <= GetPRCSwitch(PRC_XP_MAX_LEVEL_DIFF))
{
//now the individual slider
fPCAdjust = IntToFloat(GetLocalInt(oTest, PRC_XP_SLIDER_x100))/100.0;
if(fPCAdjust == 0.0) fPCAdjust = 1.0;
nXPAward = FloatToInt(IntToFloat(nXPAward) * fPCAdjust);
GiveXPReward(oTest, nXPAward);
}
else if(!bSPAM)
SendMessageToPC(oTest, "You are too high level to gain any experience.");
}
else
GiveXPReward(oTest, nXPAward, FALSE);
}
oTest = GetNextFactionMember(oKiller, FALSE);
}
}
void GiveXPReward(object oCreature, int nXP, int bIsPC = TRUE)
{
//actually give the XP
if(bIsPC)
{
if(GetPRCSwitch(PRC_XP_USE_SETXP))
SetXP(oCreature, GetXP(oCreature)+nXP);
else
GiveXPToCreature(oCreature, nXP);
}
else if(GetPRCSwitch(PRC_XP_GIVE_XP_TO_NPCS))
SetLocalInt(oCreature, "NPC_XP", GetLocalInt(oCreature, "NPC_XP")+nXP);
}
//::///////////////////////////////////////////////
//:: Effective Character Level Experience Script
//:: ecl_exp
//:: Copyright (c) 2004 Theo Brinkman
//:://////////////////////////////////////////////
/*
Call ApplyECLToXP() from applicable heartbeat script(s)
to cause experience to be adjusted according to ECL.
*/
//:://////////////////////////////////////////////
//:: Created By: Theo Brinkman
//:: Last Updated On: 2004-07-28
//:://////////////////////////////////////////////
// CONSTANTS
const string sLEVEL_ADJUSTMENT = "ecl_LevelAdjustment";
const string sXP_AT_LAST_HEARTBEAT = "ecl_LastExperience";
int GetXPForLevel(int nLevel)
{
return nLevel*(nLevel-1)*500;
}
void ApplyECLToXP(object oPC)
{
//abort if simple LA is disabled
if(!GetPRCSwitch(PRC_XP_USE_SIMPLE_LA))
return;
//abort if it's not valid, still loading, or a PC
if(!GetIsObjectValid(oPC) || GetLocalInt(oPC, "PRC_ECL_Delay") || !GetIsPC(oPC))
return;
// Abort if they are registering as a cohort
if(GetLocalInt(oPC, "OriginalXP") || GetPersistantLocalInt(oPC, "RegisteringAsCohort"))
return;
// Let them make it to level 3 in peace
if(GetTag(GetModule()) == "Prelude")
return;
// And start HotU in peace
if(GetTag(GetArea(oPC)) == "q2a_yprooms")
return;
// Abort if they were just relevelled
if(GetLocalInt(oPC, "RelevelXP"))
{
DeleteLocalInt(oPC, "RelevelXP");
return;
}
//this is done first because leadership uses it too
int iCurXP = GetXP(oPC);
//if (DEBUG) DoDebug("ApplyECLToXP - iCurXP "+IntToString(iCurXP));
int iLastXP = GetPersistantLocalInt(oPC, sXP_AT_LAST_HEARTBEAT);
//if (DEBUG) DoDebug("ApplyECLToXP - iLastXP "+IntToString(iLastXP));
if(iCurXP > iLastXP)
{
//if (DEBUG) DoDebug("ApplyECLToXP - gained XP");
int iLvlAdj = GetTotalLA(oPC);
if(iLvlAdj)
{
//if (DEBUG) DoDebug("ApplyECLToXP - have LA");
int iPCLvl = GetHitDice(oPC);
// Get XP Ratio (multiply new XP by this to see what to subtract)
float fRealXPToLevel = IntToFloat(GetXPForLevel(iPCLvl+1));
float fECLXPToLevel = IntToFloat(GetXPForLevel(iPCLvl+1+iLvlAdj));
float fXPRatio = 1.0 - (fRealXPToLevel/fECLXPToLevel);
//At this point the ratio is based on total XP
//This is not correct, it should be based on the XP required to reach
//the next level.
//fRealXPToLevel = IntToFloat(iPCLvl*1000);
//fECLXPToLevel = IntToFloat((iPCLvl+iLvlAdj)*1000);
//fXPRatio = 1.0 - (fRealXPToLevel/fECLXPToLevel);
float fXPDif = IntToFloat(iCurXP - iLastXP);
int iXPDif = FloatToInt(fXPDif * fXPRatio);
int newXP = iCurXP - iXPDif;
SendMessageToPC(oPC, "XP gained since last heartbeat "+IntToString(FloatToInt(fXPDif)));
SendMessageToPC(oPC, "Real XP to level: "+IntToString(FloatToInt(fRealXPToLevel)));
SendMessageToPC(oPC, "ECL XP to level: "+IntToString(FloatToInt(fECLXPToLevel)));
SendMessageToPC(oPC, "Level Adjustment +"+IntToString(iLvlAdj)+". Reducing XP by " + IntToString(iXPDif));
SetXP(oPC, newXP);
}
}
iCurXP = GetXP(oPC);
SetPersistantLocalInt(oPC, sXP_AT_LAST_HEARTBEAT, iCurXP);
}
int GetBuyoffCost(object oPC)
{
int nECL = GetECL(oPC);
int nXP = (nECL-1) * 1000;
return nXP;
}
void BuyoffLevel(object oPC)
{
int nECL = GetECL(oPC);
int nXP = (nECL-1) * 1000;
SetXP(oPC, GetXP(oPC)-nXP);
int nBuyoff = GetPersistantLocalInt(oPC, "LA_Buyoff");
SetPersistantLocalInt(oPC, "LA_Buyoff", nBuyoff+1);
}
int GetCanBuyoffLA(object oPC)
{
int nReturn = FALSE;
int nBuyoff = GetPersistantLocalInt(oPC, "LA_Buyoff");
int nChar = GetHitDice(oPC);
int nLA = StringToInt(Get2DACache("ECL", "LA", GetRacialType(oPC))) + GetPersistantLocalInt(oPC, "template_LA");
int nCheck = nLA - nBuyoff;
if (DEBUG) DoDebug("PRE-LA nBuyoff "+IntToString(nBuyoff)+" nChar "+IntToString(nChar)+" nLA "+IntToString(nLA)+" nCheck "+IntToString(nCheck));
if (0 >= nCheck) // no LA
return FALSE;
if (!nBuyoff) // Not purchased anything yet
{
if (nChar >= StringToInt(Get2DACache("la_buyoff", "1st", nLA)))
nReturn = TRUE;
}
if (nBuyoff == 1) // Purchased first already
{
if (nChar >= StringToInt(Get2DACache("la_buyoff", "2nd", nLA)))
nReturn = TRUE;
}
if (nBuyoff == 2) // Purchased second already
{
if (nChar >= StringToInt(Get2DACache("la_buyoff", "3rd", nLA)))
nReturn = TRUE;
}
if (nBuyoff == 3) // Purchased third already
{
if (nChar >= StringToInt(Get2DACache("la_buyoff", "4th", nLA)))
nReturn = TRUE;
}
if (nBuyoff == 4) // Purchased fourth already
{
if (nChar >= StringToInt(Get2DACache("la_buyoff", "5th", nLA)))
nReturn = TRUE;
}
if (nBuyoff == 5) // Purchased fifth already
{
if (nChar >= StringToInt(Get2DACache("la_buyoff", "6th", nLA)))
nReturn = TRUE;
}
if (DEBUG) DoDebug("nReturn "+IntToString(nReturn)+" nBuyoff "+IntToString(nBuyoff)+" nChar "+IntToString(nChar)+" nLA "+IntToString(nLA));
return nReturn;
}

Binary file not shown.

View File

@@ -0,0 +1,151 @@
//Cohort HB script
#include "prc_alterations"
#include "prc_inc_leadersh"
void main()
{
object oCohort = OBJECT_SELF;
object oPC = GetMaster(oCohort);
object oMaster = GetLocalObject(oCohort, "MasterObject");
if(!GetIsObjectValid(oPC) && GetIsObjectValid(oMaster))
{
//must have become disconnected from master
//re-add it as a cohort, but dont re-setup it
AddCohortToPlayerByObject(oCohort, oMaster, FALSE);
//dont continue this script, allow next HB to kick in instead
return;
}
else if(!GetIsObjectValid(oPC) && !GetIsObjectValid(oMaster))
{
//master no longer exists
RemoveCohortFromPlayer(oCohort, oPC);
return;
}
//if it doesnt have a tag, abort
if(GetTag(OBJECT_SELF) == "")
return;
//cohort XP gain
//get the amount the PC has gained
int XPGained = GetXP(oPC)-GetLocalInt(OBJECT_SELF, "MastersXP");
//correct for simple LA XP penalty
if(GetPRCSwitch(PRC_XP_USE_SIMPLE_LA))
{
int iPCLvl = GetHitDice(oPC);
int nRace = GetRacialType(oPC);
int iLvlAdj = StringToInt(Get2DACache("ECL", "LA", nRace));
if(GetPRCSwitch(PRC_XP_INCLUDE_RACIAL_HIT_DIE_IN_LA))
iLvlAdj += StringToInt(Get2DACache("ECL", "RaceHD", nRace));
float fRealXPToLevel = IntToFloat(GetXPForLevel(iPCLvl+1));
float fECLXPToLevel = IntToFloat(GetXPForLevel(iPCLvl+1+iLvlAdj));
float fXPRatio = fECLXPToLevel/fRealXPToLevel;
XPGained = FloatToInt(IntToFloat(XPGained)*fXPRatio);
}
//store the amount the PC now has for the next HB
SetLocalInt(OBJECT_SELF, "MastersXP", GetXP(oPC));
//work out proportion based on relative ECLs
int nPCECL = GetECL(oPC);
int nCohortECL = GetECL(oCohort);
int nCohortLag = GetLocalInt(oCohort, "CohortLevelLag");
int nCohortMaxHD = nPCECL-nCohortLag-StringToInt(Get2DACache("ECL", "LA", GetRacialType(oCohort)));
if(GetPRCSwitch(PRC_XP_INCLUDE_RACIAL_HIT_DIE_IN_LA))
nCohortMaxHD -= StringToInt(Get2DACache("ECL", "RaceHD", GetRacialType(oCohort)));
float ECLRatio = IntToFloat(nPCECL)/IntToFloat(nCohortECL);
//get the amount to gain
int nCohortXPGain = FloatToInt(IntToFloat(XPGained)*ECLRatio);
//get the current amount
int nCohortXP = GetXP(oCohort);
//work out the new amount
int nCohortNewXP = nCohortXP+nCohortXPGain;
//get the cap based on PC level and cohort LA
int nCohortXPCap = ((nCohortMaxHD)*(nCohortMaxHD+1)*500)-1;
//this is how much XP the next levelup will be at
int nCohortXPLevel = nCohortECL*(nCohortECL+1)*500;
//DoDebug("XPGained = "+IntToString(XPGained));
//DoDebug("nPCECL = "+IntToString(nPCECL));
//DoDebug("nCohortECL = "+IntToString(nCohortECL));
//DoDebug("nCohortXPGain = "+IntToString(nCohortXPGain));
//DoDebug("nCohortXP = "+IntToString(nCohortXP));
//DoDebug("nCohortNewXP = "+IntToString(nCohortNewXP));
//DoDebug("nCohortXPCap = "+IntToString(nCohortXPCap));
//DoDebug("nCohortXPLevel = "+IntToString(nCohortXPLevel));
//apply the cap
if(nCohortNewXP > nCohortXPCap)
nCohortNewXP = nCohortXPCap;
//give the XP
SetXP(oCohort, nCohortNewXP);
//handle levelup
if(nCohortNewXP >= nCohortXPLevel)
{
//standard
if(GetResRef(oCohort) != "")
{
LevelUpHenchman(oCohort, CLASS_TYPE_INVALID, TRUE);
}
else
{
//custom
//resummon it but dont decrease XP as much
int nCohortID = GetLocalInt(oCohort, "CohortID");
//Call creation of new cohort
object oNewCohort = AddCohortToPlayer(nCohortID, oPC);
object oTest;
//copy its equipment & inventory
// object oTest = GetFirstItemInInventory(oCohort);
// while(GetIsObjectValid(oTest))
// {
// if(!GetLocalInt(oTest, "CohortCopied"))
// object oNewTest = CopyItem(oTest, oNewCohort, TRUE);
// SetLocalInt(oTest, "CohortCopied", TRUE);
// DestroyObject(oTest, 0.01);
// oTest = GetNextItemInInventory(oCohort);
//}
//Delete new cohorts items (todo: prevent having them added in first place)
object currItem = GetFirstItemInInventory(oNewCohort);
while(GetIsObjectValid(currItem)){
DestroyObject(currItem, 0.01);
currItem = GetNextItemInInventory(oNewCohort);
}
//Copy Inventory Items
currItem = GetFirstItemInInventory(oCohort);
while(GetIsObjectValid(currItem)){
CopyItem(currItem,oNewCohort,TRUE);
DestroyObject(currItem, 0.01);
currItem = GetNextItemInInventory(oCohort);
}
//Copy Equiped items (todo: fix equipping)
int nSlot;
for(nSlot = 0;nSlot<14;nSlot++)
{
oTest = GetItemInSlot(nSlot, OBJECT_SELF);
object oTest2 = CopyItem(oTest, oNewCohort, TRUE);
//currently isn't equiping it
AssignCommand(oNewCohort, ClearAllActions());
AssignCommand(oNewCohort, ActionEquipItem(oTest2, nSlot));
DestroyObject(oTest, 0.01);
}
//destroy old cohort
SetIsDestroyable(TRUE, FALSE, FALSE);
DestroyObject(OBJECT_SELF, 0.1);
}
}/*
//and now for some intelligence to the AI
//if you have a familiar, summon it
if(GetHasFeat(FEAT_SUMMON_FAMILIAR, oCohort)
//&& !GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oCohort))
)
ActionUseFeat(FEAT_SUMMON_FAMILIAR, oCohort);
//SummonFamiliar(oCohort);
//if you have an animal companion, summon it
if(GetHasFeat(FEAT_ANIMAL_COMPANION, oCohort)
//&& !GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oCohort))
)
ActionUseFeat(FEAT_ANIMAL_COMPANION, oCohort);
//SummonAnimalCompanion(oCohort);*/
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,141 @@
//::///////////////////////////////////////////////
//:: OnPlayerDeath eventscript
//:: prc_ondeath
//:://////////////////////////////////////////////
/*
This is also triggered by the NPC OnDeath event.
*/
#include "prc_inc_combat"
#include "psi_inc_psifunc"
#include "inc_ecl"
#include "prc_inc_assoc"
void PreyOnTheWeak(object oDead)
{
float fRange = FeetToMeters(10.0);
int i = 1;
object oPrey = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oDead, i, CREATURE_TYPE_IS_ALIVE, TRUE);
while(GetIsObjectValid(oPrey) && GetDistanceBetween(oPrey, oDead) < fRange)
{
if(GetHasSpellEffect(MOVE_TC_PREY_ON_THE_WEAK, oPrey))
{
if(!GetLocalInt(oPrey, "PRC_POTW_HAS_ATTACKED"))
{
//GetNearestEnemy
object oAoOTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oPrey, 1, CREATURE_TYPE_IS_ALIVE, TRUE);
if(GetIsObjectValid(oAoOTarget) && GetDistanceBetween(oPrey, oAoOTarget) < fRange)
{
effect eNone;
object oWeap = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPrey);
//SetLocalInt
SetLocalInt(oPrey, "PRC_POTW_HAS_ATTACKED", 1);
PerformAttack(oAoOTarget, oPrey, eNone, 0.0, 0, 0, GetWeaponDamageType(oWeap), "Prey on the Weak Hit", "Prey on the Weak Miss");
//Set up removal
DelayCommand(RoundsToSeconds(1), DeleteLocalInt(oPrey, "PRC_POTW_HAS_ATTACKED"));
}
}
}
i++;
oPrey = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oDead, i, CREATURE_TYPE_IS_ALIVE, TRUE);
}
}
void main()
{
object oDead = GetLastBeingDied();
object oKiller = MyGetLastKiller();
// We are not actually dead until -10
// Unless it's a spell death
//int nHP = GetCurrentHitPoints(oDead);
//if ((nHP >= -9) || (GetLocalInt(oTarget, "PRC_PNP_EfectDeathApplied"))
// return;
// Unsummon familiar/animal companions
DelayCommand(0.1f, UnsummonCompanions(oDead));
// Clear a damage tracking variable. Oni's stuff uses this
SetLocalInt(oDead, "PC_Damage", 0);
// Do Lolth's Meat for the killer
if(GetAbilityScore(oDead, ABILITY_INTELLIGENCE) >= 4 && GetHasFeat(FEAT_LOLTHS_MEAT, oKiller))
{
/*effect eLink = EffectSavingThrowIncrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_ALL);
eLink = EffectLinkEffects(eLink, EffectAttackIncrease(1, ATTACK_BONUS_MISC));
eLink = EffectLinkEffects(eLink, EffectDamageIncrease(DAMAGE_BONUS_1, DAMAGE_TYPE_DIVINE));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oKiller, RoundsToSeconds(5));
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_EVIL_HELP), oKiller);*/
ExecuteScript("prc_lolthmeat", oKiller);
}
// Do Mind Cleave feat
if(GetHasFeat(FEAT_MIND_CLEAVE, oKiller))
{
SetLocalInt(oKiller, "MindCleave", TRUE);
ExecuteScript("psi_sk_psychsrtk", oKiller);
DelayCommand(0.25, DeleteLocalInt(oKiller, "MindCleave"));
}
// Do Merciless Purity from Shadowbane Inq
if(GetLocalInt(oDead, "MercilessPurity") && GetIsObjectValid(GetLocalObject(oDead, "Shadowbane")))
{
object oShadow = GetLocalObject(oDead, "Shadowbane");
effect eLink = EffectSavingThrowIncrease(SAVING_THROW_FORT, 1, SAVING_THROW_TYPE_ALL);
eLink = EffectLinkEffects(eLink, EffectSavingThrowIncrease(SAVING_THROW_REFLEX, 1, SAVING_THROW_TYPE_ALL));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oShadow, HoursToSeconds(24));
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_GOOD_HELP), oShadow);
if (DEBUG) FloatingTextStringOnCreature("Merciless Purity activated", oShadow, FALSE);
}
if(GetPRCSwitch(PRC_XP_USE_PNP_XP))
{
if(GetObjectType(oKiller) == OBJECT_TYPE_TRIGGER)
oKiller = GetTrapCreator(oKiller);
if(oKiller != oDead
&& GetIsObjectValid(oKiller)
&& !GetIsFriend(oKiller, oDead)
&& (GetIsObjectValid(GetFirstFactionMember(oKiller, TRUE))
|| GetPRCSwitch(PRC_XP_GIVE_XP_TO_NON_PC_FACTIONS)))
{
GiveXPRewardToParty(oKiller, oDead);
/* Not needed as we now disabled the bioware system if this is enabled
*
//bypass bioware XP system
//AssignCommand(oDead, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oDead));
SetLocalInt(oDead, "PRC_PNP_XP_DEATH", 1);
//AssignCommand(oDead, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(10000, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_TWENTY), oDead));
AssignCommand(oDead, ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDeath()), oDead));
*/
}
}
// Prey on the Weak
PreyOnTheWeak(oDead);
if(GetPRCSwitch(PRC_PW_DEATH_TRACKING) && GetIsPC(oDead))
SetPersistantLocalInt(oDead, "persist_dead", TRUE);
// Psionic creatures lose all PP on death
if(GetIsPsionicCharacter(oDead))
LoseAllPowerPoints(oDead, TRUE);
DeleteLocalInt(oDead, "PRC_SPELL_CHARGE_COUNT");
DeleteLocalInt(oDead, "PRC_SPELL_HOLD");
// Trigger the death/bleed if the PRC Death system is enabled (ElgarL).
if((GetPRCSwitch(PRC_PNP_DEATH_ENABLE)) && GetIsPC(oDead))
AddEventScript(oDead, EVENT_ONHEARTBEAT, "prc_timer_dying", TRUE, FALSE);
// Execute scripts hooked to this event for the player triggering it
ExecuteAllScriptsHookedToEvent(oDead, EVENT_ONPLAYERDEATH);
}

Binary file not shown.

View File

@@ -0,0 +1,405 @@
//:: Updated for .35 by Jaysyn 2023/03/11
#include "inc_leto_prc"
#include "x2_inc_switches"
#include "prc_inc_teleport"
#include "prc_inc_leadersh"
#include "prc_inc_domain"
#include "prc_inc_shifting"
#include "true_inc_trufunc"
#include "prc_craft_inc"
#include "prc_inc_dragsham"
#include "shd_inc_myst"
#include "prc_inc_template"
/**
* Reads the 2da file onenter_locals.2da and sets local variables
* on the entering PC accordingly. 2da format same as personal_switches.2da,
* see prc_inc_switches header comment for details.
*
* @param oPC The PC that just entered the module
*/
void DoAutoLocals(object oPC)
{
int i = 0;
string sSwitchName, sSwitchType, sSwitchValue;
// Use Get2DAString() instead of Get2DACache() to avoid caching.
while((sSwitchName = Get2DAString("onenter_locals", "SwitchName", i)) != "")
{
// Read rest of the line
sSwitchType = Get2DAString("onenter_locals", "SwitchType", i);
sSwitchValue = Get2DAString("onenter_locals", "SwitchValue", i);
// Determine switch type and set the var
if (sSwitchType == "float")
SetLocalFloat(oPC, sSwitchName, StringToFloat(sSwitchValue));
else if(sSwitchType == "int")
SetLocalInt(oPC, sSwitchName, StringToInt(sSwitchValue));
else if(sSwitchType == "string")
SetLocalString(oPC, sSwitchName, sSwitchValue);
// Increment loop counter
i += 1;
}
}
//Restore appearance
void RestoreAppearance(object oCreature)
{
if(!RestoreTrueAppearance(oCreature) && DEBUG)
DoDebug("prc_onenter: RestoreAppearance failed");
}
void CopyAMSArray(object oHideToken, object oAMSToken, int nClass, string sArray, int nMin, int nMax, int nLoopSize = 100)
{
int i = nMin;
while(i < nMin + nLoopSize && i < nMax)
{
int nSpell = array_get_int(oAMSToken, sArray, i);
int nSpellbookID = RealSpellToSpellbookID(nClass, nSpell);
if(nSpellbookID)
array_set_int(oHideToken, sArray, i, nSpellbookID);
i++;
}
if(i < nMax)
DelayCommand(0.0, CopyAMSArray(oHideToken, oAMSToken, nClass, sArray, i, nMax));
}
void DoRestoreAMS(object oPC, int nClass, object oHideToken, object oAMSToken)
{
string sSpellbook;
int nSpellbookType = GetSpellbookTypeForClass(nClass);
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
sSpellbook = "Spellbook"+IntToString(nClass);
if(DEBUG) DoDebug("DoRestoreAMS: "+sSpellbook);
if(persistant_array_exists(oPC, sSpellbook))
array_delete(oHideToken, sSpellbook);
array_create(oHideToken, sSpellbook);
int nSize = array_get_size(oAMSToken, sSpellbook);
if(DEBUG) DoDebug("DoRestoreAMS: array size = "+IntToString(nSize));
if(nSize)
DelayCommand(0.0, CopyAMSArray(oHideToken, oAMSToken, nClass, sSpellbook, 0, nSize));
}
else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
{
int i;
for(i = 0; i <= 9; i++)
{
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(i);
if(DEBUG) DoDebug("DoRestoreAMS: "+sSpellbook);
if(array_exists(oHideToken, sSpellbook))
array_delete(oHideToken, sSpellbook);
array_create(oHideToken, sSpellbook);
int nSize = array_get_size(oAMSToken, sSpellbook);
if(DEBUG) DoDebug("DoRestoreAMS: array size = "+IntToString(nSize));
if(nSize)
DelayCommand(0.0, CopyAMSArray(oHideToken, oAMSToken, nClass, sSpellbook, 0, nSize));
array_delete(oHideToken, "Spellbook"+IntToString(i)+"_"+IntToString(nClass));
array_delete(oHideToken, "NewSpellbookMem_"+IntToString(nClass));
}
}
}
void OnEnter_AMSCompatibilityCheck(object oPC)
{
object oAMSToken = GetHideToken(oPC, TRUE);
object oHideToken = GetHideToken(oPC);
//check PRC version
string sVersion = GetLocalString(oAMSToken, "ams_version");
//DoDebug("AMS version = "+sVersion);
if(sVersion != AMS_VERSION)
{
SetLocalInt(oPC, "AMS_RESTORE", 1);
int i;
for(i = 1; i <= 8; i++)
{
int nClass = GetClassByPosition(i, oPC);
DelayCommand(0.2, DoRestoreAMS(oPC, nClass, oHideToken, oAMSToken));
}
DelayCommand(2.0, WipeSpellbookHideFeats(oPC));
SetLocalString(oAMSToken, "ams_version", AMS_VERSION);
DelayCommand(5.0, DeleteLocalInt(oPC, "AMS_RESTORE"));
}
}
void main()
{
//The composite properties system gets confused when an exported
//character re-enters. Local Variables are lost and most properties
//get re-added, sometimes resulting in larger than normal bonuses.
//The only real solution is to wipe the skin on entry. This will
//mess up the lich, but only until I hook it into the EvalPRC event -
//hopefully in the next update
// -Aaon Graywolf
object oPC = GetEnteringObject();
//FloatingTextStringOnCreature("PRC on enter was called", oPC, FALSE);
// Since OnEnter event fires for the PC when loading a saved game (no idea why,
// since it makes saving and reloading change the state of the module),
// make sure that the event gets run only once
// but not in MP games, so check if it's single player or not!!
if(GetLocalInt(oPC, "PRC_ModuleOnEnterDone") && (GetPCPublicCDKey(oPC) == ""))
return;
// Use a local integer to mark the event as done for the PC, so that it gets
// cleared when the character is saved.
else
SetLocalInt(oPC, "PRC_ModuleOnEnterDone", TRUE);
//if server is loading, boot player
if(GetLocalInt(GetModule(), PRC_PW_LOGON_DELAY+"_TIMER"))
{
BootPC(oPC);
return;
}
DoDebug("Running modified prc_onenter with PW CD check");
// Verify players CD key
if(GetPRCSwitch(PRC_PW_SECURITY_CD_CHECK))
{
DoDebug("PRC_PW_SECURITY_CD_CHECK switch set on the module");
if(ExecuteScriptAndReturnInt("prc_onenter_cd", oPC))
return;
}
DoDebug("CD-check OK - continue executing prc_onenter");
// Prevent Items on area creation from trigering the GetPCSkin script
if (GetObjectType(oPC) != OBJECT_TYPE_CREATURE)
return;
// return here for DMs as they don't need all this stuff
if(GetIsDM(oPC))
return;
// Setup class info for EvalPRCFeats()
SetupCharacterData(oPC);
//do this first so other things dont interfere with it
if(GetPRCSwitch(PRC_USE_LETOSCRIPT))
LetoPCEnter(oPC);
if(GetPRCSwitch(PRC_CONVOCC_ENABLE) && !GetPRCSwitch(PRC_CONVOCC_CUSTOM_START_LOCATION) && ExecuteScriptAndReturnInt("prc_ccc_main", OBJECT_SELF))
return;
// ebonfowl: taking a risk here and commenting this out, it seems obsolete and it is very hard to fix without having an AMS token
//check spellbooks for compatibility with other PRC versions
//DelayCommand(10.0f, OnEnter_AMSCompatibilityCheck(oPC));
object oSkin = GetPCSkin(oPC);
ScrubPCSkin(oPC, oSkin);
DeletePRCLocalInts(oSkin);
// Gives people the proper spells from their bonus domains
// This should run before EvalPRCFeats, because it sets a variable
DelayCommand(0.0, CheckBonusDomains(oPC));
// Set the uses per day for domains
DelayCommand(0.0, BonusDomainRest(oPC));
// Clear old variables for AMS
DelayCommand(0.0, ClearLawLocalVars(oPC));
DelayCommand(0.0, ClearMystLocalVars(oPC));
DelayCommand(0.0, ClearLegacyUses(oPC));
DelayCommand(0.0, DeleteLocalInt(oPC, "RestTimer"));
//remove effects from hides, can stack otherwise
effect eTest=GetFirstEffect(oPC);
while (GetIsEffectValid(eTest))
{
if(GetEffectSubType(eTest) == SUBTYPE_SUPERNATURAL
&& (GetEffectType(eTest) == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE
|| GetEffectType(eTest) == EFFECT_TYPE_MOVEMENT_SPEED_INCREASE
//add other types here
)
&& !GetIsObjectValid(GetEffectCreator(eTest))
)
RemoveEffect(oPC, eTest);
eTest=GetNextEffect(oPC);
}
SetLocalInt(oPC,"ONENTER",1);
// Make sure we reapply any bonuses before the player notices they are gone.
DelayCommand(0.1, EvalPRCFeats(oPC));
DelayCommand(0.1, FeatSpecialUsePerDay(oPC));
// Check to see which special prc requirements (i.e. those that can't be done)
// through the .2da's, the entering player already meets.
ExecuteScript("prc_prereq", oPC);
ExecuteScript("prc_psi_ppoints", oPC);
ResetTouchOfVitality(oPC);
DelayCommand(0.15, DeleteLocalInt(oPC,"ONENTER"));
if(GetPRCSwitch(PRC_LETOSCRIPT_FIX_ABILITIES) && !GetIsDM(oPC))
PRCLetoEnter(oPC);
//PW tracking starts here
if(GetPRCSwitch(PRC_PNP_DEATH_ENABLE))
{
//cleanup.
int nStatus = GetPersistantLocalInt(oPC, "STATUS");
if (nStatus != ALIVE)
AddEventScript(oPC, EVENT_ONHEARTBEAT, "prc_timer_dying", TRUE, FALSE);
// Make us fall over if we should be on the floor.
if (nStatus == BLEEDING || STABLE || DEAD)
AssignCommand(oPC, DelayCommand(0.03, PlayAnimation(ANIMATION_LOOPING_DEAD_BACK, 1.0, 4.0)));
// If PRC Death is enabled we require HP tracking too
SetPRCSwitch(PRC_PW_HP_TRACKING, TRUE);
}
if(GetPRCSwitch(PRC_PW_HP_TRACKING))
{
// Make sure we actually have stored HP data to read
if(GetPersistantLocalInt(oPC, "persist_HP_stored") == -1)
{
// Read the stored level and set accordingly.
int nHP = GetPersistantLocalInt(oPC, "persist_HP");
int nDamage = GetCurrentHitPoints(oPC)-nHP;
if (nDamage >= 1) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage, DAMAGE_TYPE_MAGICAL), oPC);
}
}
if(GetPRCSwitch(PRC_PW_TIME))
{
struct time tTime = GetPersistantLocalTime(oPC, "persist_Time");
//first pc logging on
if(GetIsObjectValid(GetFirstPC())
&& !GetIsObjectValid(GetNextPC()))
{
SetTimeAndDate(tTime);
}
RecalculateTime();
}
if(GetPRCSwitch(PRC_PW_LOCATION_TRACKING))
{
struct metalocation lLoc = GetPersistantLocalMetalocation(oPC, "persist_loc");
DelayCommand(6.0, AssignCommand(oPC, JumpToLocation(MetalocationToLocation(lLoc))));
}
if(GetPRCSwitch(PRC_PW_MAPPIN_TRACKING)
&& !GetLocalInt(oPC, "PRC_PW_MAPPIN_TRACKING_Done"))
{
//this local is set so that this is only done once per server session
SetLocalInt(oPC, "PRC_PW_MAPPIN_TRACKING_Done", TRUE);
int nCount = GetPersistantLocalInt(oPC, "MapPinCount");
int i;
for(i=1; i<=nCount; i++)
{
struct metalocation mlocLoc = GetPersistantLocalMetalocation(oPC, "MapPin_"+IntToString(i));
CreateMapPinFromMetalocation(mlocLoc, oPC);
}
}
if(GetPRCSwitch(PRC_PW_DEATH_TRACKING))
{
if(GetPersistantLocalInt(oPC, "persist_dead"))
{
int nDamage=9999;
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(DAMAGE_TYPE_MAGICAL, nDamage), oPC);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oPC);
}
}
if(GetPRCSwitch(PRC_PW_SPELL_TRACKING))
{
string sSpellList = GetPersistantLocalString(oPC, "persist_spells");
string sTest;
string sChar;
while(GetStringLength(sSpellList))
{
sChar = GetStringLeft(sSpellList,1);
if(sChar == "|")
{
int nSpell = StringToInt(sTest);
DecrementRemainingSpellUses(oPC, nSpell);
sTest == "";
}
else
sTest += sChar;
sSpellList = GetStringRight(sSpellList, GetStringLength(sSpellList)-1);
}
}
//check for persistant golems
if(persistant_array_exists(oPC, "GolemList"))
{
MultisummonPreSummon(oPC, TRUE);
int i;
for(i=1;i<persistant_array_get_size(oPC, "GolemList");i++)
{
string sResRef = persistant_array_get_string(oPC, "GolemList",i);
effect eSummon = SupernaturalEffect(EffectSummonCreature(sResRef));
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSummon, oPC);
}
}
if(GetPRCSwitch(PRC_PNP_ANIMATE_DEAD) || GetPRCSwitch(PRC_MULTISUMMON))
{
MultisummonPreSummon(oPC, TRUE);
}
// Create map pins from marked teleport locations if the PC has requested that such be done.
if(GetLocalInt(oPC, PRC_TELEPORT_CREATE_MAP_PINS))
DelayCommand(10.0f, TeleportLocationsToMapPins(oPC));
if(GetPRCSwitch(PRC_XP_USE_SIMPLE_RACIAL_HD)
&& !GetXP(oPC))
{
int nRealRace = GetRacialType(oPC);
int nRacialHD = StringToInt(Get2DACache("ECL", "RaceHD", nRealRace));
int nRacialClass = StringToInt(Get2DACache("ECL", "RaceClass", nRealRace));
if(nRacialHD)
{
if(!GetPRCSwitch(PRC_XP_USE_SIMPLE_RACIAL_HD_NO_FREE_XP))
{
int nNewXP = nRacialHD*(nRacialHD+1)*500; //+1 for the original class level
SetXP(oPC, nNewXP);
if(GetPRCSwitch(PRC_XP_USE_SIMPLE_LA))
DelayCommand(1.0, SetPersistantLocalInt(oPC, sXP_AT_LAST_HEARTBEAT, nNewXP));
}
if(GetPRCSwitch(PRC_XP_USE_SIMPLE_RACIAL_HD_NO_SELECTION))
{
int i;
for(i=0;i<nRacialHD;i++)
{
LevelUpHenchman(oPC, nRacialClass, TRUE);
}
}
}
}
// Insert various debug things here
if(DEBUG)
{
// Duplicate PRCItemPropertyBonusFeat monitor
SpawnNewThread("PRC_Duplicate_IPBFeat_Mon", "prc_debug_hfeatm", 30.0f, oPC);
}
if(GetHasFeat(FEAT_SPELLFIRE_WIELDER, oPC))
SpawnNewThread("PRC_Spellfire", "prc_spellfire_hb", 6.0f, oPC);
//if the player logged off while being registered as a cohort
if(GetPersistantLocalInt(oPC, "RegisteringAsCohort"))
AssignCommand(GetModule(), CheckHB(oPC));
// If the PC logs in shifted, unshift them
if(GetPersistantLocalInt(oPC, SHIFTER_ISSHIFTED_MARKER))
UnShift(oPC);
if(GetPRCSwitch(PRC_ON_ENTER_RESTORE_APPEARANCE))
DelayCommand(2.0f, RestoreAppearance(oPC));
// Set up local variables based on a 2da file
DelayCommand(1.0 ,DoAutoLocals(oPC));
ExecuteScript("tob_evnt_recover", oPC);
// This prevents the LA function from eating XP on login
SetLocalInt(oPC, "PRC_ECL_Delay", TRUE);
SetPersistantLocalInt(oPC, sXP_AT_LAST_HEARTBEAT, GetXP(oPC));
DelayCommand(10.0, DeleteLocalInt(oPC, "PRC_ECL_Delay"));
// Execute scripts hooked to this event for the player triggering it
//How can this work? The PC isnt a valid object before this. - Primogenitor
//Some stuff may have gone "When this PC next logs in, run script X" - Ornedan
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONCLIENTENTER);
// Start the PC HeartBeat for PC's
if(GetIsPC(oPC))
AssignCommand(GetModule(), ExecuteScript("prc_onhb_indiv", oPC));
}

Binary file not shown.

View File

@@ -0,0 +1,139 @@
/** @file prc_onhb_indiv
Invidual Heartbeat event
This script is run every heartbeat for every PC via the prc_onheartbeat event
This script is run every heartbeat for every NPC via the prc_npc_hb event
Its main purposes is to provide a unified individual hb script interface
Slighly less efficient because things like switches are checked for each individual.
*/
#include "prc_alterations"
#include "prc_inc_nat_hb"
#include "inc_ecl"
void main()
{
object oPC = OBJECT_SELF;
// HB code removed from the Module OnHeartbeat (ElgarL)
// This is now executed as a delayed timer when the player logs in.
if(!GetIsObjectValid(oPC))
return;
// no running stuff for DMs or NPC's
if((!GetIsDM(oPC)) && (GetIsPC(oPC)))
{
int bPWPCAutoexport = GetPRCSwitch(PRC_PW_PC_AUTOEXPORT);
// Persistent World time tracking
if(GetPRCSwitch(PRC_PW_TIME))
{
//store it on all PCs separately
SetPersistantLocalTime(oPC, "persist_Time", GetTimeAndDate());
}
// Automatic character export every 6n seconds
// Check the counter to see if it is time to export
if(bPWPCAutoexport)
{
int nCount = GetLocalInt(oPC, "AutoexportCount");
if(nCount == bPWPCAutoexport)
DeleteLocalInt(oPC, "AutoexportCount");
else
{
nCount++;
SetLocalInt(oPC, "AutoexportCount", nCount);
bPWPCAutoexport = FALSE;
}
}
// Export if the counter has run down
if(bPWPCAutoexport)
{
if(!GetIsPolyMorphedOrShifted(oPC))
ExportSingleCharacter(oPC);
}
// Persistant hit point tracking
if(GetPRCSwitch(PRC_PW_HP_TRACKING))
{
//Flag that we have saved the HP as testing for Zero is faulty logic
//
SetPersistantLocalInt(oPC, "persist_HP_stored", -1);
// Now store the current HP.
SetPersistantLocalInt(oPC, "persist_HP", GetCurrentHitPoints(oPC));
}
// Persistant location tracking
if(GetPRCSwitch(PRC_PW_LOCATION_TRACKING) && GetStartingLocation() != GetLocation(oPC))
SetPersistantLocalMetalocation(oPC, "persist_loc", LocationToMetalocation(GetLocation(oPC)));
// Persistant map pin tracking
if(GetPRCSwitch(PRC_PW_MAPPIN_TRACKING))
{
int i;
int nMapPinCount = GetNumberOfMapPins(oPC);
struct metalocation mLoc;
for(i = 1; i <= nMapPinCount; i++)
{
mLoc = CreateMetalocationFromMapPin(oPC, i);
SetPersistantLocalMetalocation(oPC, "MapPin_" + IntToString(i), mLoc);
}
SetPersistantLocalInt(oPC, "MapPinCount", nMapPinCount);
}
// Death - Bleed - ElgarL
if(GetPRCSwitch(PRC_PNP_DEATH_ENABLE))
{
// PC doing anything that requires attention while disabled take damage
if(GetPersistantLocalInt(oPC, "STATUS") == 3)
{
int nAction = GetCurrentAction(oPC);
if(nAction == ACTION_DISABLETRAP || nAction == ACTION_TAUNT
|| nAction == ACTION_PICKPOCKET || nAction == ACTION_ATTACKOBJECT
|| nAction == ACTION_COUNTERSPELL || nAction == ACTION_FLAGTRAP
|| nAction == ACTION_CASTSPELL || nAction == ACTION_ITEMCASTSPELL)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(1), oPC);
}
}
}
// Continue the HeartBeat Timer.
DelayCommand(6.0, ExecuteScript("prc_onhb_indiv", oPC));
}
/* PC_damage code to support oni's scripts
* If HP is over 1 apply the damage and let
* the OnDying deal with the consequences
*/
int nDamage = GetLocalInt(oPC, "PC_Damage");
if(nDamage && GetCurrentHitPoints(oPC) > 1)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage), oPC);
SetLocalInt(oPC, "PC_Damage", 0);
}
// ECL
if(GetIsPC(oPC) || (!GetIsPC(oPC) && GetPRCSwitch(PRC_XP_GIVE_XP_TO_NPCS)))
ApplyECLToXP(oPC);
// Check if the character has lost a level since last HB
if(GetHitDice(oPC) != GetLocalInt(oPC, "PRC_HitDiceTracking"))
{
if(GetHitDice(oPC) < GetLocalInt(oPC, "PRC_HitDiceTracking"))
{
SetLocalInt(oPC, "PRC_OnLevelDown_OldLevel", GetLocalInt(oPC, "PRC_HitDiceTracking"));
DelayCommand(0.0f, ExecuteScript("prc_onleveldown", oPC));
}
SetLocalInt(oPC, "PRC_HitDiceTracking", GetHitDice(oPC));
}
// Race Pack Code
ExecuteScript("race_hb", oPC);
//natural weapons
//SpawnScriptDebugger();
DoNaturalWeaponHB(oPC);
// Eventhook
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONHEARTBEAT);
}

Binary file not shown.

View File

@@ -0,0 +1,55 @@
//::///////////////////////////////////////////////
//:: OnHeartbeat eventscript
//:: prc_onheartbeat
//:://////////////////////////////////////////////
#include "prc_alterations"
#include "prc_inc_leadersh"
void main()
{
// Item creation code
ExecuteScript("hd_o0_heartbeat", OBJECT_SELF);
int bBiowareDBCache = GetPRCSwitch(PRC_USE_BIOWARE_DATABASE);
if(bBiowareDBCache)
{
//decide if to cache bioware 2da yet
object oModule = GetModule();
if(GetLocalInt(oModule, "Bioware2dacacheCount") >= bBiowareDBCache)
DeleteLocalInt(oModule, "Bioware2dacacheCount");
else
{
SetLocalInt(oModule, "Bioware2dacacheCount", GetLocalInt(oModule, "Bioware2dacacheCount") + 1);
bBiowareDBCache = FALSE;
}
if(bBiowareDBCache)
{
//due to biowares piss-poor database coding, you have to destroy the old database before storing
//the object
//If you dont, the dataabse will bloat infinitely because when overriting an existing
//database entry really marks the old entry as "deleted" ( but doesnt actually remove it)
//and creates a new entry instead.
if(DEBUG) DoDebug ("Storing Bioware2DACache");
else WriteTimestampedLogEntry("Storing Bioware2DACache");
string sDBName = GetBiowareDBName();
DestroyCampaignDatabase(sDBName);
object o2daCache = GetObjectByTag("Bioware2DACache");
// Rebuild the DB
StoreCampaignObject(sDBName, "CacheChest", o2daCache);
SetCampaignString(sDBName, "version", PRC_VERSION);
SetCampaignString(sDBName, "PRC_2DA_Cache_Fingerprint", GetLocalString(oModule, "PRC_2DA_Cache_Fingerprint"));
if(DEBUG) DoDebug ("Finished storing Bioware2DACache");
else WriteTimestampedLogEntry("Finished storing Bioware2DACache");
// Updated last access fingerprint
SetLocalString(oModule, "PRC_2DA_Cache_Fingerprint_LastAccessed", GetLocalString(oModule, "PRC_2DA_Cache_Fingerprint"));
}
}
// Player HB code moved to prc_onhb_indiv
// Removes a LOT of load from teh Module HB
// and should prevent TMI problems.
}

Binary file not shown.

View File

@@ -0,0 +1,319 @@
//::///////////////////////////////////////////////
//:: 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);
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);
}
//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);
//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);
}
}

Binary file not shown.

File diff suppressed because it is too large Load Diff