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