//////////////////////////////////////////////////// // 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