RE: Server sided AI
(06-14-2013 08:09 AM)Ozmodian Wrote: Some people were asking for 2.0 code. I only made a very small change to use UID instead of file name but thought i should post it:
Client.AI
Code:
class AI : Game::Chr
{
Int ID; //ID so that we can identify which the server wants us to use
Vec OldLocation; //Old target location
Str Name; // Name-
Flt scale =2.0;
//Memc<AI> ai;
void AI::spawn(Str name, Game.ObjParamsPtr &obj, Int id, Vec pos)
{
super.create(*Game.Objs(obj.id())); //Create the object.
// Log(S+"Create successful on " + id + "\n");
Name = name; //Add specifics read from server.
ID = id;
Flt y = Game.World.hmHeight(pos.xz(),true)+0.6f;
T.pos(pos+Vec(0,y,0)); //Add Y so that it doesn't spawn just under the map.
ctrl.actor.group(AG_AI);//Set actor group to 1 so that we can disable collision (pushing of monsters)
//Log(S+"Got to end of spawn on " + id + "\n");
}
bool AI::update(){
if(super::update())
{
if( OldLocation!=0 && (T.pos() - OldLocation).length() < 2.0)T.actionBreak();
return true;
}
return false;
}
void AI::Move(Vec pos){
if(OldLocation!=0 && (T.pos() - OldLocation).length() > 3.0/*T.pos() != OldLocation*/)T.pos(OldLocation); // If old location is not already reached, set the position instantly there.
Flt y = Game::World.hmHeight(pos.xz(),true)+0.6f; //Get height of target location
T.actionMoveDir(Vec(pos.x, y, pos.z) - T.pos());//Move to locationPlr.pos() - T.pos()
OldLocation = pos+Vec(0,y,0);//Set previous Location target so that we can check when receiving next time.
// CM.New(S+"Newoldpos "+OldLocation);
}
void AI::drawName(){
Vec2 NamePos = PosToScreen(pos()+Vec(0,T.ctrl.height(),0)); // Position of monster + it's height.
if(Dist(pos(), Plr.pos())<D.viewRange()/3){ // if distance of /3
if(visible())D.text(NamePos, S+Name+ID);
}
}
void AI::Action(Byte b ){
}
bool visible() {return Frustum(mesh->box, Matrix(scale, pos()));}
}
Memc<AI> ai;
Client.Game
Code:
case CS_AI_SPAWN:
{
//CM.New("Recieved CS_AI_SPAWN");
Str name; Game.ObjParamsPtr obj; Int id; Vec Pos;
Server.data.getStr(name).decIntV(id).decFlt3cm(Pos.x).decFlt3cm(Pos.z); obj = Server.data.getUID();
ai.New().spawn(name, obj, id, Pos);
//File f = Server.data;
//Str name = Server.data.getStr(); Str obj = Server.data.getStr(); Int id = Server.data.decIntV(); Flt x = Server.data.decFlt3cm(); Flt z = Server.data.decFlt3cm();ai.New().spawn(name,obj,id,Vec(x,0,z));
} break;
case CS_AI_MOVE:
{
//CM.New("Recieved CS_AI_MOVE");
Int id = Server.data.decIntV(); Flt x = Server.data.decFlt3cm(); Flt z = Server.data.decFlt3cm(); Int ith; REPA(ai)if(ai[i].ID == id)ith =i; ai[ith].Move(Vec(x,0,z));
} break;
case CS_AI_ACTION:
{
//CM.New("Recieved CS_AI_ACTION");
} break;
Server.AI
Code:
class ArtificialIntelligence
{
/* void createAI(Int, Str, Str, Vec, Flt); //Create
bool update ( ); //Update loop
void spawn (Int);
bool foundtarget(Int);
void sendMovement();
void sendAction (); */
ArtificialIntelligence(){MovementTimer = RandomF(2,6); ActionTimer = RandomF(10,15);} //Set timers at construction
//private:
Memc<Client*> active_clients; //Active list of clients. The clients that has this monster spawned.
Str Creature_Name;
Vec Position ;
Game.ObjParamsPtr Object ; //Object path.
Int Creature_ID ;
Flt MovementTimer;
Flt ActionTimer ;
Ball RadiusBall ;
::Client& client(Int i) {return (::Client&)Server.clients.lockedData(i);}
//Memc<ArtificialIntelligence> ai;
void ArtificialIntelligence::createAI(Int id, Str name, Vec pos, Flt radius, Game.ObjParamsPtr &object){
Creature_ID = id; //Set creature ID
Creature_Name = name; //Set Creature Name
Object = object; //Object path, example "Obj/Chr/Skeleton/0.obj"
Position = pos; //Start position
RadiusBall.r = radius; //Radius it can move in each move command.
}
bool ArtificialIntelligence::update()
{
REPA(active_clients)
{
if(!active_clients[i].inGame())active_clients.remove(i); // need to remove clients that have exited game/went back to login screen
}
REPA(Server.clients){
if(client(i).inGame()/*state == iGame*/)if(Dist(Position,client(i).pos())>50)foundtarget(i); // go to state of processing if you should spawn a monster for this or if it's already spawned
}
MovementTimer -= Time.d();
ActionTimer -= Time.d();
if(MovementTimer <= 0)sendMovement();
//if(ActionTimer <= 0)sendAction();
return true;
}
void ArtificialIntelligence::spawn(Int i){
File f;
f.writeMem().putByte(CS_AI_SPAWN);
f.putStr(Creature_Name).
cmpIntV(Creature_ID ).
cmpFlt3cm(Position.x).
cmpFlt3cm(Position.z)
<<Object.id();
f.pos(0);
//Log(S+"Server Spawn " + Creature_ID);
client(i).connection.dataFull(f,f.left());
active_clients.New() = &client(i); //Directly after spawning the monster set the client into the monsters active list.
}
bool ArtificialIntelligence::foundtarget(Int a){
Int temp = 0;
REPA(active_clients){
if(active_clients[i] ==&client(a)){return false;} //If client is in monster list directly return false so that it is not spawned again.
if(active_clients[i] !=&client(a)){temp++;}
}
if(!active_clients.elms()){ //If there are no Active clients, add the first one
spawn(a);
return true;
}
if((temp-active_clients.elms())==0){ //If the client wasn't found in the active list spawn it.
spawn(a);
return true;
}
return false;
}
void ArtificialIntelligence::sendMovement(){
//tryagain:;
Vec test = Position +=Random(RadiusBall,true); //Test,
/*if(map.checkpos(test))*/{ //Map checking will be added later on
MovementTimer = RandomF(2, 10); //Reset timer
File f;
f.writeMem().putByte(CS_AI_MOVE);
f.cmpIntV(Creature_ID ).
cmpFlt3cm(Position.x).
cmpFlt3cm(Position.z);
REPA(active_clients){f.pos(0); active_clients[i]->connection.dataFull(f,f.left(),true);} //Send movement to all active clients.
}/*else goto tryagain; */ //If position failed and it's on an invalid place, then start over to try another position
}
void ArtificialIntelligence::sendAction(){
File f;
f.writeMem().putByte(CS_AI_ACTION);
f.cmpIntV(Creature_ID ).putByte(Random(0,2)); //Put random action 0-2
REPA(active_clients){f.pos(0); active_clients[i]->connection.dataFull(f,f.left(),true);} //Send action to all clients.
}
}
Memc<ArtificialIntelligence> ai;
Server.main
Code:
REP(10)ai.New().createAI(i,"Warrior",Vec(RandomF(0,20),RandomF(0,20),RandomF(0,20)),10, Game.ObjParamsPtr(UID(1789382582, 1118947404, 2757836681, 1453939461)));
[/php]
Thanks for doing this. I stepped away from AI to learn more about the engine and its functions. I think I'm ready to try and tackle this. Thanks for sharing
|