377 lines
12 KiB
Plaintext
377 lines
12 KiB
Plaintext
// hb avernus
|
|
#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 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(oItem));
|
|
} // 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=d10();
|
|
oEnemy=GetNearestObjectByTag("BAATOR1_WANDER"+IntToString(nR),oMe);
|
|
AssignCommand(oMe,ASActionMoveToObject(oEnemy,FALSE,1.0));
|
|
} // move
|
|
}// check for containers
|
|
} // wander
|
|
DelayCommand(24.0,fnWander());
|
|
} // fnWander()
|
|
|
|
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 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 fnTown()
|
|
{ // Town interaction
|
|
object oDest=GetLocalObject(OBJECT_SELF,"oBDest");
|
|
int nR;
|
|
object oMe=OBJECT_SELF;
|
|
int nState=GetLocalInt(oMe,"nState");
|
|
if (GetIsInCombat(oMe)!=TRUE)
|
|
{ // not in combat
|
|
switch(nState)
|
|
{ // town interaction switch
|
|
case 0: { // choose waypoint
|
|
nR=d4();
|
|
oDest=GetWaypointByTag("ELY1_TOWN"+IntToString(nR));
|
|
SetLocalObject(oMe,"oBDest",oDest);
|
|
SetLocalInt(oMe,"nState",1);
|
|
AssignCommand(oMe,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
break;
|
|
} // choose waypoint
|
|
case 1: { // await arrival at waypoint
|
|
if (GetDistanceBetween(oDest,oMe)>2.5)
|
|
{ // still too far away
|
|
if (GetCurrentAction(oMe)!=ACTION_MOVETOPOINT)
|
|
{ // move
|
|
AssignCommand(oMe,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
} // move
|
|
} // still too far away
|
|
else
|
|
{ // close enough
|
|
SetLocalInt(oMe,"nState",2);
|
|
} // close enough
|
|
break;
|
|
} // await arrival at waypoint
|
|
case 2: { // act
|
|
nR=d6();
|
|
if (nR==1)
|
|
{ // talk
|
|
oDest=GetNearestCreature(CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN,oMe,1);
|
|
if (oDest!=OBJECT_INVALID)
|
|
{ //!OI
|
|
AssignCommand(oMe,ActionMoveToObject(oDest,FALSE,2.0));
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL,1.0,5.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} //!OI
|
|
} // talk
|
|
else if (nR==2)
|
|
{ // sitc
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS,1.0,9.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} // sitc
|
|
else if (nR==3)
|
|
{ // drink
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_FIREFORGET_DRINK,1.0,9.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} // drink
|
|
else if (nR==4)
|
|
{ // look far
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_LOOK_FAR,1.0,5.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} // look far
|
|
else if (nR==5)
|
|
{ // read
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_FIREFORGET_READ,1.0,9.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} // read
|
|
else if (nR==6)
|
|
{ // talk laughing
|
|
oDest=GetNearestCreature(CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN,oMe,1);
|
|
if (oDest!=OBJECT_INVALID)
|
|
{ //!OI
|
|
AssignCommand(oMe,ActionMoveToObject(oDest,FALSE,2.0));
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING,1.0,5.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} //!OI
|
|
} // talk laughing
|
|
break;
|
|
} // act
|
|
default: { SetLocalInt(oMe,"nState",0); break; }
|
|
} // town interaction switch
|
|
} // not in combat
|
|
DelayCommand(10.0,fnTown());
|
|
} // fnTown()
|
|
|
|
void fnTemple()
|
|
{ // Temple interaction
|
|
object oDest=GetLocalObject(OBJECT_SELF,"oBDest");
|
|
int nR;
|
|
object oMe=OBJECT_SELF;
|
|
int nState=GetLocalInt(oMe,"nState");
|
|
if (GetIsInCombat(oMe)!=TRUE)
|
|
{ // not in combat
|
|
switch(nState)
|
|
{ // temple interaction switch
|
|
case 0: { // choose waypoint
|
|
nR=d4();
|
|
oDest=GetWaypointByTag("ELY1_TEMPLE"+IntToString(nR));
|
|
SetLocalObject(oMe,"oBDest",oDest);
|
|
SetLocalInt(oMe,"nState",1);
|
|
AssignCommand(oMe,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
break;
|
|
} // choose waypoint
|
|
case 1: { // await arrival at waypoint
|
|
if (GetDistanceBetween(oDest,oMe)>2.5)
|
|
{ // still too far away
|
|
if (GetCurrentAction(oMe)!=ACTION_MOVETOPOINT)
|
|
{ // move
|
|
AssignCommand(oMe,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
} // move
|
|
} // still too far away
|
|
else
|
|
{ // close enough
|
|
SetLocalInt(oMe,"nState",2);
|
|
} // close enough
|
|
break;
|
|
} // await arrival at waypoint
|
|
case 2: { // act
|
|
nR=d4();
|
|
if (nR==1)
|
|
{ // worship
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_WORSHIP,1.0,9.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} // worship
|
|
else if (nR==2)
|
|
{ // meditate
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,9.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} // meditate
|
|
else if (nR==3)
|
|
{ // talk pleading
|
|
oDest=GetNearestCreature(CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN,oMe,1);
|
|
if (oDest!=OBJECT_INVALID)
|
|
{ //!OI
|
|
AssignCommand(oMe,ActionMoveToObject(oDest,FALSE,2.0));
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_TALK_PLEADING,1.0,5.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} //!OI
|
|
} // talk pleading
|
|
else if (nR==4)
|
|
{ // sitc
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS,1.0,9.0));
|
|
AssignCommand(oMe,ActionDoCommand(SetLocalInt(oMe,"nState",0)));
|
|
} // sitc
|
|
break;
|
|
} // act
|
|
default: { SetLocalInt(oMe,"nState",0); break; }
|
|
} // temple interaction switch
|
|
} // not in combat
|
|
DelayCommand(10.0,fnTemple());
|
|
} // fnTemple()
|
|
|
|
void fnBehavior(object oCreature,int nBehavior)
|
|
{ // assign behavior to the creature
|
|
// 1 = wander for 4 hours
|
|
// 2 = Town interaction
|
|
// 3 = temple interaction
|
|
// 4 = move to point and despawn
|
|
object oDest;
|
|
object oNear;
|
|
int nR;
|
|
float fDelay=HoursToSeconds(4);
|
|
if (nBehavior==1)
|
|
{ // wander
|
|
AssignCommand(oCreature,fnWander());
|
|
AssignCommand(oCreature,DelayCommand(fDelay,fnDestroy()));
|
|
} // wander
|
|
else if (nBehavior==2)
|
|
{ // town interaction
|
|
AssignCommand(oCreature,fnTown());
|
|
AssignCommand(oCreature,DelayCommand(fDelay,fnDestroy()));
|
|
} // town interaction
|
|
else if (nBehavior==3)
|
|
{ // temple interaction
|
|
AssignCommand(oCreature,fnTemple());
|
|
AssignCommand(oCreature,DelayCommand(fDelay,fnDestroy()));
|
|
} // temple interaction
|
|
else if (nBehavior==4)
|
|
{ // move to point
|
|
oNear=GetNearestObject(OBJECT_TYPE_WAYPOINT,oCreature,1);
|
|
nR=d4();
|
|
oDest=GetWaypointByTag("BAATOR1_SPAWN"+IntToString(nR));
|
|
if (oDest==oNear)
|
|
{ // pick another
|
|
nR++;
|
|
if (nR>4) nR=1;
|
|
oDest=GetWaypointByTag("BAATOR1_SPAWN"+IntToString(nR));
|
|
} // pick another
|
|
SetLocalObject(oCreature,"oBDest",oDest);
|
|
AssignCommand(oCreature,fnMoveTo());
|
|
} // move to point
|
|
} // fnBehavior
|
|
|
|
void fnResidents(object oArea)
|
|
{ // spawn residents if need be
|
|
object oMod=GetModule();
|
|
int nR;
|
|
int nC=fnCountResidents();
|
|
int nSP=d4();
|
|
object oFirst=GetFirstObjectInArea(oArea);
|
|
object oCR;
|
|
int nST=VFX_IMP_LIGHTNING_M;
|
|
object oSpawnPoint=GetWaypointByTag("BAATOR1_SPAWN"+IntToString(nSP));
|
|
location lLoc=GetLocation(oSpawnPoint);
|
|
string sRes;
|
|
effect eAura=EffectVisualEffect(VFX_DUR_GLOW_WHITE);
|
|
oFirst=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,1);
|
|
if (nC<8)
|
|
{ // spawn okay
|
|
nR=d100();
|
|
if (nR<36)
|
|
{ // spawn
|
|
nR=d100();
|
|
if (nR<34)
|
|
{ // Lemure
|
|
sRes="lemure";
|
|
} // Lemure
|
|
else if (nR<67)
|
|
{ // petitioners
|
|
nR=d100();
|
|
nST=VFX_IMP_BREACH;
|
|
if (nR<34)
|
|
sRes="imp001";
|
|
else if (nR<67)
|
|
sRes="hellcat";
|
|
else {
|
|
sRes="skelwarr003"; }
|
|
} // petitioners
|
|
else if (nR<98)
|
|
{ // Devils
|
|
nR=d100();
|
|
if (nR<34) sRes="bonedevil";
|
|
else if (nR<88) sRes="erinyes001";
|
|
else { sRes="gelugon"; }
|
|
} // Devils
|
|
else
|
|
{ // Big Devils
|
|
nR=d100();
|
|
if (nR<46) sRes="gelugon";
|
|
else if (nR<95) sRes="devil002";
|
|
else { sRes="goldmflesh002"; }
|
|
|
|
} // Big Devils
|
|
oCR=fnSpawn(sRes,lLoc,nST);
|
|
nR=d4(); // behavior
|
|
if (GetTag(oCR)=="GodElundur"||GetTag(oCR)=="GoddessAbigail")
|
|
{ // god aura
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eAura,oCR,10000.0);
|
|
nR=1; // wander for 4 hours
|
|
} // god aura
|
|
nR=1;
|
|
if (d4()<3) nR=4;
|
|
fnBehavior(oCR,nR);
|
|
} // spawn
|
|
} // spawn okay
|
|
} // 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 in The Nine Hells.");
|
|
fnResidents(oMe);
|
|
//fnVisualEffects(oMe);
|
|
} // PCs present
|
|
ExecuteScript("area_hb_clean",oMe);
|
|
|
|
}
|