365 lines
14 KiB
Plaintext
365 lines
14 KiB
Plaintext
////////////////////////////////////////////////////
|
|
// OnHeartbeat for the Shadow Realm
|
|
//--------------------------------------------------
|
|
// By Deva Bryson Winblood. 01/2003
|
|
//==================================================
|
|
// This realm is responsive to light.
|
|
// Light sources
|
|
// Torch: NW_IT_TORCH001
|
|
// Light Spell VFX_DUR_LIGHT
|
|
// Glittering Necklace nw_it_mneck023
|
|
// Ring of Jade nw_it_mring011
|
|
// Ring of Cyan nw_it_mring009
|
|
// Ring of Crimson nw_it_mring010
|
|
/////////////////////////////////////////////////////
|
|
// All PCs that have a light source active will
|
|
// attract beings from the plane of shadows
|
|
// 50% Shadow nw_shadow CR 3
|
|
// 25% Shadow Mastif nw_shmastif CR 4
|
|
// 15% Shadow Fiend nw_shfiend CR 7
|
|
// 10% Bodak nw_bodak CR 9
|
|
// Night Hag nighthag CR 8
|
|
// Nightwalker nightwalker CR 20
|
|
/////////////////////////////////////////////////////////
|
|
// The death scripts have been altered so, the player
|
|
// cannot return to the inn. In addition, the emergency
|
|
// recall scroll will return them here. They must escape
|
|
// on their own.
|
|
/////////////////////////////////////////////////////////
|
|
// Escape method: Each door must be passed through once
|
|
// to get to the next Shadow Realm.
|
|
// Eventually, they will return to the real world.
|
|
// This is a difficult quest and will be worth significant
|
|
// experience.
|
|
////////////////////////////////////////////////////////////
|
|
// When light source is present there is a 15% per heartbeat
|
|
// of a monster being spawned to deal with the player if
|
|
// they have a light source activated. No more than 8 monsters
|
|
// at any given time will be spawned.
|
|
////////////////////////////////////////////////////////////
|
|
#include "prc_inc_skin"
|
|
|
|
string fnSpawnType(object oPC)
|
|
{ // return resref of creature to spawn
|
|
string sRet="nw_shadow1";
|
|
int nLevel=GetLevelByPosition(1,oPC);
|
|
int nR=d100();
|
|
nLevel=nLevel+GetLevelByPosition(2,oPC);
|
|
nLevel=nLevel+GetLevelByPosition(3,oPC);
|
|
if (nLevel<3)
|
|
{ // lowest level
|
|
if (nR<75) sRet="nw_shadow1";
|
|
else if (nR<95) sRet="nw_shmastif1";
|
|
else if (nR<100) sRet="nw_shfiend1";
|
|
else { sRet="nw_bodak1"; }
|
|
} // lowest level
|
|
else if (nLevel<6)
|
|
{ // second stage
|
|
if (nR<50) sRet="nw_shadow1";
|
|
else if (nR<80) sRet="nw_shmastif1";
|
|
else if (nR<98) sRet="nw_shfiend1";
|
|
else { sRet="nw_bodak1"; }
|
|
} // second stage
|
|
else if (nLevel<10)
|
|
{ // third stage
|
|
if (nR<33) sRet="nw_shadow1";
|
|
else if (nR<50) sRet="nw_shmastif1";
|
|
else if (nR<80) sRet="nw_shfiend1";
|
|
else if (nR<95) sRet="nw_bodak1";
|
|
else { sRet="nighthag"; }
|
|
} // third stage
|
|
else if (nLevel<15)
|
|
{ // fourth stage
|
|
if (nR<20) sRet="nw_shadow1";
|
|
else if (nR<33) sRet="nw_shmastif1";
|
|
else if (nR<50) sRet="nw_shfiend1";
|
|
else if (nR<80) sRet="nw_bodak1";
|
|
else { sRet="nighthag"; }
|
|
} // fourth stage
|
|
else if (nLevel<19)
|
|
{ // fifth stage
|
|
if (nR<10) sRet="nw_shadow1";
|
|
else if (nR<20) sRet="nw_shmastif1";
|
|
else if (nR<33) sRet="nw_shfiend1";
|
|
else if (nR<50) sRet="nw_bodak1";
|
|
else if (nR<90) sRet="nighthag";
|
|
else { sRet="nightwalker"; }
|
|
} // fifth stage
|
|
else
|
|
{ // final stage
|
|
if (nR<10) sRet="nw_shfiend1";
|
|
else if (nR<33) sRet="nw_bodak1";
|
|
else if (nR<75) sRet="nighthag";
|
|
else { sRet="nightwalker"; }
|
|
} // final stage
|
|
return sRet;
|
|
} // fnSpawnType()
|
|
|
|
|
|
int HasLightSource(object oT)
|
|
{ // check to see if the object has a light source ready
|
|
int nRet=FALSE;
|
|
effect eTest;
|
|
object oItem;
|
|
string sTag;
|
|
effect eCompare1=EffectVisualEffect(VFX_DUR_LIGHT);
|
|
effect eCompare2=EffectVisualEffect(VFX_DUR_LIGHT_WHITE_20);
|
|
effect eCompare3=EffectVisualEffect(VFX_DUR_LIGHT_WHITE_15);
|
|
effect eCompare4=EffectVisualEffect(VFX_DUR_LIGHT_WHITE_10);
|
|
effect eCompare5=EffectVisualEffect(VFX_DUR_LIGHT_WHITE_5);
|
|
effect eCompare6=EffectVisualEffect(VFX_DUR_LIGHT_YELLOW_20);
|
|
effect eCompare7=EffectVisualEffect(VFX_DUR_LIGHT_YELLOW_15);
|
|
effect eCompare8=EffectVisualEffect(VFX_DUR_LIGHT_YELLOW_10);
|
|
effect eCompare9=EffectVisualEffect(VFX_DUR_LIGHT_YELLOW_5);
|
|
effect eCompare10=EffectVisualEffect(VFX_DUR_LIGHT_BLUE_20);
|
|
effect eCompare11=EffectVisualEffect(VFX_DUR_LIGHT_BLUE_15);
|
|
effect eCompare12=EffectVisualEffect(VFX_DUR_LIGHT_GREY_20);
|
|
effect eCompare13=EffectVisualEffect(VFX_DUR_LIGHT_ORANGE_20);
|
|
effect eCompare14=EffectVisualEffect(VFX_DUR_LIGHT_PURPLE_20);
|
|
effect eCompare15=EffectVisualEffect(VFX_DUR_LIGHT_RED_20);
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_ARMS,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BELT,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BOOTS,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
//oItem=GetItemInSlot(INVENTORY_SLOT_CARMOUR,oT);
|
|
oItem = GetPCSkin(oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_CHEST,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_CLOAK,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_HEAD,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_LEFTRING,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_NECK,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oT);
|
|
if (GetItemHasItemProperty(oItem,ITEM_PROPERTY_LIGHT)==TRUE) nRet=TRUE;
|
|
if (nRet!=TRUE)
|
|
{ // test for light spell effect
|
|
eTest=GetFirstEffect(oT);
|
|
while(GetEffectType(eTest)!=EFFECT_TYPE_INVALIDEFFECT&&nRet==FALSE)
|
|
{ // check for light
|
|
if(eTest==eCompare1) nRet=TRUE;
|
|
else if (eTest==eCompare2) nRet=TRUE;
|
|
else if (eTest==eCompare3) nRet=TRUE;
|
|
else if (eTest==eCompare4) nRet=TRUE;
|
|
else if (eTest==eCompare5) nRet=TRUE;
|
|
else if (eTest==eCompare6) nRet=TRUE;
|
|
else if (eTest==eCompare7) nRet=TRUE;
|
|
else if (eTest==eCompare8) nRet=TRUE;
|
|
else if (eTest==eCompare9) nRet=TRUE;
|
|
else if (eTest==eCompare10) nRet=TRUE;
|
|
else if (eTest==eCompare11) nRet=TRUE;
|
|
else if (eTest==eCompare12) nRet=TRUE;
|
|
else if (eTest==eCompare13) nRet=TRUE;
|
|
else if (eTest==eCompare14) nRet=TRUE;
|
|
else if (eTest==eCompare15) nRet=TRUE;
|
|
eTest=GetNextEffect(oT);
|
|
} // check for light
|
|
} // test for light spell effect
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oT);
|
|
sTag=GetResRef(oItem);
|
|
if (sTag=="nw_it_torch001") nRet=TRUE;
|
|
sTag=GetName(oItem);
|
|
if (sTag=="Torch") nRet=TRUE;
|
|
return nRet;
|
|
} // HasLightSource()
|
|
|
|
int CountShadowCreatures()
|
|
{ // return number of active shadow creatures
|
|
int nRet=0;
|
|
object oWP=GetWaypointByTag("ENTER_THE_SHADOW");
|
|
object oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oWP,1);
|
|
int nC=1;
|
|
object oCR=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oWP,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY);
|
|
while(oCR!=OBJECT_INVALID)
|
|
{ // count them
|
|
nRet++;
|
|
nC++;
|
|
oCR=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oWP,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY);
|
|
} // count them
|
|
return nRet;
|
|
} // CountShadowCreatures()
|
|
|
|
/*string GetCreatureAttracted()
|
|
{ // determine resref of Shadow creature attracted
|
|
string sRet="";
|
|
int nD=d100();
|
|
if (nD<16)
|
|
{ // an encounter occurred
|
|
nD=d100();
|
|
if (nD<51) sRet="nw_shadow"; // a shadow
|
|
else if (nD<76) sRet="nw_shmastif"; // a shadow mastif
|
|
else if (nD<91) sRet="nw_shfiend"; // a shadow fiend
|
|
else sRet="nw_bodak"; // a bodak
|
|
} // an encounter occurred
|
|
return sRet;
|
|
} // GetCreatureAttracted()*/
|
|
|
|
void fnShadowAI()
|
|
{ // make the shadows on this level react
|
|
object oPortal=GetNearestObjectByTag("SR_AI_TRANSITION",OBJECT_SELF,1);
|
|
object oEnemy=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,OBJECT_SELF,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY);
|
|
float fDist=GetDistanceBetween(OBJECT_SELF,oEnemy);
|
|
object oMod=GetModule();
|
|
int nDisableNonEssential=GetLocalInt(oMod,"nDisableNonEssential");
|
|
float fSpeed=8.0;
|
|
object oTargetEnemy=GetLocalObject(OBJECT_SELF,"oTargetEnemy");
|
|
if (nDisableNonEssential==TRUE) fSpeed=10.0; // reduce a little usage
|
|
if (GetIsInCombat(OBJECT_SELF)!=TRUE&&GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,OBJECT_SELF,1)!=OBJECT_INVALID)
|
|
{ // not fighting
|
|
if (oTargetEnemy!=oEnemy||GetArea(oTargetEnemy)!=GetArea(OBJECT_SELF))
|
|
{
|
|
AssignCommand(OBJECT_SELF,ClearAllActions(TRUE));
|
|
DeleteLocalObject(OBJECT_SELF,"oTargetEnemy");
|
|
}
|
|
if (fDist<20.0&&oEnemy!=OBJECT_INVALID&&GetObjectSeen(oEnemy)==TRUE)
|
|
{ // engage enemy
|
|
AssignCommand(OBJECT_SELF,ClearAllActions());
|
|
AssignCommand(OBJECT_SELF,ActionAttack(oEnemy));
|
|
SetLocalObject(OBJECT_SELF,"oTargetEnemy",oEnemy);
|
|
} // engage enemy
|
|
else if (HasLightSource(oEnemy)==TRUE)
|
|
{ // run to enemy
|
|
AssignCommand(OBJECT_SELF,ClearAllActions());
|
|
AssignCommand(OBJECT_SELF,ActionMoveToObject(oEnemy,TRUE,1.0));
|
|
SetLocalObject(OBJECT_SELF,"oTargetEnemy",oEnemy);
|
|
} // run to enemy
|
|
else
|
|
{ // walk to portal
|
|
AssignCommand(OBJECT_SELF,ClearAllActions());
|
|
AssignCommand(OBJECT_SELF,ActionForceMoveToObject(oPortal,FALSE,2.0,120.0));
|
|
} // walk to portal
|
|
} // not fighting
|
|
DelayCommand(fSpeed,fnShadowAI());
|
|
} // fnShadowAI()
|
|
|
|
|
|
////////////////////////////////////////////////// MAIN ////////////////////
|
|
/*void main()
|
|
{
|
|
object oPC=GetFirstPC();
|
|
object oWP=GetWaypointByTag("ENTER_THE_SHADOW");
|
|
object oCP;
|
|
int nCount=1;
|
|
object oCR=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oWP,nCount);
|
|
int nHostiles;
|
|
object oAttract;
|
|
object oATarget;
|
|
object oMod=GetModule();
|
|
string sShadow;
|
|
int nC;
|
|
float fDist;
|
|
int nRun=FALSE;
|
|
if (GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oWP,1)!=OBJECT_INVALID)
|
|
{ // PC is in area
|
|
while(oCR!=OBJECT_INVALID)
|
|
{ // check PCs for light source
|
|
nRun=FALSE;
|
|
if(HasLightSource(oCR)==TRUE)
|
|
{ // carrying a light
|
|
oATarget=oCR;
|
|
nHostiles=CountShadowCreatures();
|
|
if (nHostiles<8)
|
|
{ // possibly attract another
|
|
sShadow=fnSpawnType(oCR);
|
|
if (GetStringLength(sShadow)>1)
|
|
{ // yes one was attracted
|
|
oCP=GetWaypointByTag("SR_SPAWN_"+IntToString(d10()));
|
|
if (oCP!=OBJECT_INVALID&&GetObjectType(oCP)==OBJECT_TYPE_WAYPOINT)
|
|
{ // valid location
|
|
oAttract=CreateObject(OBJECT_TYPE_CREATURE,sShadow,GetLocation(oCP));
|
|
if (oAttract!=OBJECT_INVALID)
|
|
{ // was conjured
|
|
SetLocalObject(oAttract,"oTarget",oCR);
|
|
if(d8()<5) nRun=TRUE;
|
|
AssignCommand(oAttract,ActionForceMoveToObject(oCR,nRun,3.0,90.0));
|
|
} // was conjured
|
|
} // valid location
|
|
} // yes one was attracted
|
|
} // possibly attract another
|
|
} // carrying a light
|
|
if (GetIsEnemy(oPC,oCR)==TRUE)
|
|
{ // this is a hostile make sure still has a target
|
|
oAttract=GetLocalObject(oCR,"oTarget");
|
|
if (oAttract==OBJECT_INVALID&&oATarget!=OBJECT_INVALID)
|
|
{ // assign default
|
|
SetLocalObject(oCR,"oTarget",oATarget);
|
|
if(d8()<5) nRun=TRUE;
|
|
AssignCommand(oCR,ActionForceMoveToObject(oATarget,nRun,3.0,90.0));
|
|
} // assign default
|
|
else if ((GetArea(oAttract)!=GetArea(oCR)||HasLightSource(oAttract)==FALSE)&&
|
|
(GetDistanceBetween(oAttract,oCR)>10.0))
|
|
{ // change targets
|
|
SetLocalObject(oCR,"oTarget",oATarget);
|
|
if(d8()<5) nRun=TRUE;
|
|
AssignCommand(oCR,ActionForceMoveToObject(oATarget,nRun,3.0,90.0));
|
|
} // change targets
|
|
} // this is a hostile make sure still has a target
|
|
oATarget=GetLocalObject(oCR,"oTarget");
|
|
if (GetDistanceBetween(oATarget,oCR)==0.0)
|
|
{ // target is not here
|
|
SetLocalObject(oCR,"oTarget",OBJECT_INVALID);
|
|
oATarget=GetNearestObjectByTag("soul_token",oCR,1);
|
|
fDist=GetDistanceBetween(oCR,oATarget);
|
|
if (fDist!=0.0&&fDist<15.0)
|
|
{ // move to soul and eat it
|
|
nC=GetLocalInt(oMod,"nShadowSouls");
|
|
AssignCommand(oCR,ActionForceMoveToLocation(GetLocation(oATarget),TRUE,1.0));
|
|
DestroyObject(oCR);
|
|
nC++;
|
|
SetLocalInt(oMod,"nShadowSouls",nC);
|
|
} // move to soul and eat it
|
|
} // target is not here
|
|
nCount++;
|
|
oCR=GetNearestObject(OBJECT_TYPE_CREATURE,oWP,nCount);
|
|
} // check creatures for light source
|
|
} // PC is in area
|
|
} */
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void main()
|
|
{ // shadow realm 1 - hb rewrite
|
|
object oWP=GetWaypointByTag("ENTER_THE_SHADOW");
|
|
object oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oWP,1);
|
|
int nC;
|
|
object oLoc;
|
|
int nR;
|
|
object oCR;
|
|
string sShadow;
|
|
while(oPC!=OBJECT_INVALID)
|
|
{ // check PCs for light sources
|
|
if (HasLightSource(oPC)==TRUE)
|
|
{ // PC is carrying light
|
|
nR=CountShadowCreatures();
|
|
if (nR<8)
|
|
{ // okay to spawn another
|
|
oLoc=GetWaypointByTag("SR_SPAWN_"+IntToString(d10()));
|
|
if (oLoc!=OBJECT_INVALID)
|
|
{ // spawn shadow critters
|
|
sShadow=fnSpawnType(oPC);
|
|
oCR=CreateObject(OBJECT_TYPE_CREATURE,sShadow,GetLocation(oLoc));
|
|
if (oCR!=OBJECT_INVALID) AssignCommand(oCR,fnShadowAI());
|
|
} // spawn shadow critters
|
|
} // okay to spawn another
|
|
} // PC is carrying light
|
|
nC++;
|
|
oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oWP,nC);
|
|
} // check PCs for light sources
|
|
DelayCommand(1.0,ExecuteScript("area_hb_clean",OBJECT_SELF));
|
|
} // shadow realm 1 - hb rewrite
|