// Hellcat OnUserDefined // 05.28.04 // by Invizible420 // Hellcat Heartbeat script // 04.28.05 // by Invizible420 // Line 129 - 132 you can configure the chances to grapple and rake #include "inc_utility" // Colors object oCOLOR_OBJ = GetObjectByTag("i420_COLOR_OBJ"); string COLOR_RED = GetStringLeft(GetName(oCOLOR_OBJ),6); string COLOR_BLUE = GetStringRight(GetName(oCOLOR_OBJ),6); // Debugger //int DEBUG = FALSE; void DB(string sDebug) { if (DEBUG == TRUE) SendMessageToPC(GetFirstPC(), sDebug); } // Function that is used to determine if a PC is in the area, to save HB CPU cycles int GetIsPCInArea(object oArea) { int iRValue = FALSE; object oPC = GetFirstPC(); while(GetIsObjectValid(oPC) == TRUE) { if (GetArea(oPC) == oArea && GetIsDead(oPC) != TRUE) iRValue = TRUE; oPC = GetNextPC(); } return iRValue; } int GetHasEffect(object oCreature, effect eEffect) { int iRValue = FALSE; effect e1stEffect = GetFirstEffect(oCreature); while (GetIsEffectValid(e1stEffect) == TRUE) { if (e1stEffect == eEffect) iRValue = TRUE; e1stEffect = GetNextEffect(oCreature); } return iRValue; } void DoGrapple(object oTarget, object oGrappler, int iRakeChance, int iRakeAmount) { if (GetLocalInt(oTarget, "AoO_SUCCESS") != 1) { DB(GetName(oTarget)+" missed the Attack of Opportunity"); // Debug Line // Grapple Vars for formula calculation int iGrapplerAtkBonus = GetBaseAttackBonus(OBJECT_SELF); int iTargetAtkBonus = GetBaseAttackBonus(oTarget); int iGrapplersStrMod = GetAbilityModifier(ABILITY_STRENGTH, OBJECT_SELF); int iTargetsStrMod = GetAbilityModifier(ABILITY_STRENGTH, oTarget); int iTempTargetSize = GetCreatureSize(oTarget); int iTargetSize; switch(iTempTargetSize) { case CREATURE_SIZE_HUGE: iTargetSize = 5; case CREATURE_SIZE_INVALID: iTargetSize = 0; case CREATURE_SIZE_LARGE: iTargetSize = 4; case CREATURE_SIZE_MEDIUM: iTargetSize = 3; case CREATURE_SIZE_SMALL: iTargetSize = 2; case CREATURE_SIZE_TINY: iTargetSize = 1; } int id20 = d20(1); int id20_2 = d20(1); // Grapple Check Formulas int iGrapplersGCheck = id20_2+iGrapplerAtkBonus+iGrapplersStrMod+4; // 4 because the Hellcat is a large creature int iTargetGCheck = id20+iTargetAtkBonus+iTargetsStrMod+iTargetSize; // PC's grapple check DB(GetName(oTarget)+"'s GCheck = "+IntToString(iTargetGCheck)+" versus "+GetName(OBJECT_SELF)+"'s GCheck = "+IntToString(iGrapplersGCheck)); if (GetIsImmune(oTarget, IMMUNITY_TYPE_KNOCKDOWN) == TRUE) { DeleteLocalInt(oTarget, "AoO_SUCCESS"); DeleteLocalInt(oTarget, "AoO_TO_RESIST_GRAPPLE"); DeleteLocalObject(OBJECT_SELF,"IS_GRAPPLING"); // removed this feedback... not necessary // SendMessageToPC(oTarget, "Immunity to knockdown resists the grapple attempt from the "+GetName(oGrappler)+"."); } else if (iGrapplersGCheck > iTargetGCheck) { SetLocalObject(oGrappler, "IS_GRAPPLING", oTarget); SendMessageToPC(oTarget,COLOR_BLUE+GetName(oTarget)+"'s Grapple Check vs. "+GetName(OBJECT_SELF)+"'s : *failure* ("+IntToString(iTargetGCheck)+" vs. "+IntToString(iGrapplersGCheck)+")"); ActionAttack(oTarget); ActionForceMoveToObject(oTarget, TRUE, 0.25, 0.25); AssignCommand(oTarget, ActionDoCommand(ActionForceMoveToObject(oGrappler,TRUE,0.25,0.25))); // knock down the PC for 1 round, and set int to say they are grappled and held ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectKnockdown(), oTarget, 6.0); // Do Rake Stuff if (iRakeChance > d100(1)) { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_COM_BLOOD_REG_RED), oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(iRakeAmount,DAMAGE_TYPE_PIERCING), oTarget); } } else { // per d&d 3rd ed... if the PC wins the grapple check 1d3 damage to other SendMessageToPC(oTarget,COLOR_BLUE+GetName(oTarget)+"'s Grapple Check vs. "+GetName(OBJECT_SELF)+"'s : *success* ("+IntToString(iTargetGCheck)+" vs. "+IntToString(iGrapplersGCheck)+")"); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d3(1),DAMAGE_TYPE_BLUDGEONING), OBJECT_SELF); DeleteLocalInt(oTarget, "AoO_SUCCESS"); DeleteLocalInt(oTarget, "AoO_TO_RESIST_GRAPPLE"); DeleteLocalObject(OBJECT_SELF,"IS_GRAPPLING"); } } else { FloatingTextStringOnCreature("Attack of Opportunity",oTarget,FALSE); AssignCommand(oTarget,ActionAttack(OBJECT_SELF)); DeleteLocalInt(oTarget, "AoO_SUCCESS"); DeleteLocalInt(oTarget, "AoO_TO_RESIST_GRAPPLE"); DeleteLocalObject(OBJECT_SELF,"IS_GRAPPLING"); } } int iEventNum = GetUserDefinedEventNumber(); void main() { int DO_GRAPPLE_RAKE = TRUE; // Set to False and OBJECT_SELF will not do grapple and rake stuff int GRAPPLE_CHANCE = 25; // Chance when bite is used OBJECT_SELF will grapple int RAKE_CHANCE = 50; // Chance OBJECT_SELF will rake while grappling int RAKE_DMG = d4(1)+3; // Rake damage switch(iEventNum) { case 1001: // Called by OnHeartbeat if(GetLocalObject(OBJECT_SELF, "IS_GRAPPLING") != OBJECT_INVALID && GetIsDead(GetLocalObject(OBJECT_SELF, "IS_GRAPPLING")) != TRUE) { object oPC = GetLocalObject(OBJECT_SELF, "IS_GRAPPLING"); ActionForceMoveToObject(oPC,TRUE,0.5,0.5); SendMessageToPC(oPC,COLOR_RED+"The "+GetName(OBJECT_SELF)+" holds on to you."); DeleteLocalInt(oPC,"AoO_SUCCESS"); DoGrapple(oPC, OBJECT_SELF, RAKE_CHANCE, RAKE_DMG); } else if(GetLocalObject(OBJECT_SELF, "IS_GRAPPLING") != OBJECT_INVALID && GetIsDead(GetLocalObject(OBJECT_SELF, "IS_GRAPPLING")) == TRUE) { DeleteLocalInt(GetLocalObject(OBJECT_SELF,"IS_GRAPPLING"), "AoO_SUCCESS"); DeleteLocalInt(GetLocalObject(OBJECT_SELF,"IS_GRAPPLING"), "AoO_TO_RESIST_GRAPPLE"); DeleteLocalInt(GetLocalObject(OBJECT_SELF, "LAST_ATTACKER"), "AoO_SUCCESS"); DeleteLocalInt(GetLocalObject(OBJECT_SELF, "LAST_ATTACKER"), "AoO_TO_RESIST_GRAPPLE"); DeleteLocalObject(OBJECT_SELF,"IS_GRAPPLING"); DeleteLocalObject(OBJECT_SELF,"IS_GRAPPLING"); DeleteLocalObject(OBJECT_SELF, "LAST_ATTACKER"); } // Run script only if a PC is in the area if (GetIsPCInArea(GetArea(OBJECT_SELF)) == TRUE) { DB("PC_IN_AREA"); // Debug Line // Vars to find the numerical location of OBJECT_SELF object oArea = GetArea(OBJECT_SELF); vector vPos = GetPosition(OBJECT_SELF); float fFace = GetFacing(OBJECT_SELF); location lLoc = Location(oArea, vPos, fFace); int iLight1 = GetTileSourceLight1Color(lLoc); int iLight2 = GetTileSourceLight2Color(lLoc); int iMLight1 = GetTileMainLight1Color(lLoc); int iMLight2 = GetTileMainLight2Color(lLoc); DB("iLight1 = "+IntToString(iLight1)); // Debug Line DB("iLight2 = "+IntToString(iLight1)); // Debug Line DB("iMLight1 = "+IntToString(iLight1)); // Debug Line DB("iMLight2 = "+IntToString(iLight1)); // Debug Line // Remove of Apply Invisibility if light is on OBJECT_SELF or not if (iLight1 != TILE_SOURCE_LIGHT_COLOR_WHITE || iLight1 != TILE_SOURCE_LIGHT_COLOR_PALE_YELLOW || iLight2 != TILE_SOURCE_LIGHT_COLOR_WHITE || iLight2 != TILE_SOURCE_LIGHT_COLOR_PALE_YELLOW || iMLight1 != TILE_MAIN_LIGHT_COLOR_YELLOW || iMLight1 != TILE_MAIN_LIGHT_COLOR_PALE_YELLOW || iMLight1 != TILE_MAIN_LIGHT_COLOR_DIM_WHITE || iMLight1 != TILE_MAIN_LIGHT_COLOR_BRIGHT_WHITE || iMLight2 != TILE_MAIN_LIGHT_COLOR_YELLOW || iMLight2 != TILE_MAIN_LIGHT_COLOR_PALE_YELLOW || iMLight2 != TILE_MAIN_LIGHT_COLOR_DIM_WHITE || iMLight2 != TILE_MAIN_LIGHT_COLOR_BRIGHT_WHITE) { RemoveEffect(OBJECT_SELF, EffectVisualEffect(VFX_DUR_INVISIBILITY)); } else if(GetHasEffect(OBJECT_SELF, EffectVisualEffect(VFX_DUR_INVISIBILITY)) == FALSE) { ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectVisualEffect(VFX_DUR_INVISIBILITY), OBJECT_SELF); } // Grapple and Rake Stuff if (GetIsInCombat(OBJECT_SELF) == TRUE && DO_GRAPPLE_RAKE == TRUE) { object oLastAttacker = GetLocalObject(OBJECT_SELF, "LAST_ATTACKER"); DB(GetName(OBJECT_SELF)+" is in combat with "+GetName(oLastAttacker)); // Debug Line if (GetDistanceBetween(oLastAttacker, OBJECT_SELF) <= 5.0) { int iMeleeTouch = TouchAttackMelee(oLastAttacker, TRUE); DB(GetName(OBJECT_SELF)+"'s Melee Touch Attack = "+IntToString(iMeleeTouch)); // Debug Line // Grapple if (GRAPPLE_CHANCE > d100(1) && iMeleeTouch >= 1 && GetLocalInt(oLastAttacker, "IS_GRAPPLED") != 1) { ActionUseSkill(SKILL_TAUNT, oLastAttacker); SetLocalInt(oLastAttacker, "AoO_TO_RESIST_GRAPPLE",1); DoGrapple(oLastAttacker, OBJECT_SELF, RAKE_CHANCE, RAKE_DMG); } } else DeleteLocalObject(OBJECT_SELF, "LAST_ATTACKER"); } } break; // case 1002: // Called by OnPerception SetLocalObject(OBJECT_SELF, "LAST_ATTACKER", GetLastPerceived()); break; case 1005: // Called by Attack SetLocalObject(OBJECT_SELF, "LAST_ATTACKER", GetLastAttacker()); break; case 1006: if (GetLocalInt(GetLastDamager(OBJECT_SELF), "AoO_TO_RESIST_GRAPPLE") == 1) SetLocalInt(GetLastDamager(OBJECT_SELF), "AoO_SUCCESS", 1); break; case 1007: DelayCommand(4.0,ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD),OBJECT_SELF)); break; case 1010: SetLocalObject(OBJECT_SELF, "LAST_ATTACKER", GetLastSpellCaster()); break; } }