rip out most of gamecode

This commit is contained in:
q66 2020-04-16 23:18:05 +02:00
parent 69ad67a65e
commit b03c776b81
21 changed files with 91 additions and 6291 deletions

View file

@ -21,12 +21,6 @@ defaultsoundpack = [
registersound // pain2
registersound "uphys/die1" 150
registersound "uphys/die2" 150
registersound "ctf/flagpickup" 100
registersound "ctf/flagdrop" 100
registersound "ctf/flagreturn" 100
registersound "ctf/flagscore" 100
registersound "ctf/flagreturn" 100
registersound "ctf/flagfail" 100
]
loadsoundpack = [

View file

@ -3,7 +3,6 @@
exec "config/ui/lib.cfg" // UI library
exec "config/ui/style.cfg" // Styles
exec "config/ui/scoreboard.cfg" // Scoreboard
exec "config/ui/edithud.cfg" // Edit HUD
exec "config/ui/fkey.cfg" // F# Key Menus
exec "config/ui/serverbrowser.cfg" // Server Browser
@ -36,46 +35,6 @@ UImenu "main" [
uifill 0.2 0.02 [UIbar 1]
UIbutton "hold2" [uitext "Quit" 0.65] 0.2 0.04 [quit]
]
if (! $mainmenu) [
uifill 0.02 0.24 [UIbar 0 1]
uivlist 0 [
if (isspectator $getclientnum) [
if $scoreboardmultiplayer [
if (ismaster $getclientnum) [
UIbutton "hold2" [uitext "Play" 0.65] 0.2 0.04 [hideui "main" ; spectator 0]
] [
if (> $getmastermode 1) [
uifill 0 0.04 [uitext "^f4Play" 0.65]
] [
UIbutton "hold2" [uitext "Play" 0.65] 0.2 0.04 [hideui "main" ; spectator 0]
]
]
] [
UIbutton "hold2" [uitext "Play" 0.65] 0.2 0.04 [hideui "main" ; spectator 0]
]
] [
UIbutton "hold2" [uitext "Spectate" 0.65] 0.2 0.04 [hideui "main" ; spectator 1]
]
case $getteam [
0] [uifill 0 0.04] [
1] [UIbutton "hold2" [uitext "Join ^f3Rojo" 0.65] 0.2 0.04 [team rojo]] [
2] [UIbutton "hold2" [uitext "Join ^f1Azul" 0.65] 0.2 0.04 [team azul]]
uifill 0.2 0.02 [UIbar 1]
if $scoreboardmultiplayer [
UIbutton "hold2" [uitext "Master" 0.65] 0.2 0.04 [hideui "main" ; showui "master"]
if (ismaster $getclientnum) [
UIbutton "hold2" [uitext "Bots" 0.65] 0.2 0.04 [hideui "main" ; showui "bots"]
] [
uifill 0 0.04
]
] [
uifill 0 0.04
UIbutton "hold2" [uitext "Bots" 0.65] 0.2 0.04 [hideui "main" ; showui "bots"]
]
uifill 0.2 0.02 [UIbar 1]
UIbutton "hold2" [uitext "Disconnect" 0.65] 0.2 0.04 [disconnect]
]
]
]
]
@ -234,7 +193,7 @@ UImenu "credits" [
///////////////////////////////////////////////////////////////////////////////
// Master //
///////////////////////////////////////////////////////////////////////////////
menu_master = [if $isconnected [if $scoreboardmultiplayer [toggleui "master"]]]
menu_master = []
UImenu "master" [
uifill 0 0 [

View file

@ -57,7 +57,7 @@ newui "varicons" [
uialign 1 1
uispace 0.01 0.1 [
uivlist 0 [
looplist i (concatword "allfaces entselsnap entediting fullbright showmat " (? $scoreboardmultiplayer "nompedit")) [
looplist i (concatword "allfaces entselsnap entediting fullbright showmat") [
uifont "default_outline" [
uialign 1
if $$i [

View file

@ -1,222 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// Scoreboard //
///////////////////////////////////////////////////////////////////////////////
newui "scoreboard" [
if $mainmenu [hideui "scoreboard"]
uiallowinput 0
refreshscoreboard
uicolor (? $sbtransparent $c_menu_a $c_menu) 0 0 [
uivlist 0 [
UI_sbheader
uifill 0 0.005
if (> $getmode 2) UI_playertableteam UI_playertablesolo
UI_spectatorlist
]
]
] [if $mainmenu [hideui "scoreboard"]]
///////////////////////////////////////////////////////////////////////////////
UI_sbwsolo = 0.68
UI_sbwteam = 1.18
UI_sbheader = [
uifill 0 0.005
uifill (? (> $getmode 2) $UI_sbwteam $UI_sbwsolo) 0.05 [
uifill (-f (? (> $getmode 2) $UI_sbwteam $UI_sbwsolo) (? (= $showip 1) 0.18 0)) 0 [
uialign -1
uiclip (-f (? (> $getmode 2) $UI_sbwteam $UI_sbwsolo) (? (= $showip 1) 0.18 0)) 0 [
uialign -1
uispace 0.01 0 [
uivlist 0 [
if $scoreboardservinfo [
uitext $scoreboardservinfo 0.65
] [
uitext "^f4Tesseract" 0.65
]
uihlist 0.015 [
uifill
uihlist 0.003 [
uitext "^fs[" 0.52
uitext (concatword (at ["^f0" "^f0" "^f2" "^f3"] $getmastermode) (getmastermodename $getmastermode)) 0.52
uitext "^fS]" 0.52
]
UItriangle 0x606060 0.01 0.01 270
uitext (getmodeprettyname $getmode) 0.52
UItriangle 0x606060 0.01 0.01 270
uitext $scoreboardmap 0.52
if (m_timed $getmode) [
UItriangle 0x606060 0.01 0.01 270
uitext (concatword (? (|| $intermission $paused) "^f3" "^f8") $scoreboardtime) 0.52
]
]
uialign* -1
]
]
]
]
if $scoreboardmultiplayer [
if $showip [
uifill 0.18 0 [
uialign 1
UIbar 0 1; uialign- -1
uiclip 0.18 0 [
uialign 1
uispace 0.01 0 [
uivlist 0.004 [
uicolortext $connectedip 0xA0A0A0 0.52
uicolortext $connectedport 0xA0A0A0 0.52
uialign* 1
]
]
uialign- 1
]
]
]
]
]
]
//-------------------------------------------------------------------------------------------------
UI_cw_s = 0.042
UI_cw_k = 0.054
UI_cw_d = 0.054
UI_cw_pj = 0.050
UI_cw_p = 0.050
UI_cw_cn = 0.040
UI_cw_n = [-f (? (> $getmode 2) (*f $UI_sbwteam 0.5) $UI_sbwsolo) (? (> $getmode 2) (? $showscore $UI_cw_s)) (? $showkills $UI_cw_k) (? $showdeaths $UI_cw_d) (? $scoreboardmultiplayer (? $showpj $UI_cw_pj)) (? $scoreboardmultiplayer (? $showping $UI_cw_p)) (? $scoreboardmultiplayer (? $showclientnum $UI_cw_cn)) 0.03]
// ^ blarg
UI_playertablesolo = [
uifill 0 0 [
uitable 0 0 [
uitableheader [
uifill 0.015
uifill (UI_cw_n) 0.022
if $showkills [uifill $UI_cw_k 0.022 [uicolortext "K" 0xBBCC8B 0.45 ; uialign- 1 1]]
if $showdeaths [uifill $UI_cw_d 0.022 [uicolortext "D" 0xE56767 0.45 ; uialign- 1 1]]
if $scoreboardmultiplayer [
if $showpj [uifill $UI_cw_pj 0.022 [uicolortext "PJ" 0x77A1D9 0.45 ; uialign- 1 1]]
if $showping [uifill $UI_cw_p 0.022 [uicolortext "P" 0x77A1D9 0.45 ; uialign- 1 1]]
if $showclientnum [uifill $UI_cw_cn 0.022 [uicolortext "#" 0xA0A0A0 0.45 ; uialign- 1 1]]
]
uifill 0.015
] [uicolor 0x88161616 0 0 [uiclamp 1 1 1 1]]
UI_sbtc = 0
loopscoreboard cn 0 [
UI_sbtc = (! $UI_sbtc)
uitablerow [
uifill 0.015
uifill (UI_cw_n) 0.026 [uicolortext (getclientcolorname $cn) (scoreboardstatus $cn) 0.57 ; uialign- -1]
if $showkills [uifill $UI_cw_k 0.026 [uicolortext (getclientfrags $cn) 0xBBCC8B 0.52 ; uialign- 1]]
if $showdeaths [uifill $UI_cw_d 0.026 [uicolortext (getclientdeaths $cn) 0xE56767 0.52 ; uialign- 1]]
if $scoreboardmultiplayer [
if $showpj [uifill $UI_cw_pj 0.026 [uicolortext (? (isai $cn) "^f4-" (scoreboardpj $cn)) 0x77A1D9 0.52 ; uialign- 1]]
if $showping [uifill $UI_cw_p 0.026 [uicolortext (? (isai $cn) "^f4-" (scoreboardping $cn)) 0x77A1D9 0.52 ; uialign- 1]]
if $showclientnum [uifill $UI_cw_cn 0.026 [uicolortext (? (isai $cn) "^f4-" $cn) 0xA0A0A0 0.52 ; uialign- 1]]
]
uifill 0.015
] [
uicolor (? $UI_sbtc 0x99323232 0x99262626) 0 0 [uiclamp 1 1 1 1]
pushif highlight (scoreboardhighlight $cn) [uioutline 0xA0A0A0 (-f $UI_sbwsolo 0.002) 0.024]
]
]
]
]
]
UI_playertableteam = [
uifill 0 0 [
uihlist 0 [
uitable 0 0 [
uialign 0 -1
uitableheader [
uifill 0.015
if $scoreboardmultiplayer [
if $showclientnum [uifill $UI_cw_cn 0.042 [uicolortext "#" 0xA0A0A0 0.45 ; uialign- -1 1]]
if $showping [uifill $UI_cw_p 0.042 [uicolortext "P" 0x77A1D9 0.45 ; uialign- -1 1]]
if $showpj [uifill $UI_cw_pj 0.042 [uicolortext "PJ" 0x77A1D9 0.45 ; uialign- -1 1]]
]
if $showdeaths [uifill $UI_cw_d 0.042 [uicolortext "D" 0xE56767 0.45 ; uialign- -1 1]]
if $showkills [uifill $UI_cw_k 0.042 [uicolortext "K" 0xBBCC8B 0.45 ; uialign- -1 1]]
if $showscore [uifill $UI_cw_s 0.042 [uicolortext "Score" 0x62B370 0.45 ; uialign- -1 1]]
uifill (UI_cw_n) 0.042 [uicolortext (getteamscore 1) 0x4060D0 1 ; uialign- 1]
uifill 0.015
] [uicolor 0x99202860 0 0 [uiclamp 1 1 1 1]]
UI_sbtc = 0
loopscoreboard cn 1 [
UI_sbtc = (! $UI_sbtc)
uitablerow [
uifill 0.015
if $scoreboardmultiplayer [
if $showclientnum [uifill $UI_cw_cn 0.026 [uicolortext (? (isai $cn) "^f4-" $cn) 0xA0A0A0 0.52 ; uialign- -1]]
if $showping [uifill $UI_cw_p 0.026 [uicolortext (? (isai $cn) "^f4-" (scoreboardping $cn)) 0x77A1D9 0.52 ; uialign- -1]]
if $showpj [uifill $UI_cw_pj 0.026 [uicolortext (? (isai $cn) "^f4-" (scoreboardpj $cn)) 0x77A1D9 0.52 ; uialign- -1]]
]
if $showdeaths [uifill $UI_cw_d 0.026 [uicolortext (getclientdeaths $cn) 0xE56767 0.52 ; uialign- -1]]
if $showkills [uifill $UI_cw_k 0.026 [uicolortext (getclientfrags $cn) 0xBBCC8B 0.52 ; uialign- -1]]
if $showscore [uifill $UI_cw_s 0.026 [uicolortext (getclientflags $cn) 0x62B370 0.52 ; uialign- -1]]
uifill (UI_cw_n) 0.026 [uicolortext (getclientcolorname $cn) (scoreboardstatus $cn) 0.57 ; uialign- 1]
uifill 0.015
] [
uicolor (? $UI_sbtc 0x99333b40 0x99262b33) 0 0 [uiclamp 1 1 1 1]
pushif highlight (scoreboardhighlight $cn) [uioutline 0xA0A0A0 (-f (*f $UI_sbwteam 0.5) 0.002) 0.024]
]
]
]
uitable 0 0 [
uialign 0 -1
uitableheader [
uifill 0.015
uifill (UI_cw_n) 0.042 [uicolortext (getteamscore 2) 0xD04040 1 ; uialign- -1]
if $showscore [uifill $UI_cw_s 0.042 [uicolortext "Score" 0x62B370 0.45 ; uialign- 1 1]]
if $showkills [uifill $UI_cw_k 0.042 [uicolortext "K" 0xBBCC8B 0.45 ; uialign- 1 1]]
if $showdeaths [uifill $UI_cw_d 0.042 [uicolortext "D" 0xE56767 0.45 ; uialign- 1 1]]
if $scoreboardmultiplayer [
if $showpj [uifill $UI_cw_pj 0.042 [uicolortext "PJ" 0x77A1D9 0.45 ; uialign- 1 1]]
if $showping [uifill $UI_cw_p 0.042 [uicolortext "P" 0x77A1D9 0.45 ; uialign- 1 1]]
if $showclientnum [uifill $UI_cw_cn 0.042 [uicolortext "#" 0xA0A0A0 0.45 ; uialign- 1 1]]
]
uifill 0.015
] [uicolor 0x99602020 0 0 [uiclamp 1 1 1 1]]
UI_sbtc = 0
loopscoreboard cn 2 [
UI_sbtc = (! $UI_sbtc)
uitablerow [
uifill 0.015
uifill (UI_cw_n) 0.026 [uicolortext (getclientcolorname $cn) (scoreboardstatus $cn) 0.57 ; uialign- -1]
if $showscore [uifill $UI_cw_s 0.026 [uicolortext (getclientflags $cn) 0x62B370 0.52 ; uialign- 1]]
if $showkills [uifill $UI_cw_k 0.026 [uicolortext (getclientfrags $cn) 0xBBCC8B 0.52 ; uialign- 1]]
if $showdeaths [uifill $UI_cw_d 0.026 [uicolortext (getclientdeaths $cn) 0xE56767 0.52 ; uialign- 1]]
if $scoreboardmultiplayer [
if $showpj [uifill $UI_cw_pj 0.026 [uicolortext (? (isai $cn) "^f4-" (scoreboardpj $cn)) 0x77A1D9 0.52 ; uialign- 1]]
if $showping [uifill $UI_cw_p 0.026 [uicolortext (? (isai $cn) "^f4-" (scoreboardping $cn)) 0x77A1D9 0.52 ; uialign- 1]]
if $showclientnum [uifill $UI_cw_cn 0.026 [uicolortext (? (isai $cn) "^f4-" $cn) 0xA0A0A0 0.52 ; uialign- 1]]
]
uifill 0.015
] [
uicolor (? $UI_sbtc 0x99403333 0x99332626) 0 0 [uiclamp 1 1 1 1]
pushif highlight (scoreboardhighlight $cn) [uioutline 0xA0A0A0 (-f (*f $UI_sbwteam 0.5) 0.002) 0.024]
]
]
]
]
]
]
//-------------------------------------------------------------------------------------------------
UI_spectatorlist = [
uicolor 0x88161616 0 0.022 [
uiclamp 1 1 1 1
if $showspectators [
uigrid (? (> $getmode 2) 3 2) 0 0 [
loopscoreboard cn -1 [
uispace 0.01 0.01 [
pushif sbhigh (scoreboardhighlight $cn) [
uioutline 0xA0A0A0 ; uiclamp- 1 1 1 1
]
uihlist 0.01 [
uicolortext (getclientcolorname $cn) (scoreboardstatus $cn) 0.57
if $scoreboardmultiplayer [if $showclientnum [uitext $cn 0.57]]
]
]
]
]
]
]
]

View file

@ -40,14 +40,11 @@ client_src = [
'../engine/water.cc',
'../engine/world.cc',
'../engine/worldio.cc',
'../game/ai.cc',
'../game/client.cc',
'../game/entities.cc',
'../game/game.cc',
'../game/render.cc',
'../game/scoreboard.cc',
'../game/server.cc',
'../game/waypoint.cc',
'../game/weapon.cc'
]

View file

@ -1890,7 +1890,7 @@ bool moveplayer(physent *pl, int moveres, bool local, int curtime)
else if(pl->inwater && !water) game::physicstrigger(pl, local, 0, 1, pl->inwater);
pl->inwater = water ? material&MATF_VOLUME : MAT_AIR;
if(pl->state==CS_ALIVE && (pl->o.z < 0 || material&MAT_DEATH)) game::suicide(pl);
//if(pl->state==CS_ALIVE && (pl->o.z < 0 || material&MAT_DEATH)) game::suicide(pl);
return true;
}

View file

@ -194,7 +194,6 @@ void sendpacket(int n, int chan, ENetPacket *packet, int exclude)
{
if(n<0)
{
server::recordpacket(chan, packet->data, packet->dataLength);
loopv(clients) if(i!=exclude && server::allowbroadcast(i)) sendpacket(i, chan, packet);
return;
}

File diff suppressed because it is too large Load diff

View file

@ -1,317 +0,0 @@
struct gameent;
#define MAXBOTS 32
enum { AI_NONE = 0, AI_BOT, AI_MAX };
#define isaitype(a) (a >= 0 && a <= AI_MAX-1)
namespace ai
{
const int MAXWAYPOINTS = USHRT_MAX - 2;
const int MAXWAYPOINTLINKS = 6;
const int WAYPOINTRADIUS = 16;
const float MINWPDIST = 4.f; // is on top of
const float CLOSEDIST = 32.f; // is close
const float FARDIST = 128.f; // too far to remap close
const float JUMPMIN = 4.f; // decides to jump
const float JUMPMAX = 32.f; // max jump
const float SIGHTMIN = 64.f; // minimum line of sight
const float SIGHTMAX = 1024.f; // maximum line of sight
const float VIEWMIN = 90.f; // minimum field of view
const float VIEWMAX = 180.f; // maximum field of view
struct waypoint
{
vec o;
float curscore, estscore;
int weight;
ushort route, prev;
ushort links[MAXWAYPOINTLINKS];
waypoint() {}
waypoint(const vec &o, int weight = 0) : o(o), weight(weight), route(0) { memset(links, 0, sizeof(links)); }
int score() const { return int(curscore) + int(estscore); }
int find(int wp)
{
loopi(MAXWAYPOINTLINKS) if(links[i] == wp) return i;
return -1;
}
bool haslinks() { return links[0]!=0; }
};
extern vector<waypoint> waypoints;
static inline bool iswaypoint(int n)
{
return n > 0 && n < waypoints.length();
}
extern int showwaypoints, dropwaypoints;
extern int closestwaypoint(const vec &pos, float mindist, bool links, gameent *d = NULL);
extern void findwaypointswithin(const vec &pos, float mindist, float maxdist, vector<int> &results);
extern void inferwaypoints(gameent *d, const vec &o, const vec &v, float mindist = ai::CLOSEDIST);
struct avoidset
{
struct obstacle
{
void *owner;
int numwaypoints;
float above;
obstacle(void *owner, float above = -1) : owner(owner), numwaypoints(0), above(above) {}
};
vector<obstacle> obstacles;
vector<int> waypoints;
void clear()
{
obstacles.setsize(0);
waypoints.setsize(0);
}
void add(void *owner, float above)
{
obstacles.add(obstacle(owner, above));
}
void add(void *owner, float above, int wp)
{
if(obstacles.empty() || owner != obstacles.last().owner) add(owner, above);
obstacles.last().numwaypoints++;
waypoints.add(wp);
}
void add(avoidset &avoid)
{
waypoints.put(avoid.waypoints.getbuf(), avoid.waypoints.length());
loopv(avoid.obstacles)
{
obstacle &o = avoid.obstacles[i];
if(obstacles.empty() || o.owner != obstacles.last().owner) add(o.owner, o.above);
obstacles.last().numwaypoints += o.numwaypoints;
}
}
void avoidnear(void *owner, float above, const vec &pos, float limit);
#define loopavoid(v, d, body) \
if(!(v).obstacles.empty()) \
{ \
int cur = 0; \
loopv((v).obstacles) \
{ \
const ai::avoidset::obstacle &ob = (v).obstacles[i]; \
int next = cur + ob.numwaypoints; \
if(ob.owner != d) \
{ \
for(; cur < next; cur++) \
{ \
int wp = (v).waypoints[cur]; \
body; \
} \
} \
cur = next; \
} \
}
bool find(int n, gameent *d) const
{
loopavoid(*this, d, { if(wp == n) return true; });
return false;
}
int remap(gameent *d, int n, vec &pos, bool retry = false);
};
extern bool route(gameent *d, int node, int goal, vector<int> &route, const avoidset &obstacles, int retries = 0);
extern void navigate();
extern void clearwaypoints(bool full = false);
extern void seedwaypoints();
extern void loadwaypoints(bool force = false, const char *mname = NULL);
extern void savewaypoints(bool force = false, const char *mname = NULL);
// ai state information for the owner client
enum
{
AI_S_WAIT = 0, // waiting for next command
AI_S_DEFEND, // defend goal target
AI_S_PURSUE, // pursue goal target
AI_S_INTEREST, // interest in goal entity
AI_S_MAX
};
enum
{
AI_T_NODE,
AI_T_PLAYER,
AI_T_AFFINITY,
AI_T_ENTITY,
AI_T_MAX
};
struct interest
{
int state, node, target, targtype;
float score;
interest() : state(-1), node(-1), target(-1), targtype(-1), score(0.f) {}
~interest() {}
};
struct aistate
{
int type, millis, targtype, target, idle;
bool override;
aistate(int m, int t, int r = -1, int v = -1) : type(t), millis(m), targtype(r), target(v)
{
reset();
}
~aistate() {}
void reset()
{
idle = 0;
override = false;
}
};
const int NUMPREVNODES = 6;
struct aiinfo
{
vector<aistate> state;
vector<int> route;
vec target, spot;
int enemy, enemyseen, enemymillis, weappref, prevnodes[NUMPREVNODES], targnode, targlast, targtime, targseq,
lastrun, lasthunt, lastaction, lastcheck, jumpseed, jumprand, blocktime, huntseq, blockseq, lastaimrnd;
float targyaw, targpitch, views[3], aimrnd[3];
bool dontmove, becareful, tryreset, trywipe;
aiinfo()
{
clearsetup();
reset();
loopk(3) views[k] = 0.f;
}
~aiinfo() {}
void clearsetup()
{
weappref = GUN_RAIL;
spot = target = vec(0, 0, 0);
lastaction = lasthunt = lastcheck = enemyseen = enemymillis = blocktime = huntseq = blockseq = targtime = targseq = lastaimrnd = 0;
lastrun = jumpseed = lastmillis;
jumprand = lastmillis+5000;
targnode = targlast = enemy = -1;
}
void clear(bool prev = false)
{
if(prev) memset(prevnodes, -1, sizeof(prevnodes));
route.setsize(0);
}
void wipe(bool prev = false)
{
clear(prev);
state.setsize(0);
addstate(AI_S_WAIT);
trywipe = false;
}
void clean(bool tryit = false)
{
if(!tryit) becareful = dontmove = false;
targyaw = rnd(360);
targpitch = 0.f;
tryreset = tryit;
}
void reset(bool tryit = false) { wipe(); clean(tryit); }
bool hasprevnode(int n) const
{
loopi(NUMPREVNODES) if(prevnodes[i] == n) return true;
return false;
}
void addprevnode(int n)
{
if(prevnodes[0] != n)
{
memmove(&prevnodes[1], prevnodes, sizeof(prevnodes) - sizeof(prevnodes[0]));
prevnodes[0] = n;
}
}
aistate &addstate(int t, int r = -1, int v = -1)
{
return state.add(aistate(lastmillis, t, r, v));
}
void removestate(int index = -1)
{
if(index < 0) state.pop();
else if(state.inrange(index)) state.remove(index);
if(!state.length()) addstate(AI_S_WAIT);
}
aistate &getstate(int idx = -1)
{
if(state.inrange(idx)) return state[idx];
return state.last();
}
aistate &switchstate(aistate &b, int t, int r = -1, int v = -1)
{
if((b.type == t && b.targtype == r) || (b.type == AI_S_INTEREST && b.targtype == AI_T_NODE))
{
b.millis = lastmillis;
b.target = v;
b.reset();
return b;
}
return addstate(t, r, v);
}
};
extern avoidset obstacles;
extern vec aitarget;
extern float viewdist(int x = 101);
extern float viewfieldx(int x = 101);
extern float viewfieldy(int x = 101);
extern bool targetable(gameent *d, gameent *e);
extern bool cansee(gameent *d, vec &x, vec &y, vec &targ = aitarget);
extern void init(gameent *d, int at, int on, int sk, int bn, int pm, int col, const char *name, int team);
extern void update();
extern void avoid();
extern void think(gameent *d, bool run);
extern bool badhealth(gameent *d);
extern bool checkothers(vector<int> &targets, gameent *d = NULL, int state = -1, int targtype = -1, int target = -1, bool teams = false, int *members = NULL);
extern bool makeroute(gameent *d, aistate &b, int node, bool changed = true, int retries = 0);
extern bool makeroute(gameent *d, aistate &b, const vec &pos, bool changed = true, int retries = 0);
extern bool randomnode(gameent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, float wander = SIGHTMAX);
extern bool randomnode(gameent *d, aistate &b, float guard = SIGHTMIN, float wander = SIGHTMAX);
extern bool violence(gameent *d, aistate &b, gameent *e, int pursue = 0);
extern bool patrol(gameent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, float wander = SIGHTMAX, int walk = 1, bool retry = false);
extern bool defend(gameent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, float wander = SIGHTMAX, int walk = 1);
extern void assist(gameent *d, aistate &b, vector<interest> &interests, bool all = false, bool force = false);
extern bool parseinterests(gameent *d, aistate &b, vector<interest> &interests, bool override = false, bool ignore = false);
extern void spawned(gameent *d);
extern void damaged(gameent *d, gameent *e);
extern void killed(gameent *d, gameent *e);
extern void itemspawned(int ent);
extern void render();
}

View file

@ -1,276 +0,0 @@
// server-side ai manager
namespace aiman
{
bool dorefresh = false, botbalance = true;
VARN(serverbotlimit, botlimit, 0, 8, MAXBOTS);
VAR(serverbotbalance, 0, 1, 1);
void calcteams(vector<teamscore> &teams)
{
loopv(clients)
{
clientinfo *ci = clients[i];
if(ci->state.state==CS_SPECTATOR || !validteam(ci->team)) continue;
teamscore *t = NULL;
loopvj(teams) if(teams[j].team == ci->team) { t = &teams[j]; break; }
if(t) t->score++;
else teams.add(teamscore(ci->team, 1));
}
teams.sort(teamscore::compare);
if(teams.length() < MAXTEAMS)
{
loopi(MAXTEAMS) if(teams.htfind(1+i) < 0) teams.add(teamscore(1+i, 0));
}
}
void balanceteams()
{
vector<teamscore> teams;
calcteams(teams);
vector<clientinfo *> reassign;
loopv(bots) if(bots[i]) reassign.add(bots[i]);
while(reassign.length() && teams.length() && teams[0].score > teams.last().score + 1)
{
teamscore &t = teams.last();
clientinfo *bot = NULL;
loopv(reassign) if(reassign[i] && reassign[i]->team != teams[0].team)
{
bot = reassign.removeunordered(i);
teams[0].score--;
t.score++;
for(int j = teams.length() - 2; j >= 0; j--)
{
if(teams[j].score >= teams[j+1].score) break;
swap(teams[j], teams[j+1]);
}
break;
}
if(bot)
{
if(smode && bot->state.state==CS_ALIVE) smode->changeteam(bot, bot->team, t.team);
bot->team = t.team;
sendf(-1, 1, "riiii", N_SETTEAM, bot->clientnum, bot->team, 0);
}
else teams.remove(0, 1);
}
}
int chooseteam()
{
vector<teamscore> teams;
calcteams(teams);
return teams.length() ? teams.last().team : 0;
}
static inline bool validaiclient(clientinfo *ci)
{
return ci->clientnum >= 0 && ci->state.aitype == AI_NONE && (ci->state.state!=CS_SPECTATOR || ci->local || (ci->privilege && !ci->warned));
}
clientinfo *findaiclient(clientinfo *exclude = NULL)
{
clientinfo *least = NULL;
loopv(clients)
{
clientinfo *ci = clients[i];
if(!validaiclient(ci) || ci==exclude) continue;
if(!least || ci->bots.length() < least->bots.length()) least = ci;
}
return least;
}
bool addai(int skill, int limit)
{
int numai = 0, cn = -1, maxai = limit >= 0 ? min(limit, MAXBOTS) : MAXBOTS;
loopv(bots)
{
clientinfo *ci = bots[i];
if(!ci || ci->ownernum < 0) { if(cn < 0) cn = i; continue; }
numai++;
}
if(numai >= maxai) return false;
if(bots.inrange(cn))
{
clientinfo *ci = bots[cn];
if(ci)
{ // reuse a slot that was going to removed
clientinfo *owner = findaiclient();
ci->ownernum = owner ? owner->clientnum : -1;
if(owner) owner->bots.add(ci);
ci->aireinit = 2;
dorefresh = true;
return true;
}
}
else { cn = bots.length(); bots.add(NULL); }
int team = m_teammode ? chooseteam() : 0;
if(!bots[cn]) bots[cn] = new clientinfo;
clientinfo *ci = bots[cn];
ci->clientnum = MAXCLIENTS + cn;
ci->state.aitype = AI_BOT;
clientinfo *owner = findaiclient();
ci->ownernum = owner ? owner->clientnum : -1;
if(owner) owner->bots.add(ci);
ci->state.skill = skill <= 0 ? rnd(50) + 51 : clamp(skill, 1, 101);
clients.add(ci);
ci->state.lasttimeplayed = lastmillis;
copystring(ci->name, "bot", MAXNAMELEN+1);
ci->state.state = CS_DEAD;
ci->team = team;
ci->playermodel = rnd(128);
ci->playercolor = rnd(0x8000);
ci->aireinit = 2;
ci->connected = true;
dorefresh = true;
return true;
}
void deleteai(clientinfo *ci)
{
int cn = ci->clientnum - MAXCLIENTS;
if(!bots.inrange(cn)) return;
if(ci->ownernum >= 0 && !ci->aireinit && smode) smode->leavegame(ci, true);
sendf(-1, 1, "ri2", N_CDIS, ci->clientnum);
clientinfo *owner = (clientinfo *)getclientinfo(ci->ownernum);
if(owner) owner->bots.removeobj(ci);
clients.removeobj(ci);
DELETEP(bots[cn]);
dorefresh = true;
}
bool deleteai()
{
loopvrev(bots) if(bots[i] && bots[i]->ownernum >= 0)
{
deleteai(bots[i]);
return true;
}
return false;
}
void reinitai(clientinfo *ci)
{
if(ci->ownernum < 0) deleteai(ci);
else if(ci->aireinit >= 1)
{
sendf(-1, 1, "ri8s", N_INITAI, ci->clientnum, ci->ownernum, ci->state.aitype, ci->state.skill, ci->playermodel, ci->playercolor, ci->team, ci->name);
if(ci->aireinit == 2)
{
ci->reassign();
if(ci->state.state==CS_ALIVE) sendspawn(ci);
else sendresume(ci);
}
ci->aireinit = 0;
}
}
void shiftai(clientinfo *ci, clientinfo *owner = NULL)
{
if(ci->ownernum >= 0 && !ci->aireinit && smode) smode->leavegame(ci, true);
clientinfo *prevowner = (clientinfo *)getclientinfo(ci->ownernum);
if(prevowner) prevowner->bots.removeobj(ci);
if(!owner) { ci->aireinit = 0; ci->ownernum = -1; }
else if(ci->ownernum != owner->clientnum) { ci->aireinit = 2; ci->ownernum = owner->clientnum; owner->bots.add(ci); }
dorefresh = true;
}
void removeai(clientinfo *ci)
{ // either schedules a removal, or someone else to assign to
loopvrev(ci->bots) shiftai(ci->bots[i], findaiclient(ci));
}
bool reassignai()
{
clientinfo *hi = NULL, *lo = NULL;
loopv(clients)
{
clientinfo *ci = clients[i];
if(!validaiclient(ci)) continue;
if(!lo || ci->bots.length() < lo->bots.length()) lo = ci;
if(!hi || ci->bots.length() > hi->bots.length()) hi = ci;
}
if(hi && lo && hi->bots.length() - lo->bots.length() > 1)
{
loopvrev(hi->bots)
{
shiftai(hi->bots[i], lo);
return true;
}
}
return false;
}
void checksetup()
{
if(m_teammode && botbalance) balanceteams();
loopvrev(bots) if(bots[i]) reinitai(bots[i]);
}
void clearai()
{ // clear and remove all ai immediately
loopvrev(bots) if(bots[i]) deleteai(bots[i]);
}
void checkai()
{
if(!dorefresh) return;
dorefresh = false;
if(m_botmode && numclients(-1, false, true))
{
checksetup();
while(reassignai());
}
else clearai();
}
void reqadd(clientinfo *ci, int skill)
{
if(!ci->local && !ci->privilege) return;
if(!addai(skill, !ci->local && ci->privilege < PRIV_ADMIN ? botlimit : -1)) sendf(ci->clientnum, 1, "ris", N_SERVMSG, "failed to create or assign bot");
}
void reqdel(clientinfo *ci)
{
if(!ci->local && !ci->privilege) return;
if(!deleteai()) sendf(ci->clientnum, 1, "ris", N_SERVMSG, "failed to remove any bots");
}
void setbotlimit(clientinfo *ci, int limit)
{
if(ci && !ci->local && ci->privilege < PRIV_ADMIN) return;
botlimit = clamp(limit, 0, MAXBOTS);
dorefresh = true;
defformatstring(msg, "bot limit is now %d", botlimit);
sendservmsg(msg);
}
void setbotbalance(clientinfo *ci, bool balance)
{
if(ci && !ci->local && !ci->privilege) return;
botbalance = balance ? 1 : 0;
dorefresh = true;
defformatstring(msg, "bot team balancing is now %s", botbalance ? "enabled" : "disabled");
sendservmsg(msg);
}
void changemap()
{
dorefresh = true;
loopv(clients) if(clients[i]->local || clients[i]->privilege) return;
if(botbalance != (serverbotbalance != 0)) setbotbalance(NULL, serverbotbalance != 0);
}
void addclient(clientinfo *ci)
{
if(ci->state.aitype == AI_NONE) dorefresh = true;
}
void changeteam(clientinfo *ci)
{
if(ci->state.aitype == AI_NONE) dorefresh = true;
}
}

File diff suppressed because it is too large Load diff

View file

@ -225,7 +225,6 @@ namespace entities
else d->vel = vec(0, 0, 0);
entinmap(d);
updatedynentcache(d);
ai::inferwaypoints(d, ents[n]->o, ents[e]->o, 16.f);
break;
}
}
@ -267,7 +266,6 @@ namespace entities
d->lastpickup = e->type;
d->lastpickupmillis = lastmillis;
jumppadeffects(d, n, true);
if(d->ai) d->ai->becareful = true;
d->falling = vec(0, 0, 0);
d->physstate = PHYS_FALL;
d->timeinair = 1;

View file

@ -1,145 +0,0 @@
#define EXT_ACK -1
#define EXT_VERSION 105
#define EXT_NO_ERROR 0
#define EXT_ERROR 1
#define EXT_PLAYERSTATS_RESP_IDS -10
#define EXT_PLAYERSTATS_RESP_STATS -11
#define EXT_UPTIME 0
#define EXT_PLAYERSTATS 1
#define EXT_TEAMSCORE 2
/*
Client:
-----
A: 0 EXT_UPTIME
B: 0 EXT_PLAYERSTATS cn #a client number or -1 for all players#
C: 0 EXT_TEAMSCORE
Server:
--------
A: 0 EXT_UPTIME EXT_ACK EXT_VERSION uptime #in seconds#
B: 0 EXT_PLAYERSTATS cn #send by client# EXT_ACK EXT_VERSION 0 or 1 #error, if cn was > -1 and client does not exist# ...
EXT_PLAYERSTATS_RESP_IDS pid(s) #1 packet#
EXT_PLAYERSTATS_RESP_STATS pid playerdata #1 packet for each player#
C: 0 EXT_TEAMSCORE EXT_ACK EXT_VERSION 0 or 1 #error, no teammode# remaining_time gamemode loop(teamdata [numbases bases] or -1)
Errors:
--------------
B:C:default: 0 command EXT_ACK EXT_VERSION EXT_ERROR
*/
VAR(extinfoip, 0, 0, 1);
void extinfoplayer(ucharbuf &p, clientinfo *ci)
{
ucharbuf q = p;
putint(q, EXT_PLAYERSTATS_RESP_STATS); // send player stats following
putint(q, ci->clientnum); //add player id
putint(q, ci->ping);
sendstring(ci->name, q);
sendstring(teamname(m_teammode ? ci->team : 0), q);
putint(q, ci->state.frags);
putint(q, ci->state.flags);
putint(q, ci->state.deaths);
putint(q, ci->state.teamkills);
putint(q, ci->state.damage*100/max(ci->state.shotdamage,1));
putint(q, ci->state.health);
putint(q, 0);
putint(q, ci->state.gunselect);
putint(q, ci->privilege);
putint(q, ci->state.state);
uint ip = extinfoip ? getclientip(ci->clientnum) : 0;
q.put((uchar*)&ip, 3);
sendserverinforeply(q);
}
static inline void extinfoteamscore(ucharbuf &p, int team, int score)
{
sendstring(teamname(team), p);
putint(p, score);
if(!smode || !smode->extinfoteam(team, p))
putint(p,-1); //no bases follow
}
void extinfoteams(ucharbuf &p)
{
putint(p, m_teammode ? 0 : 1);
putint(p, gamemode);
putint(p, max((gamelimit - gamemillis)/1000, 0));
if(!m_teammode) return;
vector<teamscore> scores;
if(smode && smode->hidefrags()) smode->getteamscores(scores);
loopv(clients)
{
clientinfo *ci = clients[i];
if(ci->state.state!=CS_SPECTATOR && validteam(ci->team) && scores.htfind(ci->team) < 0)
{
if(smode && smode->hidefrags()) scores.add(teamscore(ci->team, 0));
else { teaminfo &t = teaminfos[ci->team-1]; scores.add(teamscore(ci->team, t.frags)); }
}
}
loopv(scores) extinfoteamscore(p, scores[i].team, scores[i].score);
}
void extserverinforeply(ucharbuf &req, ucharbuf &p)
{
int extcmd = getint(req); // extended commands
//Build a new packet
putint(p, EXT_ACK); //send ack
putint(p, EXT_VERSION); //send version of extended info
switch(extcmd)
{
case EXT_UPTIME:
{
putint(p, totalsecs); //in seconds
break;
}
case EXT_PLAYERSTATS:
{
int cn = getint(req); //a special player, -1 for all
clientinfo *ci = NULL;
if(cn >= 0)
{
loopv(clients) if(clients[i]->clientnum == cn) { ci = clients[i]; break; }
if(!ci)
{
putint(p, EXT_ERROR); //client requested by id was not found
sendserverinforeply(p);
return;
}
}
putint(p, EXT_NO_ERROR); //so far no error can happen anymore
ucharbuf q = p; //remember buffer position
putint(q, EXT_PLAYERSTATS_RESP_IDS); //send player ids following
if(ci) putint(q, ci->clientnum);
else loopv(clients) putint(q, clients[i]->clientnum);
sendserverinforeply(q);
if(ci) extinfoplayer(p, ci);
else loopv(clients) extinfoplayer(p, clients[i]);
return;
}
case EXT_TEAMSCORE:
{
extinfoteams(p);
break;
}
default:
{
putint(p, EXT_ERROR);
break;
}
}
sendserverinforeply(p);
}

View file

@ -39,15 +39,6 @@ namespace game
void follow(char *arg)
{
int cn = -1;
if(arg[0])
{
if(player1->state != CS_SPECTATOR) return;
cn = parseplayer(arg);
if(cn == player1->clientnum) cn = -1;
}
if(cn < 0 && (following < 0 || specmode)) return;
following = cn;
}
COMMAND(follow, "s");
@ -96,25 +87,16 @@ namespace game
gameent *spawnstate(gameent *d) // reset player state not persistent accross spawns
{
d->respawn();
d->spawnstate(gamemode);
d->spawnstate(0);
return d;
}
void respawnself()
{
if(ispaused()) return;
if(m_mp(gamemode))
{
int seq = (player1->lifesequence<<16)|((lastmillis/1000)&0xFFFF);
if(player1->respawned!=seq) { addmsg(N_TRYSPAWN, "rc", player1); player1->respawned = seq; }
}
else
{
spawnplayer(player1);
showscores(false);
lasthit = 0;
if(cmode) cmode->respawned(player1);
}
spawnplayer(player1);
lasthit = 0;
if(cmode) cmode->respawned(player1);
}
gameent *pointatplayer()
@ -194,7 +176,7 @@ namespace game
loopv(players)
{
gameent *d = players[i];
if(d == player1 || d->ai) continue;
if(d == player1) continue;
if(d->state==CS_DEAD && d->ragdoll) moveragdoll(d);
else if(!intermission)
@ -225,10 +207,8 @@ namespace game
if(!curtime) { gets2c(); if(player1->clientnum>=0) c2sinfo(); return; }
physicsframe();
ai::navigate();
updateweapons(curtime);
otherplayers(curtime);
ai::update();
moveragdolls();
gets2c();
if(connected)
@ -354,15 +334,11 @@ namespace game
}
damageeffect(damage, d, d!=h);
ai::damaged(d, actor);
if(d->health<=0) { if(local) killed(d, actor); }
else if(d==h) playsound(S_PAIN2);
else playsound(S_PAIN1, &d->o);
}
VARP(deathscore, 0, 1, 1);
void deathstate(gameent *d, bool restore)
{
d->state = CS_DEAD;
@ -374,7 +350,6 @@ namespace game
}
if(d==player1)
{
if(deathscore) showscores(true);
disablezoom();
d->attacking = ACT_IDLE;
//d->pitch = 0;
@ -431,7 +406,6 @@ namespace game
else conoutf(contype, "\f2%s fragged %s", aname, dname);
}
deathstate(d);
ai::killed(d, actor);
}
void timeupdate(int secs)
@ -451,7 +425,6 @@ namespace game
int accuracy = (player1->totaldamage*100)/max(player1->totalshots, 1);
conoutf(CON_GAMEINFO, "\f2player total damage dealt: %d, damage wasted: %d, accuracy(%%): %d", player1->totaldamage, player1->totalshots-player1->totaldamage, accuracy);
showscores(true);
disablezoom();
execident("intermission");
@ -469,7 +442,7 @@ namespace game
gameent *newclient(int cn) // ensure valid entity
{
if(cn < 0 || cn > max(0xFF, MAXCLIENTS + MAXBOTS))
if(cn < 0 || cn > max(0xFF, MAXCLIENTS))
{
neterr("clientnum", false);
return NULL;
@ -497,7 +470,6 @@ namespace game
void clientdisconnected(int cn, bool notify)
{
if(!clients.inrange(cn)) return;
unignore(cn);
gameent *d = clients[cn];
if(d)
{
@ -506,7 +478,6 @@ namespace game
removetrackedparticles(d);
removetrackeddynlights(d);
if(cmode) cmode->removeplayer(d);
removegroupedplayer(d);
players.removeobj(d);
DELETEP(clients[cn]);
cleardynentcache();
@ -538,8 +509,6 @@ namespace game
clearbouncers();
clearragdolls();
clearteaminfo();
// reset perma-state
loopv(players) players[i]->startgame();
@ -555,14 +524,8 @@ namespace game
cmode->setup();
}
conoutf(CON_GAMEINFO, "\f2game mode is %s", server::modeprettyname(gamemode));
const char *info = m_valid(gamemode) ? gamemodes[gamemode - STARTGAMEMODE].info : NULL;
if(showmodeinfo && info) conoutf(CON_GAMEINFO, "\f0%s", info);
syncplayer();
showscores(false);
disablezoom();
lasthit = 0;
@ -571,11 +534,7 @@ namespace game
void startmap(const char *name) // called just after a map load
{
ai::savewaypoints();
ai::clearwaypoints(true);
if(!m_mp(gamemode)) spawnplayer(player1);
else findplayerspawn(player1, -1, m_teammode ? player1->team : 0);
spawnplayer(player1);
entities::resetspawns();
copystring(clientmap, name ? name : "");
@ -584,20 +543,20 @@ namespace game
const char *getmapinfo()
{
return showmodeinfo && m_valid(gamemode) ? gamemodes[gamemode - STARTGAMEMODE].info : NULL;
return NULL;
}
const char *getscreenshotinfo()
{
return server::modename(gamemode, NULL);
return NULL;
}
void physicstrigger(physent *d, bool local, int floorlevel, int waterlevel, int material)
{
if (waterlevel>0) { if(material!=MAT_LAVA) playsound(S_SPLASHOUT, d==player1 ? NULL : &d->o); }
else if(waterlevel<0) playsound(material==MAT_LAVA ? S_BURN : S_SPLASHIN, d==player1 ? NULL : &d->o);
if (floorlevel>0) { if(d==player1 || d->type!=ENT_PLAYER || ((gameent *)d)->ai) msgsound(S_JUMP, d); }
else if(floorlevel<0) { if(d==player1 || d->type!=ENT_PLAYER || ((gameent *)d)->ai) msgsound(S_LAND, d); }
if (floorlevel>0) { if(d==player1 || d->type!=ENT_PLAYER) msgsound(S_JUMP, d); }
else if(floorlevel<0) { if(d==player1 || d->type!=ENT_PLAYER) msgsound(S_LAND, d); }
}
void dynentcollide(physent *d, physent *o, const vec &dir)
@ -613,8 +572,6 @@ namespace game
}
else
{
if(d->type==ENT_PLAYER && ((gameent *)d)->ai)
addmsg(N_SOUND, "ci", d, n);
playsound(n, &d->o);
}
}
@ -638,10 +595,10 @@ namespace game
const char *colorname(gameent *d, const char *name, const char * alt, const char *color)
{
if(!name) name = alt && d == player1 ? alt : d->name;
bool dup = !name[0] || duplicatename(d, name, alt) || d->aitype != AI_NONE;
bool dup = !name[0] || duplicatename(d, name, alt);
if(dup || color[0])
{
if(dup) return tempformatstring(d->aitype == AI_NONE ? "\fs%s%s \f5(%d)\fr" : "\fs%s%s \f5[%d]\fr", color, name, d->clientnum);
if(dup) return tempformatstring("\fs%s%s \f5(%d)\fr", color, name, d->clientnum);
return tempformatstring("\fs%s%s\fr", color, name);
}
return name;
@ -673,22 +630,6 @@ namespace game
teamsound(isteam(d->team, player1->team), n, loc);
}
void suicide(physent *d)
{
if(d==player1 || (d->type==ENT_PLAYER && ((gameent *)d)->ai))
{
if(d->state!=CS_ALIVE) return;
gameent *pl = (gameent *)d;
if(!m_mp(gamemode)) killed(pl, pl);
else
{
int seq = (pl->lifesequence<<16)|((lastmillis/1000)&0xFFFF);
if(pl->suicided!=seq) { addmsg(N_SUICIDE, "rc", pl); pl->suicided = seq; }
}
}
}
ICOMMAND(suicide, "", (), suicide(player1));
bool needminimap() { return false; }
void drawicon(int icon, float x, float y, float sz)