Aschbourne_PRC8/_module/nss/prc_onuserdef.nss
Jaysyn904 5d27edafba Major update
Fixed CCOH, Fixed starting GP, Fixed DMFI languages, Fix cep weapon appearances, Fixed new player start up system.  Added PC deleter.  Added ACP 4.1.  Full compile.  Updated release archive.
2024-09-16 23:40:48 -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)));
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////