//Mr. E. Mustard's Injury System /* Injury array notes: 1, Right Arm Mangled 2, Left Arm Mangled 3, Reduced Dex Due to Right Arm Injury 4, Reduced Dex Due to Left Arm Injury 5, Reduced Con Due to Chest Injury 6, Slow Effect Due to Leg Injury */ #include "x2_inc_intweapon" #include "nw_o0_itemmaker" //Constants const int InjureDam = 10; //Amount of damage required to cause an injury const int DeathDam = 20; //Amount of damage required to cause death blows const int HealTime = 6; /*Determines how long after first rest it takes to recover from an injury*/ /*Applies reduced strength if hp is low enough following a successful hit*/ void j_weaken(object oTarget) { int iWeak = GetLocalInt(oTarget, "iWeaken"); effect eWeaken = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_STRENGTH, (iWeak+1))); int iHP = GetCurrentHitPoints(oTarget); int iMaxHP = GetMaxHitPoints(oTarget); object oPC = oTarget; if(!GetIsPC(oPC)) oPC = GetFirstPC(); /*The following switch is designed to weaken the character's strength gradually as health drops.*/ if(iWeak < 4)//No further weakening allowed, so no sense running the switch { switch(iWeak) { case 0: if (iHP < iMaxHP/2 && iWeak < 1) { SendMessageToPC(oPC, GetName(oTarget) + "'s strenght is waning!"); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWeaken, oTarget); SetLocalInt(oTarget, "iWeaken", 1); } break; case 1: if (iHP < iMaxHP*2/5 && iWeak < 2) { SendMessageToPC(oPC, GetName(oTarget) + "'s strenght is waning!"); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWeaken, oTarget); SetLocalInt(oTarget, "iWeaken", 2); } break; case 2: if (iHP < iMaxHP*3/10 && iWeak < 3) { SendMessageToPC(oPC, GetName(oTarget) + "'s strenght is waning!"); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWeaken, oTarget); SetLocalInt(oTarget, "iWeaken", 3); } break; case 3: if (iHP < iMaxHP*1/5) { SendMessageToPC(oPC, GetName(oTarget) + "'s strenght is waning!"); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWeaken, oTarget); SetLocalInt(oTarget, "iWeaken", 4); } break; } } } /*Applies an 'injury' if a hit does more than 10 points of damage (default). Also, instant death is possible if the damage is > 19 (default). (20% chance if dmg > DeathDam)*/ void j_injure(object oTarget) { //effect eVis = EffectVisualEffect(VFX_IMP_NEGATIVE_ENERGY); /*No bones, but red energy instead of blood*/ effect eVis = EffectVisualEffect(VFX_COM_CHUNK_RED_SMALL); /*Bones fly out... a little odd*/ int iHP = GetCurrentHitPoints(oTarget); int iDam = GetLocalInt(oTarget, "iOldHP")-iHP; object oPC; //Adjust old HP to reflect the damage just done SetLocalInt(oTarget, "iOldHP", iHP); if(GetIsPC(oTarget)) oPC = oTarget; else oPC = GetFirstPC(); PrintString("The damage done to " + GetTag(oTarget) + " is: "); PrintInteger(iDam); // SendMessageToPC(oPC, "Damage is " + IntToString(iDam)); if(iDam>=InjureDam) { ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget); //Switch determines the type of injury sustained switch(d20()) { //Head wound (10% chance) //50% chance that wound is fatal, otherwise daze effect applied case 1: case 2: if(d2()==1 && GetLocalInt(oTarget, "iAllowDeath")==1 && iDam >= DeathDam) { effect eDeath = EffectDeath(TRUE); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oTarget); SendMessageToPC(oPC, GetName(oTarget) + " suffers a FATAL head wound!"); } else { effect eDaze = EffectDazed(); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDaze, oTarget, 5.0); SendMessageToPC(oPC, GetName(oTarget) + " suffers from a concussion!"); } PrintString("The injury is head wound."); break; /*Chest wound (%30 chance) 50% chance that chest wound is fatal(default), otherwise Con drops by 2. Also, there's no limit to the Con reduction, so repeated injury can be fatal.*/ case 3: case 4: case 5: case 6: case 7: case 8: if(d2()==1 && GetLocalInt(oTarget, "iAllowDeath")==1 && iDam >= DeathDam) { effect eDeath = EffectDeath(TRUE); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oTarget); SendMessageToPC(oPC, GetName(oTarget) + " recieves a FATAL chest wound!"); } else { int iChestWound = GetLocalArrayInt(oTarget, "injury", 5); effect eInternal = SupernaturalEffect(EffectAbilityDecrease(ABILITY_CONSTITUTION, 2+2*iChestWound)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eInternal, oTarget); SendMessageToPC(oPC, GetName(oTarget) + " suffers a chest wound that reduces stamina!"); SetLocalArrayInt(oTarget, "injury", 5, 1+iChestWound); DelayCommand(0.25, SetLocalInt(oTarget, "iOldHP", GetCurrentHitPoints(oTarget))); } PrintString("The injury is chest wound."); break; /*Right arm wound (15% chance) 33.33% chance that it disarms and prevents usage of an arm Reduces Dex by 1 to a max of 3, if mangled max reduction applied Note: the two arm injury cases are exceedingly messy... sorry!*/ case 9: case 10: case 11: //Checks if right arm is already mangled if(GetLocalArrayInt(oTarget, "injury", 1)==0) { int iReducedRTL = GetLocalArrayInt(oTarget, "injury", 4); int iReducedRTR = GetLocalArrayInt(oTarget, "injury", 3); //switch determines whether arm is mangled or just Dex penalty if(d3()==1) { if(GetIsPC(oTarget)) AssignCommand(oTarget, ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget))); else //AI script will just re-equip, so we destroy the weapon DestroyObject(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget)); SendMessageToPC(oPC, GetName(oTarget) + "'s right arm has been mangled!"); SetLocalArrayInt(oTarget, "injury", 1, 1); if(iReducedRTR < 3) //Maximize right arm Dex penalty { effect eRArm = SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 3 + iReducedRTL)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eRArm, oTarget); SetLocalArrayInt(oTarget, "injury", 3, 3); } } //Only apply a penalty for arm injury if penalty does not exceed 3 else if(iReducedRTR < 3) { effect eRArm = SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 1+iReducedRTR+iReducedRTL)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eRArm, oTarget); SendMessageToPC(oPC, GetName(oTarget) + " suffers an arm wound that reduces reaction time!"); SetLocalArrayInt(oTarget, "injury", 3, 1+iReducedRTR); } } PrintString("The injury is right arm wound."); break; //Left arm wound (15% chance) //33.33% chance that it disarms and prevents usage of an arm //Reduces Dex by 1 to a max of 3, if mangled max reduction applied case 12: case 13: case 14: //Checks if left arm is mangled already if(GetLocalArrayInt(oTarget, "injury", 2)==0) { int iReducedRTL = GetLocalArrayInt(oTarget, "injury", 4); int iReducedRTR = GetLocalArrayInt(oTarget, "injury", 3); if(d3()==1) { object oWeapon = GetLastWeaponUsed(oTarget); if(GetIsPC(oTarget)) { //If weapon is two-handed, prevent equiping if(MatchDoubleHandedWeapon(oWeapon)) AssignCommand(oTarget, ActionUnequipItem(oWeapon)); else AssignCommand(oTarget, ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget))); } else //AI script will just re-equip, so we destroy the weapon/shield { if(MatchDoubleHandedWeapon(oWeapon)) DestroyObject(oWeapon); else DestroyObject(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget)); } SendMessageToPC(oPC, GetName(oTarget) + "'s left arm has been mangled!"); SetLocalArrayInt(oTarget, "injury", 2, 1); if(iReducedRTL < 3) { effect eRArm = SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 3+iReducedRTR)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eRArm, oTarget); SetLocalArrayInt(oTarget, "injury", 4, 3); } } else if(iReducedRTL < 3) { effect eLArm = SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, (1+iReducedRTL+iReducedRTR))); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLArm, oTarget); SendMessageToPC(oPC, GetName(oTarget) + " recieves an arm wound!"); SetLocalArrayInt(oTarget, "injury", 4, iReducedRTL+1); } } PrintString("The injury is left arm wound."); break; //Leg wound (%30 chance) //Applies slow effect and has a 33.33% chance of causing knockdown default: if(GetLocalArrayInt(oTarget, "injury", 6) == 0) { effect eSlow = SupernaturalEffect(EffectSlow()); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSlow, oTarget); SendMessageToPC(oPC, GetName(oTarget) + " recieves a leg wound and suffers hindered movement!"); SetLocalArrayInt(oTarget, "injury", 6, 1); } if(d3()==1) { effect eKnockdown = EffectKnockdown(); ApplyEffectToObject(DURATION_TYPE_INSTANT, eKnockdown, oTarget); SendMessageToPC(oPC, GetName(oTarget) + " stumbles due to a leg injury!"); } break; PrintString("The injury is leg wound."); } } } /*Mangled check- prevents equiping items requiring the damaged arm/hand*/ void j_mangle_chk(object oPC, object oItem) { if(GetLocalArrayInt(oPC, "injury", 1)==1) { ClearAllActions(FALSE); AssignCommand(oPC, ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC))); FloatingTextStringOnCreature("Your right arm is injured and cannot wield a weapon.", oPC); } if(GetLocalArrayInt(oPC, "injury", 2)==1) { ClearAllActions(FALSE); if(MatchDoubleHandedWeapon(oItem)) AssignCommand(oPC, ActionUnequipItem(oItem)); else AssignCommand(oPC, ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC))); FloatingTextStringOnCreature("Your left arm is injured and cannot wield an item.", oPC); } } /* return the current time in hours */ int GetCurrentTimeStamp() { return ( GetCalendarYear() * 8064 ) + ( GetCalendarMonth() * 672 ) + ( GetCalendarDay() * 24 ) + ( GetTimeHour()); } /*Removes injury effects*/ void injury_mend(object oPC, int iInjury) { /*used to re-apply injuries that shouldn't be healed*/ int iWound = GetLocalArrayInt(oPC, "injury", 5); int iRWound = GetLocalArrayInt(oPC, "injury", 3); int iLWound = GetLocalArrayInt(oPC, "injury", 4); effect e; //Set local variable to indicate the injury is gone SetLocalArrayInt(oPC, "injury", iInjury, 0); //Reset Injury Date so that next rest will set new injury dates SetLocalArrayInt(oPC, "iInjuryDate", iInjury, 0); SendMessageToPC(oPC, "Injuries have mended!"); /*This switch, though messy, is needed to remove each type of injury*/ switch(iInjury) { case 1: case 2: break; case 3: e = GetFirstEffect(oPC); while (GetIsEffectValid(e)) { if (GetEffectType(e) == EFFECT_TYPE_ABILITY_DECREASE && GetEffectSubType(e) == SUBTYPE_SUPERNATURAL) RemoveEffect(oPC, e); e = GetNextEffect(oPC); } if(iWound > 0) //Re-apply chest wound if removed in previous 'while' statement { effect eWound = SupernaturalEffect(EffectAbilityDecrease(ABILITY_CONSTITUTION, 2*iWound)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWound, oPC); } if(iLWound > 0) //Re-apply left arm injury { effect eWound = SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, iLWound)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWound, oPC); } break; case 4: e = GetFirstEffect(oPC); while (GetIsEffectValid(e)) { if (GetEffectType(e) == EFFECT_TYPE_ABILITY_DECREASE && GetEffectSubType(e) == SUBTYPE_SUPERNATURAL) RemoveEffect(oPC, e); e = GetNextEffect(oPC); } if(iWound > 0) //Re-apply chest wound if removed in previous 'while' statement { effect eWound = SupernaturalEffect(EffectAbilityDecrease(ABILITY_CONSTITUTION, 2*iWound)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWound, oPC); } if(iRWound > 0) //Re-apply right arm injury { effect eWound = SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, iRWound)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWound, oPC); } break; case 5: e = GetFirstEffect(oPC); while (GetIsEffectValid(e)) { if (GetEffectType(e) == EFFECT_TYPE_ABILITY_DECREASE && GetEffectSubType(e) == SUBTYPE_SUPERNATURAL) RemoveEffect(oPC, e); e = GetNextEffect(oPC); } //Need to re-apply dextirity loss if(iRWound > 0 || iLWound > 0) { effect eWound = SupernaturalEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, iRWound+iLWound)); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eWound, oPC); } break; case 6: e = GetFirstEffect(oPC); while (GetIsEffectValid(e)) { if (GetEffectType(e) == EFFECT_TYPE_SLOW && GetEffectSubType(e) == SUBTYPE_SUPERNATURAL) RemoveEffect(oPC, e); e = GetNextEffect(oPC); } break; default: break; } } /*Calculates when injury occured and whether enough time has passed for it to heal*/ void injury_mend_chk(object oPC) { /*Set hour of injury to the first rest after recieving it In RP terms, I'm thinking the injury can't begin to heal until stabilized via rest)*/ int i; int iTime = GetCurrentTimeStamp(); for(i = 1; i <= 6; i++) { //Checks for injury... if(GetLocalArrayInt(oPC, "injury", i) > 0) //Now check whether rest as occured since the injury if(GetLocalArrayInt(oPC, "iInjuryDate", i) == 0) //Set the current time as the first rest since injury SetLocalArrayInt(oPC, "iInjuryDate", i, iTime); //Finally, determine if enough time as passed for the injury to "mend" else if((GetLocalArrayInt(oPC, "iInjuryDate", i)+ HealTime) <= iTime) injury_mend(oPC, i); } } //void main(){}