HoS_PRC8/_mod/_module/nss/astral_hb.nss
Jaysyn904 04165202c0 Initial upload
Initial upload
2024-11-25 19:36:07 -05:00

454 lines
14 KiB
Plaintext

////////////////////////////////////////////////////////////////////////
// Astral Plane Heartbeat
////////////////////////////////////////////////////////////////////////
#include "antistuck_h"
int fnCountResidents()
{ // return how many NPCs in the area
int nRet=0;
int nC=1;
object oCr=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,OBJECT_SELF,nC,CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_NOT_PC);
while(oCr!=OBJECT_INVALID)
{ // count
nRet++;
nC++;
oCr=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,OBJECT_SELF,nC,CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_NOT_PC);
} // count
return nRet;
} // fnCountResidents()
void fnMoveTo()
{ // move to point and despawn
object oMe=OBJECT_SELF;
object oDest=GetLocalObject(oMe,"oBDest");
float fDist=GetDistanceBetween(oMe,oDest);
effect eVis=EffectVisualEffect(VFX_FNF_IMPLOSION);
if (GetIsInCombat(oMe)!=TRUE)
{ // not fighting
if (fDist<3.0)
{ // arrived
ApplyEffectToObject(DURATION_TYPE_INSTANT,eVis,oMe,3.0);
DelayCommand(2.0,DestroyObject(oMe));
} // arrived
else
{ // move
AssignCommand(oMe,ASActionMoveToObject(oDest,FALSE,1.0));
} // move
} // not fighting
DelayCommand(10.0,fnMoveTo());
} // fnMoveTo()
void fnDestroyContainer(object oContainer)
{ // empty items
object oItem=GetFirstItemInInventory(oContainer);
while(oItem!=OBJECT_INVALID)
{
DelayCommand(0.2,DestroyObject(oItem));
oItem=GetNextItemInInventory(oContainer);
}
DelayCommand(0.3,DestroyObject(oContainer));
} // fnDestroyContainer()
object fnSpawn(string sRes,location lLoc,int nVis=VFX_FNF_SUMMON_MONSTER_1)
{ // create creature
object oRet;
effect eVis=EffectVisualEffect(nVis);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis,lLoc,1.0);
oRet=CreateObject(OBJECT_TYPE_CREATURE,sRes,lLoc,FALSE);
return oRet;
} // fnSpawn()
void fnWander()
{ // wander
object oMe=OBJECT_SELF;
object oEnemy=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oMe,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
int nR;
if (GetIsInCombat(oMe)!=TRUE&&oEnemy==OBJECT_INVALID)
{ // wander
oEnemy=GetNearestObject(OBJECT_TYPE_ITEM,oMe,1);
if (oEnemy!=OBJECT_INVALID&&GetDistanceBetween(oEnemy,oMe)<20.0)
{ // cleanup item
AssignCommand(oMe,ClearAllActions());
AssignCommand(oMe,ActionMoveToObject(oEnemy,TRUE,1.0));
AssignCommand(oMe,ActionDoCommand(fnDestroyContainer(oEnemy)));
} // cleanup item
else
{ // check for containers
oEnemy=GetNearestObject(OBJECT_TYPE_PLACEABLE,oMe,1);
if (oEnemy!=OBJECT_INVALID&&GetDistanceBetween(oEnemy,oMe)<20.0&&GetHasInventory(oEnemy)==TRUE)
{ // empty container
AssignCommand(oMe,ClearAllActions());
AssignCommand(oMe,ActionMoveToObject(oEnemy,TRUE,1.0));
AssignCommand(oMe,ActionDoCommand(fnDestroyContainer(oEnemy)));
} // empty container
else
{ // move
nR=d20();
oEnemy=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,nR);
AssignCommand(oMe,ASActionMoveToObject(oEnemy,FALSE,1.0));
} // move
}// check for containers
} // wander
DelayCommand(15.0,fnWander());
} // fnWander()
void fnDestroy()
{ // destroy self
object oMe=OBJECT_SELF;
object oEnemy=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oMe,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
effect eVis=EffectVisualEffect(VFX_FNF_IMPLOSION);
if (GetIsInCombat(oMe)!=TRUE&&oEnemy==OBJECT_INVALID)
{ // Destroy Self
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis,GetLocation(oMe),3.0);
DelayCommand(1.0,DestroyObject(oMe));
} // Destroy Self
else
{ // wait a bit longer
DelayCommand(20.0,fnDestroy());
} // wait a bit longer
} // fnDestroy()
void fnAssignBehavior(object oCreature,int nBehavior)
{ // start the behavior for the NPC creature
// 1 = wander for 2 game hours
// 2 = wander for 4 game hours
// 3 = go to another spawn point and despawn
// 4 = wander for 6 game hours
object oDest;
object oNear;
int nR;
float fDelay=HoursToSeconds(2);
if (nBehavior==2) fDelay=HoursToSeconds(4);
else if (nBehavior==4) fDelay=HoursToSeconds(6);
if (nBehavior!=3)
{ // wander
AssignCommand(oCreature,fnWander());
AssignCommand(oCreature,DelayCommand(fDelay,fnDestroy()));
} // wander
else
{ // move to destination
oNear=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,oCreature,1);
oDest=OBJECT_INVALID;
if (oNear!=OBJECT_INVALID)
{ // see if has a destination
oDest=GetLocalObject(oNear,"oBDest");
} // see if has a destination
if (oDest==OBJECT_INVALID)
{ // find a destination
oNear=GetNearestObject(OBJECT_TYPE_WAYPOINT,oCreature,1);
nR=d6();
oDest=GetWaypointByTag("ASTRAL_SPAWN"+IntToString(nR));
if (oDest==oNear)
{ // pick another
nR++;
if (nR>6) nR=1;
oDest=GetWaypointByTag("ASTRAL_SPAWN"+IntToString(nR));
} // pick another
} // find a destination
SetLocalObject(oCreature,"oBDest",oDest);
AssignCommand(oCreature,fnMoveTo());
} // move to destination
} // fnAssignBehavior()
void fnResidents(object oMe)
{ // determine if need to spawn creatures and handle their behaviour
object oArea=GetArea(oMe);
object oMod=GetModule();
int nEvil=GetLocalInt(oMod,"nEvilPower");
int nR;
int nC=fnCountResidents();
int nSP=d6();
object oCR;
object oSpawnPoint=GetWaypointByTag("ASTRAL_SPAWN"+IntToString(nSP));
location lLoc=GetLocation(oSpawnPoint);
string sRes;
int nBehavior=d4();
//SendMessageToPC(GetFirstPC()," COUNT of ASTRAL CREATURES:"+IntToString(nC));
if (nC<8)
{ // spawn chance
nR=d100();
//SendMessageToPC(GetFirstPC(),"Rolled a "+IntToString(nR)+" percentile.");
if (nR<21)
{ // spawn
nR=d100()+(nEvil/100);
if (nR<34)
{ // Githyanki
nR=d100();
if (nR<11)
{ // lone warlock
oCR=fnSpawn("githyankiwarlock",lLoc);
fnAssignBehavior(oCR,nBehavior);
} // lone warlock
else if (nR<21)
{ // lone gith
oCR=fnSpawn("githyankigith",lLoc);
fnAssignBehavior(oCR,nBehavior);
} // lone gith
else if (nR<95)
{ // company
oCR=fnSpawn("githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
oCR=fnSpawn("githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
oCR=fnSpawn("githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
oCR=fnSpawn("githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
} // company
else
{ // squad
oCR=fnSpawn("githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"githyankiwarrior",lLoc);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"githyankiwarlock",lLoc);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"githyankigith",lLoc);
fnAssignBehavior(oCR,3);
} // squad
} // Githyanki
else if (nR<60)
{ // Deva
nR=d100();
if (nR<34)
{ // Movanic
oCR=fnSpawn("movanicdeva",lLoc,VFX_FNF_SUMMON_MONSTER_2);
fnAssignBehavior(oCR,nBehavior);
} // Movanic
else if (nR<67)
{ // Monadic
oCR=fnSpawn("monadicdeva",lLoc,VFX_FNF_SUMMON_MONSTER_2);
fnAssignBehavior(oCR,nBehavior);
} // Monadic
else if (nR<91)
{ // Astral
oCR=fnSpawn("astraldeva",lLoc,VFX_FNF_SUMMON_MONSTER_3);
fnAssignBehavior(oCR,nBehavior);
} // Astral
else if (nR<99)
{ // Planetar
oCR=fnSpawn("planetar",lLoc,VFX_FNF_SUMMON_CELESTIAL);
fnAssignBehavior(oCR,nBehavior);
} // Planetar
else
{ // solar
oCR=fnSpawn("solar",lLoc,VFX_FNF_SUMMON_CELESTIAL);
fnAssignBehavior(oCR,nBehavior);
} // solar
} // Deva
else if (nR<75)
{ // elementals
nR=d100();
if (nR<34)
{ // fire
nR=d100();
if (nR<21) sRes="fire001";
else if (nR<91) sRes="firehuge001";
else { sRes="fireelder001"; }
nR=VFX_IMP_FLAME_M;
} // fire
else if (nR<67)
{ // earth
nR=d100();
if (nR<21) sRes="earth001";
else if (nR<91) sRes="earthhuge001";
else { sRes="eartheld001"; }
nR=VFX_IMP_BREACH;
} // earth
else
{ // air
nR=d100();
if (nR<21) sRes="air001";
else if (nR<91) sRes="airhuge001";
else { sRes="airelder001"; }
nR=VFX_IMP_LIGHTNING_M;
} // air
oCR=fnSpawn(sRes,lLoc,nR);
fnAssignBehavior(oCR,nBehavior);
} // elementals
else if (nR<85)
{ // miscellaneous
nR=d100();
if (nR<34)
{ // passing through
oCR=fnSpawn("azer002",lLoc,VFX_IMP_FLAME_M);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"azer002",lLoc);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"azer003",lLoc);
fnAssignBehavior(oCR,3);
oCR=CreateObject(OBJECT_TYPE_CREATURE,"azer003",lLoc);
fnAssignBehavior(oCR,3);
} // passing through
else
{ // other
nR=d100();
if (nR<8)
{
nR=VFX_FNF_SUMMON_MONSTER_2;
sRes="nighthag";
}
else if (nR<20)
{
nR=VFX_FNF_SUMMON_MONSTER_2;
sRes="rakshasa001";
}
else if (nR<30)
{
nR=VFX_FNF_SUMMON_MONSTER_1;
sRes="dmquasit001";
}
else if (nR<40)
{
nR=VFX_FNF_SUMMON_MONSTER_1;
sRes="imp001";
}
else if (nR<50)
{
nR=VFX_FNF_SUMMON_MONSTER_2;
sRes="drider002";
}
else if (nR==50)
{
nR=VFX_FNF_SUMMONDRAGON;
sRes="dragonpris002";
}
else if (nR==51)
{
nR=VFX_FNF_UNDEAD_DRAGON;
sRes="dracolich002";
}
else if (nR==52)
{
nR=VFX_FNF_SUMMON_EPIC_UNDEAD;
sRes="lich002";
}
else if (nR==53)
{
nR=VFX_FNF_SUMMON_UNDEAD;
sRes="demilich003";
}
else
{ // Slaad
nR=d100();
if (nR<34)
sRes="slaadred001";
else if (nR<51)
sRes="slaadbl001";
else if (nR<76)
sRes="slaadgrn001";
else if (nR<88)
sRes="slaadgray001";
else if (nR<95)
sRes="slaaddeth001";
else if (nR<99)
sRes="slaadwhite002";
else { sRes="slaadblack002"; }
nR=VFX_FNF_SUMMON_MONSTER_3;
} // slaad
oCR=fnSpawn(sRes,lLoc,nR);
fnAssignBehavior(oCR,nBehavior);
} // other
} // miscellaneous
else
{ // fiends
nR=d100();
if (nR<50)
{ // least
nR=d100();
if (nR<51)
sRes="erinyes001";
else { sRes="dmsucubus001"; }
} // least
else if (nR<70)
{ // lesser
nR=d100();
if (nR<51)
sRes="maurezhi";
else { sRes="dmvrock001"; }
} // lesser
else if (nR<80)
{ // mid
nR=d100();
if (nR<51)
sRes="devil002";
else { sRes="demon001"; }
} // mid
else if (nR<99)
{ // upper
nR=d100();
if (nR<51)
sRes="devil003";
else { sRes="balorboss001"; }
} // upper
else
{ // greatest
sRes="demonlord";
} // greatest
oCR=fnSpawn(sRes,lLoc,VFX_FNF_SUMMON_GATE);
fnAssignBehavior(oCR,nBehavior);
} // fiends
//SendMessageToPC(GetFirstPC(),"A "+GetName(oCR)+" should have spawned at "+GetName(oSpawnPoint)+".");
} // spawn
} // spawn chance
} // fnResidents()
void fnVisualEffects(object oMe)
{ // do Astral plane visual effects
effect eVis1=EffectVisualEffect(VFX_IMP_TORNADO);
effect eVis2=EffectVisualEffect(VFX_FNF_SMOKE_PUFF);
effect eVis3=EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_ACID);
effect eVis4=EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_EVIL);
effect eVis5=EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_NATURE);
effect eVis6=EffectVisualEffect(VFX_FNF_ELECTRIC_EXPLOSION);
int nC=1;
int nR;
int nX;
int nY;
int nZ;
vector vVec;
location lLoc;
object oArea=GetArea(oMe);
while(nC<9)
{ // play visual effects
nX=Random(16)*10;
nY=Random(16)*10;
nZ=Random(4)*6;
vVec=Vector(IntToFloat(nX),IntToFloat(nY),IntToFloat(nZ));
lLoc=Location(oArea,vVec,0.0);
nR=d20();
if (nR<3)
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,eVis1,lLoc,6.0);
else if (nR<8)
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis2,lLoc,3.0);
else if (nR<12)
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis3,lLoc,3.0);
else if (nR<15)
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis4,lLoc,3.0);
else if (nR<18)
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis5,lLoc,3.0);
else { ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eVis6,lLoc,3.0); }
nC++;
} // play visual effects
} // fnResidents()
void main()
{
object oMe=OBJECT_SELF;
object oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oMe,1);
if (oPC!=OBJECT_INVALID)
{ // PCs present
SendMessageToPC(oPC,"You are wandering through the astral plane.");
fnResidents(oMe);
fnVisualEffects(oMe);
} // PCs present
ExecuteScript("area_hb_clean",oMe);
}