Added CCOH and missing areas Changed some areas to be craftable, Fixed some on death issues, Fixed the Gaurd
422 lines
18 KiB
Plaintext
422 lines
18 KiB
Plaintext
#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)));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|