Updated AMS marker feats. Removed arcane & divine marker feats. Updated Dread Necromancer for epic progression. Updated weapon baseitem models. Updated new weapons for crafting & npc equip. Updated prefix. Updated release archive.
228 lines
7.8 KiB
Plaintext
228 lines
7.8 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
// VARIABLE DECLARATIONS
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
const string PRC_Rest_Generation = "PRC_Rest_Generation";
|
|
const string PRC_Rest_Generation_Check = "PRC_Rest_Generation_Check";
|
|
const string PRC_ForcedRestDetector_Generation = "PRC_ForcedRestDetector_Generation";
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// INCLUDES
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "prc_alterations"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION DECLARATIONS
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Returns the number of henchmen a player has.
|
|
int GetNumHenchmen(object oPC);
|
|
|
|
// returns the float time in seconds to close the given distance
|
|
float GetTimeToCloseDistance(float fMeters, object oPC, int bIsRunning = FALSE);
|
|
|
|
/* PRC ForceRest wrapper
|
|
*
|
|
* ForceRest does not trigger the module's OnRest event, nor will the targeted player show up
|
|
* when GetLastPCRested is used. This wrapper can be used to ForceRest a target, while still
|
|
* running the PRC's OnRest script.
|
|
*/
|
|
void PRCForceRest(object oPC);
|
|
void PRCForceRested(object oPC);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION DEFINITIONS
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
int GetNumHenchmen(object oPC)
|
|
{
|
|
if (!GetIsPC(oPC)) return -1;
|
|
|
|
int nLoop, nCount;
|
|
for (nLoop = 1; nLoop <= GetMaxHenchmen(); nLoop++)
|
|
{
|
|
if (GetIsObjectValid(GetHenchman(oPC, nLoop)))
|
|
nCount++;
|
|
}
|
|
|
|
return nCount;
|
|
}
|
|
|
|
float GetTimeToCloseDistance(float fMeters, object oPC, int bIsRunning = FALSE)
|
|
{
|
|
float fTime = 0.0;
|
|
float fSpeed = 0.0;
|
|
|
|
int iMoveRate = GetMovementRate(oPC);
|
|
|
|
switch(iMoveRate)
|
|
{
|
|
case 0:
|
|
fSpeed = 2.0;
|
|
break;
|
|
case 1:
|
|
fSpeed = 0.0;
|
|
break;
|
|
case 2:
|
|
fSpeed = 0.75;
|
|
break;
|
|
case 3:
|
|
fSpeed = 1.25;
|
|
break;
|
|
case 4:
|
|
fSpeed = 1.75;
|
|
break;
|
|
case 5:
|
|
fSpeed = 2.25;
|
|
break;
|
|
case 6:
|
|
fSpeed = 2.75;
|
|
break;
|
|
case 7:
|
|
fSpeed = 2.0; // could change to creature default in the appearance.2da.
|
|
break;
|
|
case 8:
|
|
fSpeed = 5.50;
|
|
break;
|
|
}
|
|
|
|
// movement speed doubled if running
|
|
if(bIsRunning) fSpeed *= 2.0;
|
|
|
|
// other effects that can change movement speed
|
|
if( PRCGetHasEffect(EFFECT_TYPE_HASTE, oPC) ) fSpeed *= 2.0;
|
|
if( PRCGetHasEffect(EFFECT_TYPE_MOVEMENT_SPEED_INCREASE, oPC) ) fSpeed *= 2.0;
|
|
|
|
if( PRCGetHasEffect(EFFECT_TYPE_SLOW, oPC) ) fSpeed /= 2.0;
|
|
if( PRCGetHasEffect(EFFECT_TYPE_MOVEMENT_SPEED_DECREASE, oPC) ) fSpeed /= 2.0;
|
|
|
|
if( GetHasFeat(FEAT_BARBARIAN_ENDURANCE, oPC) ) fSpeed *= 1.1; // 10% gain
|
|
if( GetHasFeat(FEAT_MONK_ENDURANCE, oPC) )
|
|
{
|
|
float fBonus = 0.1 * (GetLevelByClass(CLASS_TYPE_MONK, oPC) / 3 );
|
|
if (fBonus > 0.90) fBonus = 0.9;
|
|
|
|
fBonus += 1.0;
|
|
fSpeed *= fBonus;
|
|
}
|
|
|
|
// final calculation
|
|
fTime = fMeters / fSpeed;
|
|
|
|
return fTime;
|
|
}
|
|
|
|
int PRC_NextGeneration(int nCurrentGeneration)
|
|
{
|
|
nCurrentGeneration++;
|
|
if (nCurrentGeneration > 30000)
|
|
nCurrentGeneration = 1;
|
|
return nCurrentGeneration;
|
|
}
|
|
|
|
//TODO: TRIED THIS CLEANER VERSION AND IT DIDN'T WORK; FIX IT AND USE IT LATER
|
|
// effect _prc_inc_ForcedRestDetectorEffect()
|
|
// {
|
|
// //Create an extraordinary effect, which is removed only by resting.
|
|
// //Therefore, if it disappears, we know that resting has happened.
|
|
// return ExtraordinaryEffect(EffectVisualEffect(VFX_DUR_CESSATE_NEUTRAL));
|
|
// //TODO: this could match effects that are not ours. Make it more unique somehow.
|
|
// }
|
|
//
|
|
// void _prc_inc_ApplyForcedRestDetectorEffect(object oPC)
|
|
// {
|
|
// ApplyEffectToObject(DURATION_TYPE_PERMANENT, _prc_inc_ForcedRestDetectorEffect(), oPC);
|
|
// }
|
|
//
|
|
// int _prc_inc_TestForcedRestDetectorEffect(effect eEffect)
|
|
// {
|
|
// effect eTestEffect = _prc_inc_ForcedRestDetectorEffect();
|
|
// return GetEffectType(eEffect) == GetEffectType(eTestEffect) &&
|
|
// GetEffectSubType(eEffect) == GetEffectSubType(eTestEffect) &&
|
|
// GetEffectDurationType(eEffect) == GetEffectDurationType(eTestEffect) &&
|
|
// GetEffectSpellId(eEffect) == -1;
|
|
// }
|
|
|
|
void _prc_inc_ApplyForcedRestDetectorEffect(object oPC)
|
|
{
|
|
//Apply an extraordinary effect, which is removed only by resting
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ExtraordinaryEffect(EffectVisualEffect(VFX_DUR_CESSATE_NEUTRAL)), oPC);
|
|
//TODO: this could match effects that are not ours. Make it more unique somehow.
|
|
}
|
|
|
|
int _prc_inc_TestForcedRestDetectorEffect(effect eEffect)
|
|
{
|
|
return GetEffectType(eEffect) == EFFECT_TYPE_VISUALEFFECT && GetEffectSubType(eEffect) == SUBTYPE_EXTRAORDINARY && GetEffectDurationType(eEffect) == DURATION_TYPE_PERMANENT && GetEffectSpellId(eEffect) == -1;
|
|
//TODO: this could match effects that are not ours. Make it more unique somehow.
|
|
}
|
|
|
|
void _prc_inc_ForcedRestDetector(object oPC, int nExpectedGeneration)
|
|
{
|
|
int nGeneration = GetLocalInt(oPC, PRC_ForcedRestDetector_Generation);
|
|
if (nGeneration != nExpectedGeneration)
|
|
{
|
|
//There's another forced rest detector running, so stop ourselves and let that one continue
|
|
DoDebug("STOPPING DUPLICATE FORCED REST DETECTOR");
|
|
return;
|
|
}
|
|
nGeneration = PRC_NextGeneration(nGeneration);
|
|
SetLocalInt(oPC, PRC_ForcedRestDetector_Generation, nGeneration);
|
|
|
|
int nRestGeneration = GetLocalInt(oPC, PRC_Rest_Generation);
|
|
int nRestGenerationCheck = GetLocalInt(oPC, PRC_Rest_Generation_Check);
|
|
if (nRestGeneration != nRestGenerationCheck)
|
|
{
|
|
//A normal rest happened, and the delayed commands it schedules may still
|
|
//be executing or waiting to execute, so do nothing and check back later.
|
|
SetLocalInt(oPC, PRC_Rest_Generation_Check, nRestGeneration);
|
|
DelayCommand(10.0f, _prc_inc_ApplyForcedRestDetectorEffect(oPC));
|
|
DelayCommand(10.1f, _prc_inc_ForcedRestDetector(oPC, nGeneration));
|
|
}
|
|
else
|
|
{
|
|
int bFound = FALSE;
|
|
effect eEffect = GetFirstEffect(oPC);
|
|
while (GetIsEffectValid(eEffect))
|
|
{
|
|
if (_prc_inc_TestForcedRestDetectorEffect(eEffect))
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
eEffect = GetNextEffect(oPC);
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
DoDebug("FORCED REST DETECTED");
|
|
PRCForceRested(oPC); //This executes the normal resting code, which will be detected above the next time this function executes
|
|
}
|
|
|
|
//Schedule next check
|
|
DelayCommand(1.0f, _prc_inc_ForcedRestDetector(oPC, nGeneration));
|
|
}
|
|
}
|
|
|
|
void StartForcedRestDetector(object oPC)
|
|
{
|
|
//TODO: make a way for the detector to detect that forced rest has already happened, or else do it here now (but how?)
|
|
DoDebug("STARTING FORCED REST DETECTOR");
|
|
_prc_inc_ApplyForcedRestDetectorEffect(oPC);
|
|
SetLocalInt(oPC, PRC_Rest_Generation_Check, GetLocalInt(oPC, PRC_Rest_Generation));
|
|
int nGeneration = GetLocalInt(oPC, PRC_ForcedRestDetector_Generation);
|
|
DelayCommand(1.0f, _prc_inc_ForcedRestDetector(oPC, nGeneration));
|
|
}
|
|
|
|
void PRCForceRest(object oPC)
|
|
{
|
|
ForceRest(oPC);
|
|
PRCForceRested(oPC);
|
|
}
|
|
|
|
void PRCForceRested(object oPC)
|
|
{
|
|
//The PC has been forced rested--fix the problems this causes.
|
|
SetLocalInt(oPC, "PRC_ForceRested", 1);
|
|
ExecuteScript("prc_rest", oPC);
|
|
} |