#include "g_common" #include "prc_inc_spells" //////////////////////////////////////////////////////////////////////////////// // Functions List ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void EventHandler_Animal_Predator_UD(int iEventID); void EventHandler_Animal_Prey_UD(int iEventID); void EventHandler_Beast_SoulRender_UD(int iEventID); void EventHandler_Default_UD(int iEventID); void EventHandler_Giant_Troll_UD(int iEventID); void EventHandler_Undead_Zombie_UD(int iEventID); void DoZombieSpeak(); //////////////////////////////////////////////////////////////////////////////// // Function Definitions //////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void main() { int iEventID = GetUserDefinedEventNumber(); //////////////////////////////////////////////////////////////////////////// // Switch to the 'OnUserDefined' code for the correct creature ///////////// //////////////////////////////////////////////////////////////////////////// // Animals if (Object_IsClassAndRace(CLASS_TYPE_ANIMAL, OBJECT_SELF, TRUE)) { if (Object_IsPrey()) EventHandler_Animal_Prey_UD(iEventID); // Prey Items else EventHandler_Animal_Predator_UD(iEventID); // Predators } // Soul Renders if (Object_IsClassAndRace(CLASS_TYPE_BEAST, OBJECT_SELF, FALSE, "soul render")) { EventHandler_Beast_SoulRender_UD(iEventID); } // Trolls if (Object_IsClassAndRace(CLASS_TYPE_GIANT, OBJECT_SELF, FALSE, "troll")) { EventHandler_Giant_Troll_UD(iEventID); } // Zombies if (Object_IsClassAndRace(CLASS_TYPE_UNDEAD, OBJECT_SELF, FALSE, "zombie")) { EventHandler_Undead_Zombie_UD(iEventID); } // Default Handler EventHandler_Default_UD(iEventID); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Animal - Predator Event Handler function //////////////////////////////////////////////////////////////////////////////// void EventHandler_Animal_Predator_UD(int iEventID) { int iCurrentHP = GetCurrentHitPoints(); int iMaximumHP = GetMaxHitPoints(); int iThreshold = FloatToInt(0.45 * IntToFloat(iMaximumHP)); int iFlockRoll = d8(3); if(iEventID == 1001) { //HEARTBEAT // React to PC's object oNoticed = GetLocalObject(OBJECT_SELF, "oNoticed"); if (GetIsObjectValid(oNoticed)) { float fDist = GetDistanceToObject(oNoticed); // Flee from PC if not strong enough to fight if ((fDist <= 30.0) && (iCurrentHP < iThreshold) && GetObjectSeen(oNoticed)) { ClearAllActions(); AssignCommand(OBJECT_SELF, ActionMoveAwayFromObject(oNoticed, TRUE)); return; } // Walk randomly if PC is far enough away not to be a bother if (fDist >= 27.0) { SetLocalObject(OBJECT_SELF, "oNoticed", OBJECT_INVALID); AssignCommand(OBJECT_SELF, ClearAllActions()); AssignCommand(OBJECT_SELF, ActionRandomWalk()); return; } // Attack if PC gets too close and we're healthy enough! if ((fDist <= 12.0) && (iCurrentHP > iThreshold)) { if (!GetIsInCombat()) { AssignCommand(OBJECT_SELF, ClearAllActions()); AssignCommand(OBJECT_SELF, ActionAttack(oNoticed)); return; } } } } else if(iEventID == 1002) { // PERCEIVE object oNoticed = GetLastPerceived(); if(GetIsObjectValid(oNoticed)) { // Did animal notice a PC? if ((GetLastPerceptionSeen() || GetLastPerceptionHeard()) && GetIsPC(oNoticed)) { // Do not take aggression against Rangers, Druids, or Elves if ( !(GetLevelByClass(CLASS_TYPE_RANGER, oNoticed) > 1) && !(GetLevelByClass(CLASS_TYPE_DRUID, oNoticed) > 1) && (GetRacialType(oNoticed) != RACIAL_TYPE_ELF)) { SetLocalObject(OBJECT_SELF, "oNoticed", oNoticed); } } } } else if(iEventID == 1003) { // END OF COMBAT } else if(iEventID == 1004) { // ON DIALOGUE } else if(iEventID == 1005) { // ATTACKED if (!GetIsInCombat()) { ClearAllActions(); AssignCommand(OBJECT_SELF, ActionAttack(GetLastAttacker())); } } else if(iEventID == 1006) { // DAMAGED if (iCurrentHP <= iThreshold) { // Run away if too much damage was done object oDamager = GetLastDamager(); SetLocalObject(OBJECT_SELF, "oNoticed", oDamager); ClearAllActions(); SurrenderToEnemies(); ClearPersonalReputation(oDamager); AssignCommand(OBJECT_SELF, ActionMoveAwayFromObject(oDamager, TRUE)); DelayCommand(8.0, SetLocalObject(OBJECT_SELF, "oNoticed", OBJECT_INVALID)); } } else if(iEventID == 1007) { // DEATH Treasure_Death_PlaceBodyParts(); // Respawn_ByResrefWithDelay(OBJECT_SELF, 1200.0 + IntToFloat(Random(450))); } else if(iEventID == 1008) { // DISTURBED } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Animal - Prey Event Handler function //////////////////////////////////////////////////////////////////////////////// void EventHandler_Animal_Prey_UD(int iEventID) { int iCurrentHP = GetCurrentHitPoints(); int iMaximumHP = GetMaxHitPoints(); int iThreshold = FloatToInt(0.45 * IntToFloat(iMaximumHP)); if(iEventID == 1001) { //HEARTBEAT object oNoticed = GetLocalObject(OBJECT_SELF, "oNoticed"); if (GetIsObjectValid(oNoticed)) { float fDist = GetDistanceToObject(oNoticed); if (fDist < 20.0 && GetObjectSeen(oNoticed)) { ActionMoveAwayFromObject(oNoticed, TRUE, 30.0); return; } if (fDist >= 20.0 && fDist <= 40.0) { if (Random(100) >= 15) ActionMoveAwayFromObject(oNoticed, FALSE, 30.0); return; } if (fDist > 40.0) { SetLocalObject(OBJECT_SELF, "oNoticed", OBJECT_INVALID); return; } } else { SetLocalObject(OBJECT_SELF, "oNoticed", OBJECT_INVALID); // Do some flocking behaviour int iHowMany = Object_CountSameAtLocation(OBJECT_SELF, GetLocation(OBJECT_SELF), 2.0); int iTooMany; int iSize = GetCreatureSize(OBJECT_SELF); if (iSize == CREATURE_SIZE_HUGE) iTooMany = 2; if (iSize == CREATURE_SIZE_LARGE) iTooMany = 3; if (iSize == CREATURE_SIZE_MEDIUM) iTooMany = 4; if (iSize == CREATURE_SIZE_SMALL) iTooMany = 6; if (iSize == CREATURE_SIZE_TINY) iTooMany = 9; if (iHowMany >= iTooMany) { ActionForceMoveToRandomLocation(OBJECT_SELF, 20.0, 20.0, Random(3)); } else AI_Movement_FlockTypeB(); } } else if(iEventID == 1002) { // PERCEIVE object oNoticed = GetLastPerceived(); if(GetIsObjectValid(oNoticed)) { // Did animal notice another animal? string strNoticed = GetTag(oNoticed); if (GetTag(OBJECT_SELF) != strNoticed) { SetLocalObject(OBJECT_SELF, "oNoticed", oNoticed); ActionMoveAwayFromObject(oNoticed, FALSE); // Move away from it } } } else if(iEventID == 1003) { // END OF COMBAT } else if(iEventID == 1004) { // ON DIALOGUE } else if(iEventID == 1005) { // ATTACKED if (!GetIsInCombat()) { ClearAllActions(); if (Random(100) >=60) AssignCommand(OBJECT_SELF, ActionAttack(GetLastAttacker())); else ActionMoveAwayFromObject(GetLastAttacker(), TRUE); } } else if(iEventID == 1006) { // DAMAGED if (iCurrentHP <= iThreshold) { // Run away if too much damage was done object oDamager = GetLastDamager(); SetLocalObject(OBJECT_SELF, "oNoticed", oDamager); ClearAllActions(); SurrenderToEnemies(); ClearPersonalReputation(oDamager); AssignCommand(OBJECT_SELF, ActionMoveAwayFromObject(oDamager, TRUE)); DelayCommand(8.0, SetLocalObject(OBJECT_SELF, "oNoticed", OBJECT_INVALID)); } } else if(iEventID == 1007) { // DEATH Treasure_Death_PlaceBodyParts(); // Respawn_ByResrefWithDelay(OBJECT_SELF, 1200.0 + IntToFloat(Random(450))); } else if(iEventID == 1008) { // DISTURBED } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Default event handler for those creatures who did not get one previously //////////////////////////////////////////////////////////////////////////////// void EventHandler_Default_UD(int iEventID) { if(iEventID == 1001) { //HEARTBEAT } else if(iEventID == 1002) {// PERCEIVE } else if(iEventID == 1003) { // END OF COMBAT } else if(iEventID == 1004) { // ON DIALOGUE } else if(iEventID == 1005) { // ATTACKED } else if(iEventID == 1006) { // DAMAGED } else if(iEventID == 1007) { // DEATH Treasure_Death_PlaceBodyParts(); } else if(iEventID == 1008) { // DISTURBED } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Soul Render Event Handler function ///////////////////////////////////////// // v1.00 /////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // The Event Handler for the Soul Render is fairly intensive as it utilizes an object search // inside the heartbeat - keep this creature by itself! void EventHandler_Beast_SoulRender_UD(int iEventID) { // If in combat, examine nearby enemies for Negative Level Effects. // If found, then remove the drain, and select a Skill or Ability // Drain and apply it to the PC while applying the opposite effect // to the beast. if(iEventID == 1001) { //HEARTBEAT // Play horrifying sounds, just cause a soul-sucker isn't creepy enough without them... if (d100() < 20) { int iRand = d4(); if (iRand == 1) { AssignCommand(OBJECT_SELF, PlaySound("c_beastbrth")); } if (iRand == 2) { AssignCommand(OBJECT_SELF, PlaySound("c_beastmoan")); } if (iRand == 3) { AssignCommand(OBJECT_SELF, PlaySound("c_beastroar")); } if (iRand == 4) { AssignCommand(OBJECT_SELF, PlaySound("c_beastsigh")); } } // SUCK SOULS! if (GetIsInCombat()) { // Search for nearby PC's with level drains string strResult; object oPC = GetFirstObjectInShape(SHAPE_SPHERE, 5.0, GetLocation(OBJECT_SELF), FALSE, OBJECT_TYPE_CREATURE); // Determine if the Render has sucked spell memories... chuck them back! string strAbsorbedSpells = GetLocalString(OBJECT_SELF, "strAbsorbedSpells"); if (Array_GetTotalElements(strAbsorbedSpells) && (d20() < GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) )) { Effect_DischargeAbsorbedSpell(OBJECT_SELF); } // Suck some souls!!! while (GetIsObjectValid(oPC)) { if (PRCGetHasEffect(EFFECT_TYPE_NEGATIVELEVEL, oPC)) { effect eFX = GetFirstEffect(oPC); while (GetIsEffectValid(eFX)) { if (GetEffectType(eFX) == EFFECT_TYPE_NEGATIVELEVEL) { if (GetEffectCreator(eFX) == OBJECT_SELF) { RemoveEffect(oPC, eFX); strResult = ""; int iRoll = d20(2); // If the PC is a spell caster, then allow the Render to absorb spells as well if (GetLevelByClass(CLASS_TYPE_CLERIC, oPC) || GetLevelByClass(CLASS_TYPE_DRUID, oPC) || GetLevelByClass(CLASS_TYPE_WIZARD, oPC) || GetLevelByClass(CLASS_TYPE_SORCERER, oPC)) iRoll += d10(); // Should I suck hitpoints?! if (GetCurrentHitPoints() < 200) { Effect_AbsorbHitPoints(OBJECT_SELF, oPC); } // If there was some indecision, randomly decide what to SUCK! if (iRoll < 10) { strResult = Effect_AbsorbRandomAbility(OBJECT_SELF, oPC); } // Absorb an Ability else if (iRoll < 18) { strResult = Effect_AbsorbRandomSavingThrow(OBJECT_SELF, oPC); } // Absorb a saving throw else if (iRoll < 24) { strResult = Effect_AbsorbHitPoints(OBJECT_SELF, oPC); } // Absorb some of the PC's HP's else if (iRoll < 30) { strResult = Effect_AbsorbAbility(OBJECT_SELF, oPC, ABILITY_STRENGTH); } else if (iRoll < 33) { strResult = Effect_AbsorbAbility(OBJECT_SELF, oPC, ABILITY_DEXTERITY); } else if (iRoll < 40) { strResult = Effect_AbsorbAbility(OBJECT_SELF, oPC, ABILITY_CONSTITUTION); } else if (iRoll < 50) { strResult = Effect_AbsorbSpellMemory(OBJECT_SELF, oPC); } if (GetStringLength(strResult) > 0) SendMessageToPC(oPC, "Soul Render " + strResult); } } eFX = GetNextEffect(oPC); } // end while (GetIsEffectValid(eFX)) } oPC = GetNextObjectInShape(SHAPE_SPHERE, 5.0, GetLocation(OBJECT_SELF), FALSE, OBJECT_TYPE_CREATURE); } // end while (GetIsObjectValid(oPC)) } } // END of HEARTBEAT } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Troll Event Handler function /////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void EventHandler_Giant_Troll_UD(int iEventID) { object oAttacker = GetLastHostileActor(); object oSeen; if(iEventID == 1001) { //HEARTBEAT } else if(iEventID == 1002) {// PERCEIVE } else if(iEventID == 1003) { // END OF COMBAT } else if(iEventID == 1004) { // ON DIALOGUE } else if(iEventID == 1005) { // ATTACKED } else if(iEventID == 1006) { // DAMAGED Object_CheckDamageVsResistances(20, 10, 25, (4.0 + IntToFloat(d6())), 33); } else if(iEventID == 1007) { // DEATH Treasure_Death_PlaceBodyParts(); } else if(iEventID == 1008) { // DISTURBED } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Zombie Event Handler function //////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void EventHandler_Undead_Zombie_UD(int iEventID) { object oAttacker = GetLastHostileActor(); object oSeen; if(iEventID == 1001) { //HEARTBEAT } else if(iEventID == 1002) {// PERCEIVE // If a player is perceived with sight say something freaky oSeen = GetLastPerceived(); if (GetIsPC(oSeen)) DoZombieSpeak(); } else if(iEventID == 1003) { // END OF COMBAT } else if(iEventID == 1004) { // ON DIALOGUE } else if(iEventID == 1005) { // ATTACKED } else if(iEventID == 1006) { // DAMAGED Object_CheckDamageVsResistances(20, 10, 25, (4.0 + IntToFloat(d6())), 41); } else if(iEventID == 1007) { // DEATH Treasure_Death_PlaceBodyParts(); } else if(iEventID == 1008) { // DISTURBED } } void DoZombieSpeak() { int nRandom = Random(6); ClearAllActions(); string strSpeach; if (nRandom == 0) strSpeach = "dead by dawn... dead by dawn..."; if (nRandom == 1) strSpeach = "I'll swallow your soul!"; if (nRandom == 2) strSpeach = "brrraaains..."; if (nRandom == 3) strSpeach = "dead by dawn... dead by dawn..."; if (nRandom == 4) strSpeach = "Dead by dawn!!"; if (nRandom == 5) strSpeach = "We want what you have... life..."; AssignCommand(OBJECT_SELF, ActionSpeakString(strSpeach)); AssignCommand(OBJECT_SELF, ActionAttack(GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC))); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////