PRC8/nwn/nwnprc/trunk/include/tob_inc_recovery.nss
Jaysyn904 2223aa463d Bringing PRC Alpha up to pairty with PRC35
Bringing PRC alpha up to parity with PRC35 with the exception of the marker feats, which need to be reworked.  Updated PRC alpha release.
2024-01-02 20:03:30 -05:00

650 lines
22 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Tome of Battle include: Maneuver Recovery
//:: tob_inc_martlore
//::///////////////////////////////////////////////
/** @file
Defines various functions and other stuff that
do something related to recovery and readying maneuvers
See page #28 of Tome of Battle
Functions below are called by the initiator as
he makes a maneuver, or when recovering or readying
@author Stratovarius
@date Created - 2007.3.25
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
//:: Test Void
//void main (){}
//////////////////////////////////////////////////
/* Constants */
//////////////////////////////////////////////////
const int MANEUVER_READIED = 1;
const int MANEUVER_RECOVERED = 2;
const int MANEUVER_GRANTED = 3;
const int MANEVUER_WITHHELD = 4;
const string _MANEUVER_LIST_RDYMODIFIER = "_ReadyModifier";
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
/**
* Gets the number of Maneuvers a character has readied
*
* @param oPC The creature whose Maneuvers to check
* @param nList The list to check. One of MANEUVER_LIST_*
* @return The number of Maneuvers readied
*/
int GetReadiedCount(object oPC, int nList);
/**
* Gets the maximum number of Maneuvers a character may ready.
*
* @param oPC Character to determine maximum Maneuvers readied
* @param nList MANEUVER_LIST_* of the list to determine maximum Maneuvers for
* @return Maximum number of Maneuvers that oPC may ready
*/
int GetMaxReadiedCount(object oPC, int nList);
/**
* Gets the value of the Maneuvers readied modifier, which is a value that is added
* to the 2da-specified maximum Maneuvers readied to determine the actual maximum.
*
* @param oCreature The creature whose modifier to get
* @param nList The list the maximum Maneuvers readied from which the modifier
* modifies. One of MANEUVER_LIST_*
*/
int GetReadiedManeuversModifier(object oCreature, int nList);
/**
* Sets the value of the Maneuvers readied modifier, which is a value that is added
* to the 2da-specified maximum Maneuvers readied to determine the actual maximum.
*
* @param oCreature The creature whose modifier to set
* @param nList The list the maximum Maneuvers readied from which the modifier
* modifies. One of MANEUVER_LIST_*
*/
void SetReadiedManeuversModifier(object oCreature, int nList, int nNewValue);
/**
* Readies the chosen Maneuver. Also checks to see if there are any slots left
*
* @param oPC Character readying maneuver
* @param nList MANEUVER_LIST_* of the list to ready
* @param nMoveId Maneuver to ready
*/
void ReadyManeuver(object oPC, int nList, int nMoveId);
/**
* Returns whether maneuver is readied or not
*
* @param oPC Character to check
* @param nList MANEUVER_LIST_*
* @param nMoveId Maneuver to check
* @return TRUE or FALSE
*/
int GetIsManeuverReadied(object oPC, int nList, int nMoveId);
/**
* Returns whether maneuver is expended or not
*
* @param oPC Character to check
* @param nList MANEUVER_LIST_*
* @param nMoveId Maneuver to check
* @return TRUE or FALSE
*/
int GetIsManeuverExpended(object oPC, int nList, int nMoveId);
/**
* Expends the chosen Maneuver.
*
* @param oPC Character to check
* @param nList MANEUVER_LIST_*
* @param nMoveId Maneuver to expend
*/
void ExpendManeuver(object oPC, int nList, int nMoveId);
/**
* Clears all local ints marking maneuvers as expended
*
* @param oPC Character to clear
* @param nList MANEUVER_LIST_*
*/
void RecoverExpendedManeuvers(object oPC, int nList);
/**
* Recovers the chosen Maneuver.
*
* @param oPC Character to check
* @param nList MANEUVER_LIST_*
* @param nMoveId Maneuver to recover
*/
void RecoverManeuver(object oPC, int nList, int nMoveId);
/**
* Checks to see if the PC is in a Warblade recovery round
* This prevents all use of maneuvers or stances during that round.
*
* @param oPC Character to clear
* @return TRUE or FALSE
*/
int GetIsWarbladeRecoveryRound(object oPC);
/**
* Marks maneuvers as granted or withheld.
*
* @param oPC Character to grant maneuvers to
* @param nList MANEUVER_LIST_*
*/
void GrantManeuvers(object oPC, int nList);
/**
* Clears all local ints marking maneuvers as readied
*
* @param oPC Character to clear
* @param nList MANEUVER_LIST_*
*/
void ClearReadiedManeuvers(object oPC, int nList);
/**
* Grants a withheld maneuver
* Only works on Crusaders
*
* @param oPC Character to grant maneuvers to
* @param nList MANEUVER_LIST_*
* @param nMoveId Maneuver to grant
*/
void GrantWithheldManeuver(object oPC, int nList, int nMoveId = -1);
/**
* Returns whether maneuver is granted or not
* Only works on Crusaders
*
* @param oPC Character to check
* @param nMoveId Maneuver to check
* @return TRUE or FALSE
*/
int GetIsManeuverGranted(object oPC, int nMoveId);
/**
* Clears all local ints marking maneuvers as granted or withheld
* Only works on Crusaders
*
* @param oPC Character to clear
*/
void ClearGrantedWithheldManeuvers(object oPC);
/**
* Starting function for Crusader recovery, calls DoCrusaderGranting
* Only works on Crusaders
*
* @param oPC Crusader
*/
void BeginCrusaderGranting(object oPC);
/**
* Recursive function granting maneuvers each round in combat
* Will end when combat ends
* Only works on Crusaders
*
* @param oPC Crusader
* @param nTrip Round of combat. Takes values from 1 to 5, always starts with 1.
*/
void DoCrusaderGranting(object oPC, int nTrip);
/**
* Returns TRUE if a maneuver was expended, FALSE otherwise
* @param oPC Character to check
* @param nList MANEUVER_LIST_*
* @param nDiscipline DISCIPLINE_* the maneuver has to be from
*
* @return TRUE or FALSE
*/
int ExpendRandomManeuver(object oPC, int nList, int nDiscipline = -1);
/**
* Clears all local ints marking maneuvers as expended
*
* @param oPC Character to clear
* @param nPRC Specific PRC to recover, else all.
*/
void RecoverPrCAbilities(object oPC);
/**
* Heals 3 + 1 point per character level ones per minute
*
* @param oPC Character to heal
*/
void VitalRecovery(object oPC);
//////////////////////////////////////////////////
/* Includes */
//////////////////////////////////////////////////
#include "inc_lookups"
#include "tob_inc_tobfunc"
//////////////////////////////////////////////////
/* Internal functions */
//////////////////////////////////////////////////
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
int GetReadiedCount(object oPC, int nList)
{
return GetLocalInt(oPC, "ManeuverReadied" + IntToString(nList));
}
int GetMaxReadiedCount(object oPC, int nList)
{
int nLevel = GetLevelByClass(nList, oPC);
// 2das start at Row 0
int nMaxReadied = StringToInt(Get2DACache(GetAMSKnownFileName(nList), "ManeuversReadied", nLevel-1));
// Add in the custom modifier
nMaxReadied += GetReadiedManeuversModifier(oPC, nList);
if(nList == MANEUVER_LIST_SWORDSAGE)
nMaxReadied += GetHasFeat(FEAT_EXTRA_GRANTED_MANEUVER, oPC);
if(DEBUG) DoDebug("tob_inc_recovery: MaxManeuvers Readied: " +IntToString(nMaxReadied));
return nMaxReadied;
}
int GetReadiedManeuversModifier(object oCreature, int nList)
{
return GetPersistantLocalInt(oCreature, _MANEUVER_LIST_NAME_BASE + IntToString(nList) + _MANEUVER_LIST_RDYMODIFIER);
}
void SetReadiedManeuversModifier(object oCreature, int nList, int nNewValue)
{
SetPersistantLocalInt(oCreature, _MANEUVER_LIST_NAME_BASE + IntToString(nList) + _MANEUVER_LIST_RDYMODIFIER, nNewValue);
}
void ReadyManeuver(object oPC, int nList, int nMoveId)
{
int nCount = GetReadiedCount(oPC, nList);
int nMaxCount = GetMaxReadiedCount(oPC, nList);
// If the PC can ready a maneuver and hasn't filled them all up
if(nMaxCount > nCount)
{
nCount++;
SetLocalInt(oPC, "ManeuverReadied" + IntToString(nList) + IntToString(nCount), nMoveId);
SetLocalInt(oPC, "ManeuverReadied" + IntToString(nList), nCount);
if(DEBUG) DoDebug("tob_inc_recovery: ReadyManeuver: " +IntToString(nMoveId));
}
else
FloatingTextStringOnCreature("All maneuvers are readied", oPC, FALSE);
}
int GetIsManeuverReadied(object oPC, int nList, int nMoveId)
{
// Counting through the local ints to determine if this one is readied
int i, nMax = GetReadiedCount(oPC, nList);
for(i = 1; i <= nMax; i++)
{
// If the value is valid, return true
if(GetLocalInt(oPC, "ManeuverReadied" + IntToString(nList) + IntToString(i)) == nMoveId)
{
if(DEBUG) DoDebug("tob_inc_recovery: GetIsManeuverReadied: " + IntToString(nMoveId));
return TRUE;
}
}
return FALSE;
}
int GetIsManeuverExpended(object oPC, int nList, int nMoveId)
{
// Counting through the local ints to determine if this one is expended
int i, nMax = GetLocalInt(oPC, "ManeuverExpended" + IntToString(nList));
for(i = 1; i <= nMax; i++)
{
// returns if the maneuver is expended
if(GetLocalInt(oPC, "ManeuverExpended" + IntToString(nList) + IntToString(i)) == nMoveId)
{
if(DEBUG) DoDebug("tob_inc_recovery: GetIsManeuverExpended: " +IntToString(nMoveId));
return TRUE;
}
}
return FALSE;
}
void ExpendManeuver(object oPC, int nList, int nMoveId)
{
int nCount = GetLocalInt(oPC, "ManeuverExpended" + IntToString(nList)) + 1;
// This will mark the Maneuver Expended
SetLocalInt(oPC, "ManeuverExpended" + IntToString(nList) + IntToString(nCount), nMoveId);
SetLocalInt(oPC, "ManeuverExpended" + IntToString(nList), nCount);
if(DEBUG) DoDebug("tob_inc_recovery: Expending Maneuver: " + IntToString(nMoveId));
}
void RecoverExpendedManeuvers(object oPC, int nList)
{
if(DEBUG) DoDebug("tob_inc_recovery: Clearing expended maneuvers");
// Counting through the local ints to clear them all
int i, nMax = GetLocalInt(oPC, "ManeuverExpended" + IntToString(nList));
DeleteLocalInt(oPC, "ManeuverExpended" + IntToString(nList));
for(i = 1; i <= nMax; i++)
{
// Clear them all
DeleteLocalInt(oPC, "ManeuverExpended" + IntToString(nList) + IntToString(i));
}
// Do Grant/Withheld Maneuvers whenever this is called on a Crusader
if (nList == MANEUVER_LIST_CRUSADER)
{
// Make sure to clear them all first
ClearGrantedWithheldManeuvers(oPC);
// Then re-grant/withhold them
GrantManeuvers(oPC, nList);
}
if (GetHasFeat(FEAT_VITAL_RECOVERY, oPC)) VitalRecovery(oPC);
}
void RecoverManeuver(object oPC, int nList, int nMoveId)
{
// Counting through the local ints to determine if this one is expended
int i, nMax = GetLocalInt(oPC, "ManeuverExpended" + IntToString(nList));
for(i = 1; i <= nMax; i++)
{
// If it has been expended, clear that
if(GetLocalInt(oPC, "ManeuverExpended" + IntToString(nList) + IntToString(i)) == nMoveId)
{
DeleteLocalInt(oPC, "ManeuverExpended" + IntToString(nList) + IntToString(i));
if(DEBUG) DoDebug("tob_inc_recovery: Recovering Maneuver: " + IntToString(nMoveId));
}
}
if (GetHasFeat(FEAT_VITAL_RECOVERY, oPC)) VitalRecovery(oPC);
}
int GetIsWarbladeRecoveryRound(object oPC)
{
if(DEBUG) DoDebug("tob_inc_recovery: Warblade recovery check");
return GetLocalInt(oPC, "WarbladeRecoveryRound");
}
void GrantRandomManeuver(object oPC, int nList = MANEUVER_LIST_CRUSADER)
{
int nMax = GetLocalInt(oPC, "GrantRand#");
if(!nMax) return;//nothing to grant
SetLocalInt(oPC, "GrantRand#", nMax - 1);
int x = Random(nMax)+1;
int nMoveId = GetLocalInt(oPC, "GrantRand#" + IntToString(x));
if(x != nMax)
SetLocalInt(oPC, "GrantRand#" + IntToString(x), GetLocalInt(oPC, "GrantRand#" + IntToString(nMax)));
DeleteLocalInt(oPC, "GrantRand#" + IntToString(nMax));
//GrantWithheldManeuver(oPC, MANEUVER_LIST_CRUSADER, MoveId);
// No point in granting an expended maneuver
if(GetIsManeuverExpended(oPC, nList, nMoveId))
RecoverManeuver(oPC, nList, nMoveId);
int i = 1;
while(i)
{
// If it hits a non-valid, break
if(!GetLocalInt(oPC, "ManeuverGranted" + IntToString(i))) break;
i++;
}
SetLocalInt(oPC, "ManeuverGranted" + IntToString(i), nMoveId);
}
void ListGrantedManeuvers(object oPC)
{
int i;
for(i = 1; i <= 4; i++)
{
int nMoveId = GetLocalInt(oPC, "ManeuverGranted" + IntToString(i));
int nExpended = GetIsManeuverExpended(oPC, MANEUVER_LIST_CRUSADER, nMoveId);
if (nMoveId > 0 && !nExpended) FloatingTextStringOnCreature(GetManeuverName(nMoveId) + " is granted", oPC, FALSE);
}
}
void GrantManeuvers(object oPC, int nList = MANEUVER_LIST_CRUSADER)
{
// Only crusader level matters for this
int nLevel = GetLevelByClass(CLASS_TYPE_CRUSADER, oPC);
// 2das start at Row 0
int nGranted = StringToInt(Get2DACache(GetAMSKnownFileName(nList), "ManeuversGranted", nLevel-1));
nGranted += GetReadiedManeuversModifier(oPC, nList);
nGranted += GetHasFeat(FEAT_EXTRA_GRANTED_MANEUVER, oPC);
// Counting through the local ints to determine how many are readied
int i, nMaxReadied = GetReadiedCount(oPC, nList);
SetLocalInt(oPC, "GrantRand#", nMaxReadied);
for(i = 1; i <= nMaxReadied; i++)
{
// build temporary array for GrantRandomManeuver() function
int nMoveId = GetLocalInt(oPC, "ManeuverReadied" + IntToString(nList) + IntToString(i));
if(nMoveId)
SetLocalInt(oPC, "GrantRand#" + IntToString(i), nMoveId);
}
for(i = 1; i <= nGranted; i++)
{
GrantRandomManeuver(oPC);
}
ListGrantedManeuvers(oPC);
}
void ClearReadiedManeuvers(object oPC, int nList)
{
if(DEBUG) DoDebug("tob_inc_recovery: Clearing readied maneuvers");
// Counting through the local ints to clear them all
int i, nMax = GetReadiedCount(oPC, nList);
DeleteLocalInt(oPC, "ManeuverReadied" + IntToString(nList));
for(i = 1; i <= nMax; i++)
{
// Clear them all
DeleteLocalInt(oPC, "ManeuverReadied" + IntToString(nList) + IntToString(i));
}
}
/*void GrantWithheldManeuver(object oPC, int nList, int nMoveId = -1)
{
int i;
string sPsiFile = GetAMSKnownFileName(nList);
// 2das start at Row 0
int nLevel = GetInitiatorLevel(oPC, nList);
int nGranted = StringToInt(Get2DACache(sPsiFile, "ManeuversGranted", nLevel-1));
int nReadied = StringToInt(Get2DACache(sPsiFile, "ManeuversReadied", nLevel-1));
if(DEBUG) DoDebug("tob_inc_recovery: Maneuvers Granted: " + IntToString(nGranted));
if(DEBUG) DoDebug("tob_inc_recovery: Maneuvers Readied: " + IntToString(nReadied));
// If someone input a maneuver
if (nMoveId > 0)
{
// No point in granting an expended maneuver
if (GetIsManeuverExpended(oPC, nList, nMoveId))
RecoverManeuver(oPC, nList, nMoveId);
// 3 is always the number withheld
for(i = nGranted; i < nReadied; i++)
{
// Making sure it gets marked properly
int nGrantId = GetLocalInt(oPC, "ManeuverWithheld" + IntToString(i));
// If it exists, mark it as ready and break out
if (nMoveId == nGrantId)
{
if(DEBUG) DoDebug("tob_inc_recovery: Withheld Maneuver Granted: " + IntToString(nMoveId));
DeleteLocalInt(oPC, "ManeuverWithheld" + IntToString(i));
FloatingTextStringOnCreature(GetManeuverName(nMoveId) + " is granted", oPC, FALSE);
SetLocalInt(oPC, "ManeuverGranted" + IntToString(i), nMoveId);
break;
}
}
}
else
{
// 3 is always the number withheld
for(i = nGranted; i < nReadied; i++)
{
nMoveId = GetLocalInt(oPC, "ManeuverWithheld" + IntToString(i));
// If it exists, mark it as ready and break out
if (nMoveId > 0)
{
if(DEBUG) DoDebug("tob_inc_recovery: Withheld Maneuver Granted: " + IntToString(nMoveId));
DeleteLocalInt(oPC, "ManeuverWithheld" + IntToString(i));
FloatingTextStringOnCreature(GetManeuverName(nMoveId) + " is granted", oPC, FALSE);
SetLocalInt(oPC, "ManeuverGranted" + IntToString(i), nMoveId);
break;
}
}
}
}*/
int GetIsManeuverGranted(object oPC, int nMoveId)
{
if(DEBUG) DoDebug("tob_inc_recovery: GetIsManeuverGranted Start");
// Counting through the local ints to determine if this one is expended
int i, nMax = GetReadiedCount(oPC, MANEUVER_LIST_CRUSADER);
for(i = 1; i <= nMax; i++)
{
// returns if the maneuver is expended
if(GetLocalInt(oPC, "ManeuverGranted" + IntToString(i)) == nMoveId)
{
if(DEBUG) DoDebug("tob_inc_recovery: GetIsManeuverGranted: " + IntToString(nMoveId));
return TRUE;
}
}
return FALSE;
}
void ClearGrantedWithheldManeuvers(object oPC)
{
if(DEBUG) DoDebug("tob_inc_recovery: Clearing Granted and Withheld Maneuvers");
// Counting through the local ints to clear them all
int i, nMax = GetReadiedCount(oPC, MANEUVER_LIST_CRUSADER);
for(i = 1; i <= nMax; i++)
{
// Clear them all
DeleteLocalInt(oPC, "ManeuverGranted" + IntToString(i));
}
}
void BeginCrusaderGranting(object oPC)
{
if(DEBUG) DoDebug("BeginCrusaderGranting(): Entered Function");
// Stops it from being called more than once.
if(GetLocalInt(oPC, "CrusaderGrantLoop")) return;
SetLocalInt(oPC, "CrusaderGrantLoop", TRUE);
// Starts the granting process
if(DEBUG) DoDebug("BeginCrusaderGranting(): DoCrusaderGranting called");
DoCrusaderGranting(oPC, 1);
}
void DoCrusaderGranting(object oPC, int nTrip)
{
if(DEBUG) DoDebug("DoCrusaderGranting(): Entered Function on Round #" + IntToString(nTrip));
// First round of combat, no granting.
// Last round of the 5, clear and recover/grant maneuvers
if (nTrip >= 5) // Granted maneuvers empty, restart
{
if(DEBUG) DoDebug("DoCrusaderGranting(): RecoverExpendedManeuvers");
RecoverExpendedManeuvers(oPC, MANEUVER_LIST_CRUSADER);
nTrip = 1;
}
else if (nTrip > 1)
{
// Rounds 2-4, grant a single maneuver
if(DEBUG) DoDebug("DoCrusaderGranting(): GrantWithheldManeuver");
//GrantWithheldManeuver(oPC, MANEUVER_LIST_CRUSADER);
GrantRandomManeuver(oPC);
ListGrantedManeuvers(oPC);
}
if(DEBUG) DoDebug("DoCrusaderGranting(): Above Recursive");
// If in combat, keep the loop going
if (GetIsInCombat(oPC))
{
if(DEBUG) DoDebug("DoCrusaderGranting(): In Combat");
DelayCommand(6.0, DoCrusaderGranting(oPC, ++nTrip)); // Increment counter
}
else // Recover and stop loop otherwise.
{
if(DEBUG) DoDebug("DoCrusaderGranting(): Out of Combat Maneuver Recovery");
RecoverExpendedManeuvers(oPC, MANEUVER_LIST_CRUSADER);
// Resent Int for next time out
DeleteLocalInt(oPC, "CrusaderGrantLoop");
}
if(DEBUG) DoDebug("DoCrusaderGranting(): Ending");
}
int ExpendRandomManeuver(object oPC, int nList, int nDiscipline = -1)
{
// Counting through the local ints to determine if maneuver can be expended
int i, nMax = GetReadiedCount(oPC, nList);
for(i = 1; i <= nMax; i++)
{
// If the value is valid, next step
int nMoveId = GetLocalInt(oPC, "ManeuverReadied" + IntToString(nList) + IntToString(i));
if(nMoveId > 0)
{
// Make sure the disciplines match
if(nDiscipline == -1 || GetDisciplineByManeuver(nMoveId) == nDiscipline)
{
// If not expended
if(!GetIsManeuverExpended(oPC, nList, nMoveId))
{
// Expend the damn thing and go home
ExpendManeuver(oPC, nList, nMoveId);
return TRUE;
}
}
}
}
// If we're here, failed.
return FALSE;
}
void RecoverPrCAbilities(object oPC)
{
int i;
for(i = 2; i <= 8; i++) // PrC abilities: check last seven slots
{
int nClass = GetClassByPosition(i, oPC);
if(DEBUG) DoDebug("RecoverPrCAbilities" + IntToString(nClass));
switch(nClass)
{
case CLASS_TYPE_INVALID:
if(DEBUG) DoDebug("RecoverPrCAbilities: no class to recover");
break;
case CLASS_TYPE_JADE_PHOENIX_MAGE:
DeleteLocalInt(oPC, "JPM_Empowering_Strike_Expended");
DeleteLocalInt(oPC, "JPM_Quickening_Strike_Expended");
break;
case CLASS_TYPE_DEEPSTONE_SENTINEL:
DeleteLocalInt(oPC, "DPST_Awaken_Stone_Dragon_Expended");
break;
case CLASS_TYPE_ETERNAL_BLADE:
DeleteLocalInt(oPC, "ETBL_Eternal_Training_Expended");
DeleteLocalInt(oPC, "ETBL_Island_In_Time_Expended");
// Remove bonus to racial type from eternal training
PRCRemoveEffectsFromSpell(oPC, ETBL_RACIAL_TYPE);
break;
}
}
}
void VitalRecovery(object oPC)
{
if (GetLocalInt(oPC, "VitalRecovery")) return; //Once a minute
int nHD = GetHitDice(oPC);
effect eHeal = EffectHeal(nHD+3); // That's it
effect eVis = EffectVisualEffect(VFX_IMP_HEALING_M);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oPC);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
SetLocalInt(oPC, "VitalRecovery", TRUE);
DelayCommand(60.0, DeleteLocalInt(oPC, "VitalRecovery"));
}