//:://///////////////////////////////////////////// //:: Ability Damage special effects include //:: inc_abil_damage //::////////////////////////////////////////////// /** @file Implements the special effects of an ability score falling down to 0 as according to PnP. Strength: Lies helpless on ground (knockdown) Dexterity: Paralyzed Constitution: Death Intelligence: Coma (knockdown) Wisdom: Coma (knockdown) Charisma: Coma (knockdown) This can be turned off with a switch in prc_inc_switches : PRC_NO_PNP_ABILITY_DAMAGE NOTE: Due to BioOptimization (tm), Dex reaching 0 from above 3 when any other stat is already at 0 will result in Dex being considered restored at the same time the other stat is. This might be workable around, but not efficiently. */ //::////////////////////////////////////////////// //:: Created By: Ornedan //:: Created On: 09.04.2005 //:: Modified On: 25.06.2005 //::////////////////////////////////////////////// /* [00:55] <Stratovarius> yup [00:56] <Stratovarius> well, something to add [00:56] <Stratovarius> if KTTS reduces target to 0 (or would, i know NWN goes to 3) [00:56] <Stratovarius> drop a cutscene paralyze on em [00:56] <Stratovarius> and a long duration knockdown [01:00] <Ornedan> 'k. And spawn a pseudo-hb on them to do recovery if they ever regain the mental stat [01:01] <Ornedan> Also, test result: You lose spellcasting if your casting stat drops below the required, even if the reduction is a magical penalty [01:03] <Stratovarius> you do? cool */ ////////////////////////////////////////////////// /* Function prototypes */ ////////////////////////////////////////////////// // Internal function. Called by a threadscript. Handles checking if any ability that has reached 0 has been restored void AbilityDamageMonitor(); // Dex needs special handling due to the way CutsceneParalyze works (sets Dex to 3) void DoDexCheck(object oCreature, int bFirstPart = TRUE); ////////////////////////////////////////////////// /* Includes */ ////////////////////////////////////////////////// //#include "prc_inc_spells" #include "prc_inc_damage" //functions to apply damage ////////////////////////////////////////////////// /* Function defintions */ ////////////////////////////////////////////////// void AbilityDamageMonitor() { object oCreature = OBJECT_SELF; int nMonitoredAbilities = GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR); int nEffects = GetLocalInt(oCreature, ABILITY_DAMAGE_SPECIALS); if (DEBUG) DoDebug("AbilityDamageMonitor running"); // Check each of the monitored abilities if(nMonitoredAbilities & (1 << ABILITY_STRENGTH)) { if(GetAbilityScore(oCreature, ABILITY_STRENGTH) > 3) { DeleteLocalInt(oCreature, VIRTUAL_ABILITY_SCORE + IntToString(ABILITY_STRENGTH)); SetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR, GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR) ^ (1 << ABILITY_STRENGTH)); if (DEBUG) DoDebug("AbilityDamageMonitor Strength healed"); } } /*if(nMonitoredAbilities & (1 << ABILITY_DEXTERITY)) { if(GetAbilityScore(oCreature, ABILITY_DEXTERITY) > 3) { DeleteLocalInt(oCreature, VIRTUAL_ABILITY_SCORE + IntToString(ABILITY_DEXTERITY)); SetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR, GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR) ^ (1 << ABILITY_DEXTERITY)); } }*/ if(nMonitoredAbilities & (1 << ABILITY_INTELLIGENCE)) { if(GetAbilityScore(oCreature, ABILITY_INTELLIGENCE) > 3) { DeleteLocalInt(oCreature, VIRTUAL_ABILITY_SCORE + IntToString(ABILITY_INTELLIGENCE)); SetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR, GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR) ^ (1 << ABILITY_INTELLIGENCE)); if (DEBUG) DoDebug("AbilityDamageMonitor Int healed"); } } if(nMonitoredAbilities & (1 << ABILITY_WISDOM)) { if(GetAbilityScore(oCreature, ABILITY_WISDOM) > 3) { DeleteLocalInt(oCreature, VIRTUAL_ABILITY_SCORE + IntToString(ABILITY_WISDOM)); SetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR, GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR) ^ (1 << ABILITY_WISDOM)); if (DEBUG) DoDebug("AbilityDamageMonitor Wis healed"); } } if(nMonitoredAbilities & (1 << ABILITY_CHARISMA)) { if(GetAbilityScore(oCreature, ABILITY_CHARISMA) > 3) { DeleteLocalInt(oCreature, VIRTUAL_ABILITY_SCORE + IntToString(ABILITY_CHARISMA)); SetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR, GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR) ^ (1 << ABILITY_CHARISMA)); if (DEBUG) DoDebug("AbilityDamageMonitor Cha healed"); } } // Check which effects, if any, need to be removed int bRemovePara, bRemoveKnock; nMonitoredAbilities = GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR); if(!(nMonitoredAbilities & (1 << ABILITY_STRENGTH) || nMonitoredAbilities & (1 << ABILITY_INTELLIGENCE) || nMonitoredAbilities & (1 << ABILITY_WISDOM) || nMonitoredAbilities & (1 << ABILITY_CHARISMA) ) ) { // Only remove effects if they are present if(nEffects & ABILITY_DAMAGE_EFFECT_KNOCKDOWN) { bRemoveKnock = TRUE; nEffects ^= ABILITY_DAMAGE_EFFECT_KNOCKDOWN; } if(!(nMonitoredAbilities & (1 << ABILITY_DEXTERITY))) { if(nEffects & ABILITY_DAMAGE_EFFECT_PARALYZE) { bRemovePara = TRUE; nEffects ^= ABILITY_DAMAGE_EFFECT_KNOCKDOWN; } } // Dex is the only remaining stat keeping CutscenePara on, so run the dexcheck else DelayCommand(0.1f, DoDexCheck(oCreature, TRUE)); SetLocalInt(oCreature, ABILITY_DAMAGE_SPECIALS, nEffects); } if (DEBUG) DoDebug("AbilityDamageMonitor bRemovePara:" + IntToString(bRemovePara)); if (DEBUG) DoDebug("AbilityDamageMonitor bRemoveKnock:" + IntToString(bRemoveKnock)); // Do effect removal if(bRemovePara || bRemoveKnock) { effect eCheck = GetFirstEffect(oCreature); while(GetIsEffectValid(eCheck)) { if(bRemovePara && GetEffectType(eCheck) == EFFECT_TYPE_CUTSCENE_PARALYZE){ if (DEBUG) DoDebug("AbilityDamageMonitor Removed para"); RemoveEffect(oCreature, eCheck); } else if(bRemoveKnock && GetEffectType(eCheck) == 0){ RemoveEffect(oCreature, eCheck); if (DEBUG) DoDebug("AbilityDamageMonitor Removed knock"); } eCheck = GetNextEffect(oCreature); } } if (DEBUG) DoDebug("AbilityDamageMonitor Monitored abilities:" + IntToString(nMonitoredAbilities)); // Stop the thread if there is nothing to monitor anymore if(!nMonitoredAbilities) TerminateCurrentThread(); } void DoDexCheck(object oCreature, int bFirstPart = TRUE) { // Remove CutscenePara if(bFirstPart) { effect eCheck = GetFirstEffect(oCreature); while(GetIsEffectValid(eCheck)) { if(GetEffectType(eCheck) == EFFECT_TYPE_CUTSCENE_PARALYZE) RemoveEffect(oCreature, eCheck); eCheck = GetNextEffect(oCreature); } DelayCommand(0.1f, DoDexCheck(oCreature, FALSE)); if (DEBUG) DoDebug("First part ran"); } // Check if Dex is over 3 when it's gone else { // It is, so remove Dex from the monitored list if(GetAbilityScore(oCreature, ABILITY_DEXTERITY) > 3) { DeleteLocalInt(oCreature, VIRTUAL_ABILITY_SCORE + IntToString(ABILITY_DEXTERITY)); SetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR, GetLocalInt(oCreature, ABILITY_DAMAGE_MONITOR) ^ (1 << ABILITY_DEXTERITY)); if (DEBUG) DoDebug("Dex check +"); } /*else SendMessageToPC(GetFirstPC(), "Dex check -");*/ // Apply CutscenePara back in either case. Next monitor call will remove it if it's supposed to be gone ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectCutsceneParalyze(), oCreature); } } // Test main //void main(){}