rip out most of gamecode
This commit is contained in:
parent
69ad67a65e
commit
b03c776b81
21 changed files with 91 additions and 6291 deletions
|
@ -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 = [
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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]]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
|
@ -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'
|
||||
]
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
1441
src/game/ai.cc
1441
src/game/ai.cc
File diff suppressed because it is too large
Load diff
317
src/game/ai.hh
317
src/game/ai.hh
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
199
src/game/game.cc
199
src/game/game.cc
|
@ -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)
|
||||
|