246 lines
8.1 KiB
Plaintext
246 lines
8.1 KiB
Plaintext
// spawn_ocean - Underwater Ocean spawn
|
|
#include "antistuck_h"
|
|
void fnSpawn(object oArea,object oCenter,int nNumber);
|
|
|
|
void fnBehavior()
|
|
{ // PURPOSE: Movement and behavior AI for animals
|
|
object oMe=OBJECT_SELF;
|
|
int nR=d8();
|
|
object oDest;
|
|
object oEnemy;
|
|
effect eE;
|
|
if (GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oMe)!=OBJECT_INVALID)
|
|
{ // PC is present
|
|
oEnemy=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY);
|
|
if (GetIsInCombat(oMe)==FALSE&&oEnemy==OBJECT_INVALID)
|
|
{ // not in combat and no perceived enemies
|
|
if (nR==1)
|
|
{ // ActionRandomWalk()
|
|
AssignCommand(oMe,ClearAllActions());
|
|
AssignCommand(oMe,ActionRandomWalk());
|
|
DelayCommand(12.0,fnBehavior());
|
|
} // ActionRandomWalk()
|
|
else if (nR==2)
|
|
{ // Animation sequence 1
|
|
AssignCommand(oMe,ClearAllActions());
|
|
AssignCommand(oMe,ActionPlayAnimation(ANIMATION_FIREFORGET_DODGE_SIDE,1.0,4.0));
|
|
DelayCommand(8.0,fnBehavior());
|
|
} // Animation sequence 1
|
|
else if (nR==3)
|
|
{ // Animation sequence 2
|
|
AssignCommand(oMe,ClearAllActions());
|
|
oDest=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
|
|
if (oDest!=OBJECT_INVALID)
|
|
{ // follow
|
|
AssignCommand(oMe,ActionForceFollowObject(oDest,3.0));
|
|
DelayCommand(24.0,fnBehavior());
|
|
} // follow
|
|
else
|
|
{ // delay
|
|
DelayCommand(8.0,fnBehavior());
|
|
} // delay
|
|
} // Animation sequence 2
|
|
else if (nR==4)
|
|
{ // disappear reappear
|
|
AssignCommand(oMe,ClearAllActions());
|
|
AssignCommand(oMe,ClearAllActions());
|
|
oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,3);
|
|
AssignCommand(oMe,ASActionMoveToObject(oDest,Random(2),3.0));
|
|
DelayCommand(12.0,fnBehavior());
|
|
} // disappear reappear
|
|
else if (nR==5)
|
|
{ // disappear and reappear elsewhere
|
|
AssignCommand(oMe,ClearAllActions());
|
|
oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,2);
|
|
AssignCommand(oMe,ASActionMoveToObject(oDest,Random(2),3.0));
|
|
DelayCommand(8.0,fnBehavior());
|
|
} // disappear and reappear elsewhere
|
|
else if (nR>5&&nR<8)
|
|
{ // move to waypoint
|
|
AssignCommand(oMe,ClearAllActions());
|
|
oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d20());
|
|
if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d12());
|
|
if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d10());
|
|
if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d8());
|
|
if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d6());
|
|
if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d4());
|
|
if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe);
|
|
AssignCommand(oMe,ASActionMoveToObject(oDest,Random(2),3.0));
|
|
DelayCommand(20.0,fnBehavior());
|
|
} // move to waypoint
|
|
else
|
|
{ // despawn + setup delayed new spawn
|
|
AssignCommand(oMe,ClearAllActions());
|
|
oDest=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC);
|
|
if (oDest!=OBJECT_INVALID)
|
|
{ // assign respawn to PC
|
|
AssignCommand(oDest,DelayCommand(11.0+IntToFloat(d100()),fnSpawn(GetArea(oMe),oDest,1)));
|
|
AssignCommand(oMe,ActionMoveAwayFromObject(oDest,TRUE,60.0));
|
|
} // assign respawn to PC
|
|
DelayCommand(10.0,DestroyObject(oMe));
|
|
} // despawn + setup delayed new spawn
|
|
} // not in combat and no perceived enemies
|
|
else
|
|
{ // keep trying
|
|
DelayCommand(12.0,fnBehavior());
|
|
} // keep trying
|
|
} // PC is present
|
|
else
|
|
{ // keep trying
|
|
DelayCommand(6.0,fnBehavior());
|
|
} // keep trying
|
|
} // fnBehavior()
|
|
|
|
|
|
int fnFindEmptySlot(object oArea)
|
|
{ // PURPOSE: Return slot for spawning
|
|
int nRet=0;
|
|
int nN=1;
|
|
object oOb=GetLocalObject(oArea,"oInhabitant"+IntToString(nN));
|
|
while(nN<=8&&nRet==0)
|
|
{ // look for spot
|
|
if (oOb==OBJECT_INVALID) return nN;
|
|
nN++;
|
|
oOb=GetLocalObject(oArea,"oInhabitant"+IntToString(nN));
|
|
} // look for spot
|
|
return nRet;
|
|
} // fnFindEmptySlot()
|
|
|
|
|
|
void fnCreate(object oArea,object oCenter,int nSlot,string sRes,int bAppear)
|
|
{ // PURPOSE: Spawn a creature
|
|
object oWP;
|
|
object oCreature;
|
|
int nN;
|
|
oWP=GetNearestObjectByTag("UNDERWATER_SPAWN",oCenter,d20());
|
|
if (oWP==OBJECT_INVALID) oWP=GetNearestObjectByTag("UNDERWATER_SPAWN",oCenter,d12());
|
|
if (oWP==OBJECT_INVALID) oWP=GetNearestObjectByTag("UNDERWATER_SPAWN",oCenter,d10());
|
|
if (oWP==OBJECT_INVALID) oWP=GetNearestObjectByTag("UNDERWATER_SPAWN",oCenter,d8());
|
|
if (oWP==OBJECT_INVALID) oWP=GetNearestObject(OBJECT_TYPE_WAYPOINT,oCenter);
|
|
if (oWP!=OBJECT_INVALID)
|
|
{ // spawn creature
|
|
oCreature=CreateObject(OBJECT_TYPE_CREATURE,sRes,GetLocation(oWP),bAppear);
|
|
SetLocalObject(oArea,"oInhabitant"+IntToString(nSlot),oCreature);
|
|
SetLocalInt(oCreature,"nSlot",nSlot);
|
|
AssignCommand(oCreature,fnBehavior());
|
|
} // spawn creature
|
|
} // fnCreate()
|
|
|
|
void fnSpawn(object oArea,object oCenter,int nNumber)
|
|
{ // PURPOSE: Spawn nNumber creatures
|
|
int nC;
|
|
int nSlot;
|
|
string sRes;
|
|
int bAppear;
|
|
int nRoll;
|
|
nC=1;
|
|
while(nC<=nNumber)
|
|
{ // find and call spawn
|
|
nSlot=fnFindEmptySlot(oArea);
|
|
nRoll=d100();
|
|
if (nRoll<51)
|
|
{ // small shark
|
|
sRes="smallshark";
|
|
bAppear=FALSE;
|
|
} // small shark
|
|
else if (nRoll<52)
|
|
{ // giant crab
|
|
sRes="gcrab";
|
|
bAppear=FALSE;
|
|
} // giant crab
|
|
else if (nRoll<66)
|
|
{ // Crab
|
|
sRes="crab";
|
|
bAppear=FALSE;
|
|
} // Crab
|
|
else if (nRoll<81)
|
|
{ // shark
|
|
sRes="shark";
|
|
bAppear=FALSE;
|
|
} // shark
|
|
else if (nRoll<88)
|
|
{ // tiny sea snake
|
|
sRes="tinyseasnake";
|
|
bAppear=TRUE;
|
|
} // tiny sea snake
|
|
else if (nRoll<92)
|
|
{ // large shark
|
|
sRes="largeshark";
|
|
bAppear=TRUE;
|
|
} // large shark
|
|
else if (nRoll<94)
|
|
{ // huge shark
|
|
sRes="hugeshark";
|
|
bAppear=FALSE;
|
|
} // huge shark
|
|
else if (nRoll<96)
|
|
{ // seasnake
|
|
sRes="seasnake";
|
|
bAppear=TRUE;
|
|
} // seasnake
|
|
else if (nRoll<97)
|
|
{ // hugeseasnake
|
|
sRes="hugeseasnake";
|
|
bAppear=FALSE;
|
|
} // hugeseasnake
|
|
else if (nRoll<99)
|
|
{ // medium sea snake
|
|
sRes="medseasnake";
|
|
bAppear=FALSE;
|
|
} // medium sea snake
|
|
else
|
|
{ // large sea snake
|
|
sRes="largeseasnake";
|
|
bAppear=FALSE;
|
|
} // large sea snake
|
|
if (nSlot!=0)
|
|
{
|
|
fnCreate(oArea,oCenter,nSlot,sRes,bAppear);
|
|
//if (GetIsPC(oCenter)) SendMessageToPC(oCenter," "+sRes);
|
|
}
|
|
nC++;
|
|
} // find and call spawn
|
|
} // fnSpawn()
|
|
|
|
|
|
void fnSpawnMonitor(object oArea,object oPC)
|
|
{ // PURPOSE: Make sure to keep spawns coming if PC stays in the area
|
|
int nSlot;
|
|
if (GetArea(oPC)==oArea&&GetIsPC(oPC))
|
|
{ // still in the area
|
|
nSlot=fnFindEmptySlot(oArea);
|
|
if (nSlot!=0) fnSpawn(oArea,oPC,1);
|
|
DelayCommand(120.0,fnSpawnMonitor(oArea,oPC));
|
|
} // still in the area
|
|
} // fnSpawnMonitor()
|
|
|
|
///////////////////////////////////////////////////////////////////////// MAIN
|
|
void main()
|
|
{
|
|
object oPC=OBJECT_SELF;
|
|
object oArea=GetArea(oPC);
|
|
int nC;
|
|
object oOb;
|
|
int nN=1;
|
|
int nR;
|
|
SendMessageToPC(oPC,"Spawning natural ocean life.");
|
|
oOb=GetLocalObject(oArea,"oInhabitant"+IntToString(nN));
|
|
while(nN<=8)
|
|
{ // count inhabitants
|
|
if (oOb!=OBJECT_INVALID) { nC++; }
|
|
nN++;
|
|
oOb=GetLocalObject(oArea,"oInhabitant"+IntToString(nN));
|
|
} // count inhabitants
|
|
nN=0;
|
|
if (nC<8)
|
|
{ // possible to spawn more
|
|
nN=8-nC;
|
|
nR=Random(nN)+1;
|
|
if (nN>4&&nR<5) nR=5;
|
|
//SendMessageToPC(oPC,"Spawn:"+IntToString(nR)+" of "+IntToString(nN)+" Count:"+IntToString(nC));
|
|
if (nR>0) fnSpawn(oArea,oPC,nR);
|
|
} // possible to spawn more
|
|
DelayCommand(120.0,fnSpawnMonitor(oArea,oPC));
|
|
}
|
|
///////////////////////////////////////////////////////////////////////// MAIN
|