Aschbourne_PRC8/_module/nss/prc_onuserdef.nss
GetOffMyYarn 69879d6957 Areas and Fixes
Added CCOH and missing areas
Changed some areas to be craftable,
Fixed some on death issues,
Fixed the Gaurd
2024-08-30 11:38:44 -04:00

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)));
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////