Initial commit
Adding all of the current content for Anphillia Unlimited.
This commit is contained in:
295
_module/nss/zep_inc_demi.nss
Normal file
295
_module/nss/zep_inc_demi.nss
Normal file
@@ -0,0 +1,295 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Demilich constants, includes, and scripts for
|
||||
//:: use with CEP adaptation of Demigog's demilich.
|
||||
//::///////////////////////////////////////////////
|
||||
|
||||
//::--------------------------------------------------------------
|
||||
//:: Begin Demilich Constants and functions added by Loki Hakanin
|
||||
//::--------------------------------------------------------------
|
||||
|
||||
#include "zep_inc_scrptdlg"
|
||||
|
||||
//First is RESREF of demilich skull placable to be created
|
||||
//when the demilich goes into resting mode.
|
||||
const string ZEP_DEMI_SKULL_RESREF = "zep_demi_skull";
|
||||
//Second is RESREF of matching dust plume.
|
||||
const string ZEP_DEMI_DUST_RESREF = "zep_demi_dust";
|
||||
|
||||
//Also have matching TAGs for the above two:
|
||||
const string ZEP_DEMI_SKULL_TAG = "zep_demi_skull";
|
||||
const string ZEP_DEMI_DUST_TAG = "zep_demi_dust";
|
||||
|
||||
//Following sets the save DC of the demilich's attempt to
|
||||
//slay arcane spellcaters and trap their souls.
|
||||
const int DEMILICH_SOUL_EAT_SAVE_DC = 15;
|
||||
|
||||
//Following sets the maximum number of soulgem victims the
|
||||
//demilich will take on at a time. Recommend this not be
|
||||
//set higher than 8 or so, since LocalObject varibles are
|
||||
//used to keep track of the victims.
|
||||
const int DEMILICH_NUM_SOULGEMS = 8;
|
||||
|
||||
//Sets the minimum level an arcane caster must be in order
|
||||
//for the demilich to attampt to pull out their soul upon
|
||||
//a spell being cast at it.
|
||||
const int DEMILICH_POWER_THRESHOLD = 15;
|
||||
|
||||
//Last we have the new tag which the demliich will use to
|
||||
//differentiate a regenerating demilich from a normal one.
|
||||
const string ZEP_DEMI_REGEN_SKULL = "zep_demi_skull_regen";
|
||||
|
||||
//Time, in seconds, for Demilich to regenerate from battle
|
||||
//injuries. Defaults to 5 minutes. Note that PCs must use
|
||||
//Holy Water on the demilich's bones in the span of that
|
||||
//time in order to destroy it once and for all.
|
||||
const int ZEP_DEMI_REGEN_TIME = 300;
|
||||
|
||||
//Messages Displayed over head of victims of soul-geming just
|
||||
//before they are killed again by the Demilich's heartbeat
|
||||
//script.
|
||||
//Note that messages are concatenated with the name of the
|
||||
//slain creature for a personalized effect.
|
||||
|
||||
string ZEP_DEMI_RESLAY_MSG = GetStringByStrRef(nZEPCantBeRaised ,GENDER_MALE);
|
||||
//" jerks upright and spasms for a few moments before collapsing again.";
|
||||
string ZEP_DEMI_RESLAY_MSG2 = GetStringByStrRef(nZEPNoRaiseExplan ,GENDER_MALE);
|
||||
//"Until the demilich's captive souls are freed, its victims cannot be raised.";
|
||||
|
||||
//Next float variable defines the demilich's perception range,
|
||||
//while resting or regenerating, in meters.
|
||||
const float ZEP_DEMI_PERC_RANGE = 5.0;
|
||||
|
||||
//Following messages are used for demilich's respawn scripts.
|
||||
//First displayed by a just-respawned demilich that was
|
||||
//regenerating.
|
||||
//Latter displayed by a disturbed demilich that is responding
|
||||
//to intruders.
|
||||
string ZEP_DEMI_REGEN_MSG = GetStringByStrRef(nZEPDemiRestored,GENDER_MALE);
|
||||
//"At last, I am restored...";
|
||||
string ZEP_DEMI_DIST_MSG = GetStringByStrRef(nZEPDemiDisturbed ,GENDER_MALE);
|
||||
//"You disturb my work!";
|
||||
|
||||
//Following is message spoken in Demilich's OnSpellCastAt
|
||||
//script if he's hit by a spell from a high level caster
|
||||
string ZEP_DEMI_ONSPELL_MSG = GetStringByStrRef(nZEPDemiHavePower ,GENDER_MALE);
|
||||
//"Yes, I sense you have power...your potential shall be mine!";
|
||||
|
||||
//Following defines RESREF and TAG of item that is needed
|
||||
//to destroy a regenerating demilich.
|
||||
const string ZEP_DEMI_DEST_RESREF = "zep_holy_water";
|
||||
const string ZEP_DEMI_DEST_TAG = "zep_holy_water";
|
||||
|
||||
//Following is name of conversation to start if someone uses
|
||||
//the demilich's bone pile. First is for a default bone pile
|
||||
//and second is for a regenerating bone pile that has already
|
||||
//been defeated once.
|
||||
const string ZEP_DEMI_ONUSE_CONV = "zep_demi_bones";
|
||||
const string ZEP_DEMI_ONUSE_REGEN = "zep_demi_regen_c";
|
||||
|
||||
//Following string is floating text displayed over the
|
||||
//demilich upon it's final destruction.
|
||||
string ZEP_DEMI_FINAL_DEST = GetStringByStrRef(nZEPDemiVictFree ,GENDER_MALE);
|
||||
//"With the demilich destroyed, the souls of its victims are released to their bodies.";
|
||||
|
||||
//Following flag sets whether to automatically resurrect
|
||||
//victims of soul-gem entrappment upon the demilich's
|
||||
//destruction.
|
||||
|
||||
const int ZEP_DEMI_RESS_VICTIMS = FALSE;
|
||||
|
||||
//::-------------------------------------------------
|
||||
//:: Begin Demilich Functions added by Loki Hakanin
|
||||
//::-------------------------------------------------
|
||||
|
||||
//Function will spawn appropriate bones and dust plume
|
||||
//for demilich. Will also copy over variables associated
|
||||
//with any soultrapped victims, and change tag to flag bone
|
||||
//pile as regenerating as necessary.
|
||||
// Arguments:
|
||||
// object oDemilichToReplace = The demilich that we're going
|
||||
// to despawn
|
||||
// int nWasDestroyed = Are we replacing the demilich with a
|
||||
// rest-mode bone pile (FALSE), or a
|
||||
// regenerating bone pile (TRUE)?
|
||||
void ZEPDemilichSpawnBones(object oDemilichToReplace,int nWasDestroyed);
|
||||
|
||||
void ZEPDemilichSpawnBones(object oDemilichToReplace,int nWasDestroyed)
|
||||
{
|
||||
//So we'll first get the Demilich's location, and then create
|
||||
//a pair of the usual demilich placables there. However,
|
||||
//if the demilich is regenerating from wounds, we'll change
|
||||
//the tag of the skull pile to the ZEP_DEMI_REGEN_SKULL
|
||||
//constant value.
|
||||
//The scripts on the skull will use this tag to determine
|
||||
//if it is a fresh (i.e. undestroyed) demilich, or a crippled,
|
||||
//regenerating one.
|
||||
//We will also copy over the NumSouls local variable and the
|
||||
//set of LocalObjects pointing to the Demlich's set of soul-
|
||||
//gem'em victims, if any.
|
||||
location lDestroyedLocation = GetLocation(oDemilichToReplace);
|
||||
object oSkullPile;
|
||||
|
||||
//If Demliich in question was destroyed, we create the skull
|
||||
//pile with the variant tag defined above, allowing the
|
||||
//skull pile to differentiate itself from a "healthy"
|
||||
//demilich. This saves us a local variable.
|
||||
if (nWasDestroyed)
|
||||
oSkullPile=CreateObject(OBJECT_TYPE_PLACEABLE,ZEP_DEMI_SKULL_RESREF,lDestroyedLocation,FALSE,ZEP_DEMI_REGEN_SKULL);
|
||||
else oSkullPile=CreateObject(OBJECT_TYPE_PLACEABLE,ZEP_DEMI_SKULL_RESREF,lDestroyedLocation,FALSE);
|
||||
|
||||
object oDustPlume=CreateObject(OBJECT_TYPE_PLACEABLE,ZEP_DEMI_DUST_RESREF,lDestroyedLocation,FALSE);
|
||||
|
||||
//Now for the copying. Loop through all GemVictim objects,
|
||||
//based on NumSouls. Remember that GemVictim indexes start
|
||||
//from 0 (like an array in many programming languages),
|
||||
//though the Numsouls variable is a positive int.
|
||||
int nCounter=0;
|
||||
int nNumSouls=GetLocalInt(oDemilichToReplace,"NumSouls");
|
||||
//SendMessageToAllDMs(("NumSouls(SpawnBones):"+(IntToString(nNumSouls))));
|
||||
//Set NumSouls counter on skull pile
|
||||
SetLocalInt(oSkullPile,"NumSouls",nNumSouls);
|
||||
string sVictimCounterName="GemVictim";
|
||||
object oVictimCounter;
|
||||
|
||||
for (nCounter=0; nCounter < nNumSouls; nCounter++)
|
||||
{
|
||||
//Get object variable name, then set a variable on the
|
||||
//skull pile with the same name, pointing to same
|
||||
//object.
|
||||
//Note we don't delete the local objects of the Demlich
|
||||
//here as they will be cleaned up upon the final destruction
|
||||
//of the demilich, which always follows this function's call.
|
||||
sVictimCounterName=("GemVictim"+(IntToString(nCounter)));
|
||||
oVictimCounter=GetLocalObject(oDemilichToReplace,sVictimCounterName);
|
||||
// if (oVictimCounter==OBJECT_INVALID)
|
||||
// SendMessageToAllDMs(("VictimCount("+(IntToString(nCounter))+") invalid."));
|
||||
SetLocalObject(oSkullPile,sVictimCounterName,oVictimCounter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Function will play some dazed effects for a second,
|
||||
//display some text explaining that the resurrection spell
|
||||
//fails due to the demilich having oCreatureToSlay's soul,
|
||||
//and then re-kills them.
|
||||
void ZEPDemilichReSlay(object oCreatureToSlay);
|
||||
|
||||
void ZEPDemilichReSlay(object oCreatureToSlay)
|
||||
{
|
||||
//We'll get the name of our victim and concatenate it with
|
||||
//our first message. This personalizes things a bit.
|
||||
string sVictimName=GetName(oCreatureToSlay);
|
||||
|
||||
AssignCommand(oCreatureToSlay,ClearAllActions());
|
||||
//Play spasm animation:
|
||||
AssignCommand(oCreatureToSlay,ActionPlayAnimation(ANIMATION_FIREFORGET_SPASM));
|
||||
//At the same time, display a descriptive string about the
|
||||
//creature's state.
|
||||
FloatingTextStringOnCreature((sVictimName+ZEP_DEMI_RESLAY_MSG),oCreatureToSlay,FALSE);
|
||||
//Kill the creature again.
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDeath(FALSE),oCreatureToSlay);
|
||||
//Further descriptive string.
|
||||
DelayCommand(6.0,FloatingTextStringOnCreature(ZEP_DEMI_RESLAY_MSG2,oCreatureToSlay,FALSE));
|
||||
}
|
||||
|
||||
//Function will kill all soulgem victims of the Demilich again
|
||||
//if they have been raised, playing some appriopriate animations
|
||||
//and VFX, and displaying some text.
|
||||
//Essentially, we'll check against the NumSouls variable
|
||||
//on our demilich, and then cycle through all GemVictim
|
||||
//local objects, running a function to display effects and
|
||||
//kill them as necessary.
|
||||
void ZEPDemilichReSlaySoulGemVictims(object oDemilich);
|
||||
|
||||
void ZEPDemilichReSlaySoulGemVictims(object oDemilich)
|
||||
{
|
||||
int nCounter=0; //Counter for variable names
|
||||
int nNumSouls=GetLocalInt(oDemilich,"NumSouls"); //Number of consumed souls
|
||||
string sVictimCounterName; //Used with nCounter to create proper local variable name
|
||||
object oVictimCounter; //Counter for actual objects pointed to by demilich's victim list.
|
||||
|
||||
//Don't forget, Counter (i.e., the "GemVictim" variable
|
||||
//name index) starts from 0, like an array index.
|
||||
//But nNumSouls is a positive int, so this for loop should be
|
||||
//logically consistent.
|
||||
for (nCounter=0; nCounter < nNumSouls; nCounter++)
|
||||
{
|
||||
sVictimCounterName=("GemVictim"+(IntToString(nCounter)));
|
||||
oVictimCounter=GetLocalObject(oDemilich,sVictimCounterName);
|
||||
//If the victim has more than 0 HPs... (i.e. is alive)
|
||||
//we'll kill them again, with explanatory text.
|
||||
if (GetCurrentHitPoints(oVictimCounter) > 0)
|
||||
ZEPDemilichReSlay(oVictimCounter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Following function spawns a demilich from the bones
|
||||
//that it left behind, either when resting or regenerating.
|
||||
//Note that the soulgem victim list is copied over, and
|
||||
//therefore preserved.
|
||||
//Arguments:
|
||||
// oSourceBones- the bone placable that relevant variables
|
||||
// will be copied over from.
|
||||
// nDestroyBones- destroy object oSourceBones upon completion
|
||||
// of the function...TRUE= destroy it, FALSE = do nothing.
|
||||
object ZEPDemilichFromBones(object oSourceBones, int nDestroyBones);
|
||||
|
||||
object ZEPDemilichFromBones(object oSourceBones, int nDestroyBones)
|
||||
{
|
||||
//First we create the Demilich.
|
||||
object oReturnDemilich=CreateObject(OBJECT_TYPE_CREATURE,"zep_demi_lich",GetLocation(oSourceBones));
|
||||
//Now we'll use a loop to copy over the soulgem victim list.
|
||||
int nNumSouls = GetLocalInt(oSourceBones,"NumSouls");
|
||||
int nCounter=0;
|
||||
string sVarNameCounter;
|
||||
object oVictimCounter;
|
||||
|
||||
//For loop will use int counter, concatenated with "GemVictim"
|
||||
//to generate correct variable names. Will then retrieve
|
||||
//these variables from the oSourceBones object and copy
|
||||
//them over to our new Demilich.
|
||||
for (nCounter=0; nCounter < nNumSouls; nCounter++)
|
||||
{
|
||||
sVarNameCounter = ("GemVictim"+IntToString(nCounter));
|
||||
oVictimCounter = GetLocalObject(oSourceBones,sVarNameCounter);
|
||||
SetLocalObject(oReturnDemilich,sVarNameCounter,oVictimCounter);
|
||||
}
|
||||
//Now we set the "NumSouls" counter on our newsly-spawned
|
||||
//Demilich.
|
||||
SetLocalInt(oReturnDemilich,"NumSouls",nNumSouls);
|
||||
|
||||
//Now, we're going to compare our bone pile's resref against
|
||||
//the regenerating resref. If it's the same, we display the
|
||||
//regeneration message (defined above).
|
||||
//Else we play the default "disturbed" message, since this
|
||||
//function is called in two ways...a regenerating demilich
|
||||
//or a disturbed Demilich.
|
||||
string sBonePileTag=GetTag(oSourceBones);
|
||||
if (sBonePileTag == ZEP_DEMI_REGEN_SKULL)
|
||||
{
|
||||
AssignCommand(oReturnDemilich,ActionSpeakString(ZEP_DEMI_REGEN_MSG,TALKVOLUME_SHOUT));
|
||||
FloatingTextStringOnCreature(ZEP_DEMI_REGEN_MSG,oReturnDemilich);
|
||||
}
|
||||
else
|
||||
{
|
||||
AssignCommand(oReturnDemilich,ActionSpeakString(ZEP_DEMI_DIST_MSG,TALKVOLUME_SHOUT));
|
||||
FloatingTextStringOnCreature(ZEP_DEMI_DIST_MSG,oReturnDemilich);
|
||||
}
|
||||
|
||||
//Last, if the user has specified that we should destroy the
|
||||
//bones and dust plume, we do so.
|
||||
if (nDestroyBones == TRUE)
|
||||
{
|
||||
object oDustPlume=GetNearestObjectByTag(ZEP_DEMI_DUST_TAG);
|
||||
// if (oDustPlume==OBJECT_INVALID)
|
||||
// SendMessageToAllDMs("Bad Dust plume!");
|
||||
DestroyObject(oDustPlume);
|
||||
DestroyObject(oSourceBones);
|
||||
}
|
||||
return oReturnDemilich;
|
||||
}
|
||||
|
||||
//:: ---------------------------------------
|
||||
//:: End Demilich functions and constants
|
||||
//:: ---------------------------------------
|
||||
Reference in New Issue
Block a user