summaryrefslogtreecommitdiff
path: root/src/fpsgame
diff options
context:
space:
mode:
authorxolatile2025-08-17 18:28:28 +0200
committerxolatile2025-08-17 18:28:28 +0200
commitbffe8d11bd1dfec49280fb64a17f0ae529ac3f5d (patch)
tree9f4f7b6f5003585e5a170bd55ccaa335b8f26f90 /src/fpsgame
parentbec4167d29a68efd0cd2da36143e7f1c78a119a0 (diff)
downloadxolatile-badassbug-master.tar.xz
xolatile-badassbug-master.tar.zst
Compiles, removed a lot of code, do not run it...HEADmaster
Diffstat (limited to 'src/fpsgame')
-rw-r--r--src/fpsgame/ai.cpp9
-rw-r--r--src/fpsgame/ai.h1
-rw-r--r--src/fpsgame/aiman.h212
-rw-r--r--src/fpsgame/client.cpp7
-rw-r--r--src/fpsgame/entities.cpp2
-rw-r--r--src/fpsgame/extinfo.h112
-rw-r--r--src/fpsgame/fps.cpp12
-rw-r--r--src/fpsgame/game.h8
-rw-r--r--src/fpsgame/render.cpp56
-rw-r--r--src/fpsgame/scoreboard.cpp28
-rw-r--r--src/fpsgame/server.cpp338
-rw-r--r--src/fpsgame/weapon.cpp14
12 files changed, 314 insertions, 485 deletions
diff --git a/src/fpsgame/ai.cpp b/src/fpsgame/ai.cpp
index b59dbd3..5c74fe4 100644
--- a/src/fpsgame/ai.cpp
+++ b/src/fpsgame/ai.cpp
@@ -10,7 +10,6 @@ namespace ai {
ICOMMAND(addbot, "s", (char *s), addmsg(N_ADDBOT, "ri", *s ? clamp(parseint(s), 1, 101) : -1));
ICOMMAND(delbot, "", (), addmsg(N_DELBOT, "r"));
ICOMMAND(botlimit, "i", (int *n), addmsg(N_BOTLIMIT, "ri", *n));
- ICOMMAND(botbalance, "i", (int *n), addmsg(N_BOTBALANCE, "ri", *n));
float viewdist(int x) {
return x <= 100 ? clamp((SIGHTMIN+(SIGHTMAX-SIGHTMIN))/100.f*float(x), float(SIGHTMIN), 10000.0f) : 10000.0f;
}
@@ -904,16 +903,13 @@ namespace ai {
shoot(d, d->ai->target);
}
if(!intermission) {
- if(d->ragdoll) cleanragdoll(d);
moveplayer(d, 10, true);
if(allowmove && !b.idle) timeouts(d);
if(d->quadmillis) entities::checkquad(curtime, d);
entities::checkitems(d);
}
- }
- else if(d->state == CS_DEAD) {
- if(d->ragdoll) moveragdoll(d);
- else if(lastmillis-d->lastpain<2000) {
+ } else if(d->state == CS_DEAD) {
+ if(lastmillis-d->lastpain<2000) {
d->move = d->strafe = 0;
moveplayer(d, 10, false);
}
@@ -1074,4 +1070,3 @@ namespace ai {
}
}
}
-
diff --git a/src/fpsgame/ai.h b/src/fpsgame/ai.h
index 81b1e26..4328963 100644
--- a/src/fpsgame/ai.h
+++ b/src/fpsgame/ai.h
@@ -234,4 +234,3 @@ namespace ai {
extern void itemspawned(int ent);
extern void render();
}
-
diff --git a/src/fpsgame/aiman.h b/src/fpsgame/aiman.h
deleted file mode 100644
index f926d44..0000000
--- a/src/fpsgame/aiman.h
+++ /dev/null
@@ -1,212 +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) {
- static const char * const defaults[2] = { "good", "evil" };
- loopv(clients) {
- clientinfo *ci = clients[i];
- if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue;
- teamscore *t = NULL;
- loopvj(teams) if(!strcmp(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() < int(sizeof(defaults)/sizeof(defaults[0]))) {
- loopi(sizeof(defaults)/sizeof(defaults[0])) if(teams.htfind(defaults[i]) < 0) teams.add(teamscore(defaults[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] && !strcmp(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) {
- copystring(bot->team, t.team, MAXTEAMLEN+1);
- sendf(-1, 1, "riisi", N_SETTEAM, bot->clientnum, bot->team, 0);
- }
- else teams.remove(0, 1);
- }
- }
- const char *chooseteam() {
- vector<teamscore> teams;
- calcteams(teams);
- return teams.length() ? teams.last().team : "";
- }
- 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); }
- const char *team = m_teammode ? chooseteam() : "";
- 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;
- copystring(ci->team, team, MAXTEAMLEN+1);
- ci->playermodel = 0;
- ci->aireinit = 2;
- ci->connected = true;
- dorefresh = true;
- return true;
- }
- void deleteai(clientinfo *ci) {
- int cn = ci->clientnum - MAXCLIENTS;
- if(!bots.inrange(cn)) return;
- 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, "ri6ss", N_INITAI, ci->clientnum, ci->ownernum, ci->state.aitype, ci->state.skill, ci->playermodel, ci->name, ci->team);
- 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) {
- 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;
- }
-}
diff --git a/src/fpsgame/client.cpp b/src/fpsgame/client.cpp
index 83aa385..620c262 100644
--- a/src/fpsgame/client.cpp
+++ b/src/fpsgame/client.cpp
@@ -281,7 +281,6 @@ namespace game {
if(i>=0) addmsg(N_SPECTATOR, "rii", i, val);
}
ICOMMAND(spectator, "is", (int *val, char *who), togglespectator(*val, who));
- ICOMMAND(checkmaps, "", (), addmsg(N_CHECKMAPS, "r"));
int gamemode = INT_MAX, nextmode = INT_MAX;
string clientmap = "";
void changemapserv(const char *name, int mode) { // forced map change from the server {
@@ -1014,10 +1013,7 @@ namespace game {
clientdisconnected(getint(p));
break;
case N_SPAWN: {
- if(d) {
- if(d->state==CS_DEAD && d->lastpain) saveragdoll(d);
- d->respawn();
- }
+ if(d) d->respawn();
parsestate(d, p);
if(!d) break;
d->state = CS_SPAWNING;
@@ -1029,7 +1025,6 @@ namespace game {
int scn = getint(p);
fpsent *s = getclient(scn);
if(!s) { parsestate(NULL, p); break; }
- if(s->state==CS_DEAD && s->lastpain) saveragdoll(s);
if(s==player1) {
if(editmode) toggleedit();
stopfollowing();
diff --git a/src/fpsgame/entities.cpp b/src/fpsgame/entities.cpp
index 656a9b0..f8c037c 100644
--- a/src/fpsgame/entities.cpp
+++ b/src/fpsgame/entities.cpp
@@ -93,7 +93,7 @@ namespace entities {
if(mdlname) {
vec p = e.o;
p.z += 1+sinf(lastmillis/100.0+e.o.x+e.o.y)/20;
- rendermodel(&e.light, mdlname, ANIM_MAPMODEL|ANIM_LOOP, p, lastmillis/(float)revs, 0, MDL_SHADOW | MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED);
+ rendermodel(&e.light, mdlname, ANIM_MAPMODEL|ANIM_LOOP, p, lastmillis/(float)revs, 0, MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED);
}
}
}
diff --git a/src/fpsgame/extinfo.h b/src/fpsgame/extinfo.h
deleted file mode 100644
index b467a8c..0000000
--- a/src/fpsgame/extinfo.h
+++ /dev/null
@@ -1,112 +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(ci->team, 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, ci->state.armour);
- 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, const char *team, int score) {
- sendstring(team, p);
- putint(p, score);
- 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;
- loopv(clients) {
- clientinfo *ci = clients[i];
- if(ci->state.state!=CS_SPECTATOR && ci->team[0] && scores.htfind(ci->team) < 0) {
- teaminfo *ti = teaminfos.access(ci->team);
- scores.add(teamscore(ci->team, ti ? ti->frags : 0));
- }
- }
- 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);
- }
diff --git a/src/fpsgame/fps.cpp b/src/fpsgame/fps.cpp
index d5501c4..0f0e3b1 100644
--- a/src/fpsgame/fps.cpp
+++ b/src/fpsgame/fps.cpp
@@ -139,8 +139,7 @@ namespace game {
loopv(players) {
fpsent *d = players[i];
if(d == player1 || d->ai) continue;
- if(d->state==CS_DEAD && d->ragdoll) moveragdoll(d);
- else if(!intermission) {
+ if(!intermission) {
if(lastmillis - d->lastaction >= d->gunwait) d->gunwait = 0;
if(d->quadmillis) entities::checkquad(curtime, d);
}
@@ -154,7 +153,7 @@ namespace game {
if(smoothmove && d->smoothmillis>0) predictplayer(d, true);
else moveplayer(d, 1, false);
}
- else if(d->state==CS_DEAD && !d->ragdoll && lastmillis-d->lastpain<2000) moveplayer(d, 1, true);
+ else if(d->state==CS_DEAD && lastmillis-d->lastpain<2000) moveplayer(d, 1, true);
}
}
void checkslowmo() {
@@ -176,18 +175,15 @@ namespace game {
updateweapons(curtime);
otherplayers(curtime);
ai::update();
- moveragdolls();
gets2c();
if(connected) {
if(player1->state == CS_DEAD) {
- if(player1->ragdoll) moveragdoll(player1);
- else if(lastmillis-player1->lastpain<2000) {
+ if(lastmillis-player1->lastpain<2000) {
player1->move = player1->strafe = 0;
moveplayer(player1, 10, true);
}
}
else if(!intermission) {
- if(player1->ragdoll) cleanragdoll(player1);
moveplayer(player1, 10, true);
swayhudgun(curtime);
entities::checkitems(player1);
@@ -201,7 +197,6 @@ namespace game {
float a = x - lower, b = x - upper;
return (b * b) / (a * a + b * b);
}
- static inline float harmonicmean(float a, float b) { return a + b > 0 ? 2 * a * b / (a + b) : 0.0f; }
// avoid spawning near other players
float ratespawn(dynent *d, const extentity &e) {
fpsent *p = (fpsent *)d;
@@ -427,7 +422,6 @@ namespace game {
void startgame() {
clearprojectiles();
clearbouncers();
- clearragdolls();
clearteaminfo();
// reset perma-state
loopv(players) {
diff --git a/src/fpsgame/game.h b/src/fpsgame/game.h
index 92d4fd1..ed62052 100644
--- a/src/fpsgame/game.h
+++ b/src/fpsgame/game.h
@@ -139,7 +139,7 @@ enum {
N_AUTHTRY, N_AUTHKICK, N_AUTHCHAL, N_AUTHANS, N_REQAUTH,
N_PAUSEGAME, N_GAMESPEED,
N_ADDBOT, N_DELBOT, N_INITAI, N_FROMAI, N_BOTLIMIT, N_BOTBALANCE,
- N_MAPCRC, N_CHECKMAPS,
+ N_MAPCRC,
N_SWITCHNAME, N_SWITCHMODEL, N_SWITCHTEAM,
N_INITTOKENS, N_TAKETOKEN, N_EXPIRETOKENS, N_DROPTOKENS, N_DEPOSITTOKENS, N_STEALTOKENS,
N_SERVCMD,
@@ -166,7 +166,7 @@ static const int msgsizes[] = { // size inclusive message token, 0 for vari
N_AUTHTRY, 0, N_AUTHKICK, 0, N_AUTHCHAL, 0, N_AUTHANS, 0, N_REQAUTH, 0,
N_PAUSEGAME, 0, N_GAMESPEED, 0,
N_ADDBOT, 2, N_DELBOT, 1, N_INITAI, 0, N_FROMAI, 2, N_BOTLIMIT, 2, N_BOTBALANCE, 2,
- N_MAPCRC, 0, N_CHECKMAPS, 1,
+ N_MAPCRC, 0,
N_SWITCHNAME, 0, N_SWITCHMODEL, 2, N_SWITCHTEAM, 0,
N_INITTOKENS, 0, N_TAKETOKEN, 2, N_EXPIRETOKENS, 0, N_DROPTOKENS, 0, N_DEPOSITTOKENS, 2, N_STEALTOKENS, 0,
N_SERVCMD, 0,
@@ -587,12 +587,8 @@ namespace game {
const char *ffa, *blueteam, *redteam, *hudguns,
*vwep, *quad, *armour[3],
*ffaicon, *blueicon, *redicon;
- bool ragdoll;
};
extern int playermodel, teamskins, testteam;
- extern void saveragdoll(fpsent *d);
- extern void clearragdolls();
- extern void moveragdolls();
extern const playermodelinfo &getplayermodelinfo(fpsent *d);
extern void swayhudgun(int curtime);
extern vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d);
diff --git a/src/fpsgame/render.cpp b/src/fpsgame/render.cpp
index fff917e..dd8a5ee 100644
--- a/src/fpsgame/render.cpp
+++ b/src/fpsgame/render.cpp
@@ -6,42 +6,16 @@ extern float gatherspawninfos(dynent *d, int tag, vector<spawninfo> &spawninfos)
namespace game {
vector<fpsent *> bestplayers;
vector<const char *> bestteams;
- VARP(ragdoll, 0, 1, 1);
- VARP(ragdollmillis, 0, 10000, 300000);
- VARP(ragdollfade, 0, 1000, 300000);
VARP(playermodel, 0, 0, 0);
VARP(hidedead, 0, 0, 2);
- vector<fpsent *> ragdolls;
- void saveragdoll(fpsent *d) {
- if(!d->ragdoll || !ragdollmillis || (!ragdollfade && lastmillis > d->lastpain + ragdollmillis)) return;
- fpsent *r = new fpsent(*d);
- r->lastupdate = ragdollfade && lastmillis > d->lastpain + max(ragdollmillis - ragdollfade, 0) ? lastmillis - max(ragdollmillis - ragdollfade, 0) : d->lastpain;
- r->edit = NULL;
- r->ai = NULL;
- r->attackchan = r->idlechan = -1;
- if(d==player1) r->playermodel = playermodel;
- ragdolls.add(r);
- d->ragdoll = NULL;
- }
- void clearragdolls() {
- ragdolls.deletecontents();
- }
- void moveragdolls() {
- loopv(ragdolls) {
- fpsent *d = ragdolls[i];
- if(lastmillis > d->lastupdate + ragdollmillis) {
- delete ragdolls.remove(i--);
- continue;
- }
- moveragdoll(d);
- }
- }
- static const playermodelinfo playermodels[1] = {
- {
- "mrfixit", "mrfixit/blue", "mrfixit/red", "mrfixit/hudguns", NULL, "mrfixit/horns", {
- "mrfixit/armor/blue", "mrfixit/armor/green", "mrfixit/armor/yellow" },
- "mrfixit", "mrfixit_blue", "mrfixit_red", true },
- };
+ static const playermodelinfo playermodels[1] = { {
+ //~const char *ffa, *blueteam, *redteam, *hudguns,
+ //~*vwep, *quad, *armour[3],
+ //~*ffaicon, *blueicon, *redicon;
+ "mrfixit", "mrfixit/blue", "mrfixit/red", "mrfixit/hudguns", NULL, "mrfixit/horns",
+ { "mrfixit/armor/blue", "mrfixit/armor/green", "mrfixit/armor/yellow" },
+ "mrfixit", "mrfixit_blue", "mrfixit_red"
+ } };
const playermodelinfo *getplayermodelinfo(int n) {
(void) n;
return &playermodels[0];
@@ -108,7 +82,7 @@ namespace game {
case 1: mdlname = mdl.blueteam; break;
case 2: mdlname = mdl.redteam; break;
}
- renderclient(d, mdlname, a[0].tag ? a : NULL, hold, attack, delay, lastaction, intermission && d->state!=CS_DEAD ? 0 : d->lastpain, fade, ragdoll && mdl.ragdoll);
+ renderclient(d, mdlname, a[0].tag ? a : NULL, hold, attack, delay, lastaction, intermission && d->state!=CS_DEAD ? 0 : d->lastpain, fade);
}
VARP(teamskins, 0, 0, 1);
VARP(statusicons, 0, 1, 1);
@@ -194,15 +168,6 @@ namespace game {
renderstatusicons(d, team, offset);
}
}
- loopv(ragdolls) {
- fpsent *d = ragdolls[i];
- int team = 0;
- if(teamskins || m_teammode) team = isteam(player1->team, d->team) ? 1 : 2;
- float fade = 1.0f;
- if(ragdollmillis && ragdollfade)
- fade -= clamp(float(lastmillis - (d->lastupdate + max(ragdollmillis - ragdollfade, 0)))/min(ragdollmillis, ragdollfade), 0.0f, 1.0f);
- renderplayer(d, getplayermodelinfo(d), team, fade, mainpass);
- }
if(isthirdperson() && !followingplayer() && (player1->state!=CS_DEAD || hidedead != 1)) renderplayer(player1, getplayermodelinfo(player1), teamskins || m_teammode ? 1 : 0, 1, mainpass);
entities::renderentities();
renderbouncers();
@@ -212,7 +177,6 @@ namespace game {
VARP(hudgun, 0, 1, 1);
VARP(hudgunsway, 0, 1, 1);
VARP(teamhudguns, 0, 1, 1);
- VARP(chainsawhudgun, 0, 1, 1);
VAR(testhudgun, 0, 0, 1);
FVAR(swaystep, 1, 35.0f, 100);
FVAR(swayside, 0, 0.04f, 1);
@@ -263,7 +227,7 @@ namespace game {
d->muzzle = vec(-1, -1, -1);
a[0] = modelattach("tag_muzzle", &d->muzzle);
dynent *interp = NULL;
- if(d->gunselect==GUN_FIST && chainsawhudgun) {
+ if(d->gunselect==GUN_FIST) {
anim |= ANIM_LOOP;
base = 0;
interp = &guninterp;
diff --git a/src/fpsgame/scoreboard.cpp b/src/fpsgame/scoreboard.cpp
index b1c7477..851b57d 100644
--- a/src/fpsgame/scoreboard.cpp
+++ b/src/fpsgame/scoreboard.cpp
@@ -334,23 +334,23 @@ namespace game {
/// PW
g.separator();
g.pushlist();
- g.textf(" %d%% ", 0x787878, "chainsaw.png", pwaccuracy[0]);
- g.textf(" %d%% ", 0xfba6a6, "shotgun.png", pwaccuracy[1]);
- g.textf(" %d%% ", 0x7bc77a, "chaingun.png", pwaccuracy[2]);
- g.textf(" %d%% ", 0xefd7a6, "rocket_launcher.png", pwaccuracy[3]);
- g.textf(" %d%% ", 0x8f91e7, "rifle.png", pwaccuracy[4]);
- g.textf(" %d%% ", 0x9ee5e5, "grenade_launcher.png", pwaccuracy[5]);
- g.textf(" %d%% ", 0xc3c3c3, "pistol.png", pwaccuracy[6]);
+ g.textf("%d%% ", 0x787878, "chainsaw.png", pwaccuracy[0]);
+ g.textf("%d%% ", 0xfba6a6, "shotgun.png", pwaccuracy[1]);
+ g.textf("%d%% ", 0x7bc77a, "chaingun.png", pwaccuracy[2]);
+ g.textf("%d%% ", 0xefd7a6, "rocket_launcher.png", pwaccuracy[3]);
+ g.textf("%d%% ", 0x8f91e7, "rifle.png", pwaccuracy[4]);
+ g.textf("%d%% ", 0x9ee5e5, "grenade_launcher.png", pwaccuracy[5]);
+ g.textf("%d%% ", 0xc3c3c3, "pistol.png", pwaccuracy[6]);
g.poplist();
g.separator();
g.pushlist();
- g.textf(" x %d ", 0xffffff, "blue_armour.png", pwitemspicked[0]);
- g.textf(" x %d ", 0xffffff, "green_armour.png", pwitemspicked[1]);
- g.textf(" x %d ", 0xffffff, "yellow_armour.png", pwitemspicked[2]);
- g.textf(" x %d ", 0xffffff, "tiny_health.png", pwitemspicked[3]);
- g.textf(" x %d ", 0xffffff, "health.png", pwitemspicked[4]);
- g.textf(" x %d ", 0xffffff, "health_boost.png", pwitemspicked[5]);
- g.textf(" x %d ", 0xffffff, "quad_damage.png", pwitemspicked[6]);
+ g.textf("%d ", 0xffffff, "blue_armour.png", pwitemspicked[0]);
+ g.textf("%d ", 0xffffff, "green_armour.png", pwitemspicked[1]);
+ g.textf("%d ", 0xffffff, "yellow_armour.png", pwitemspicked[2]);
+ g.textf("%d ", 0xffffff, "tiny_health.png", pwitemspicked[3]);
+ g.textf("%d ", 0xffffff, "health.png", pwitemspicked[4]);
+ g.textf("%d ", 0xffffff, "health_boost.png", pwitemspicked[5]);
+ g.textf("%d ", 0xffffff, "quad_damage.png", pwitemspicked[6]);
g.poplist();
}
struct scoreboardgui : g3d_callback {
diff --git a/src/fpsgame/server.cpp b/src/fpsgame/server.cpp
index 341b050..8f17ee2 100644
--- a/src/fpsgame/server.cpp
+++ b/src/fpsgame/server.cpp
@@ -263,7 +263,6 @@ namespace server {
extern void reqadd(clientinfo *ci, int skill);
extern void reqdel(clientinfo *ci);
extern void setbotlimit(clientinfo *ci, int limit);
- extern void setbotbalance(clientinfo *ci, bool balance);
extern void changemap();
extern void addclient(clientinfo *ci);
extern void changeteam(clientinfo *ci);
@@ -1894,63 +1893,12 @@ namespace server {
crcinfo(int crc, int matches) : crc(crc), matches(matches) {}
static bool compare(const crcinfo &x, const crcinfo &y) { return x.matches > y.matches; }
};
- VAR(modifiedmapspectator, 0, 1, 2);
- void checkmaps(int req = -1) {
- if(m_edit || !smapname[0]) return;
- vector<crcinfo> crcs;
- int total = 0, unsent = 0, invalid = 0;
- if(mcrc) crcs.add(crcinfo(mcrc, clients.length() + 1));
- loopv(clients) {
- clientinfo *ci = clients[i];
- if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE) continue;
- total++;
- if(!ci->clientmap[0]) {
- if(ci->mapcrc < 0) invalid++;
- else if(!ci->mapcrc) unsent++;
- }
- else {
- crcinfo *match = NULL;
- loopvj(crcs) if(crcs[j].crc == ci->mapcrc) { match = &crcs[j]; break; }
- if(!match) crcs.add(crcinfo(ci->mapcrc, 1));
- else match->matches++;
- }
- }
- if(!mcrc && total - unsent < min(total, 4)) return;
- crcs.sort(crcinfo::compare);
- string msg;
- loopv(clients) {
- clientinfo *ci = clients[i];
- if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE || ci->clientmap[0] || ci->mapcrc >= 0 || (req < 0 && ci->warned)) continue;
- formatstring(msg, "%s has modified map \"%s\"", colorname(ci), smapname);
- sendf(req, 1, "ris", N_SERVMSG, msg);
- if(req < 0) ci->warned = true;
- }
- if(crcs.length() >= 2) loopv(crcs) {
- crcinfo &info = crcs[i];
- if(i || info.matches <= crcs[i+1].matches) loopvj(clients) {
- clientinfo *ci = clients[j];
- if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE || !ci->clientmap[0] || ci->mapcrc != info.crc || (req < 0 && ci->warned)) continue;
- formatstring(msg, "%s has modified map \"%s\"", colorname(ci), smapname);
- sendf(req, 1, "ris", N_SERVMSG, msg);
- if(req < 0) ci->warned = true;
- }
- }
- if(req < 0 && modifiedmapspectator && (mcrc || modifiedmapspectator > 1)) loopv(clients) {
- clientinfo *ci = clients[i];
- if(!ci->local && ci->warned && ci->state.state != CS_SPECTATOR) forcespectator(ci);
- }
- }
- bool shouldspectate(clientinfo *ci) {
- return !ci->local && ci->warned && modifiedmapspectator && (mcrc || modifiedmapspectator > 1);
- }
void unspectate(clientinfo *ci) {
- if(shouldspectate(ci)) return;
ci->state.state = CS_DEAD;
ci->state.respawn();
ci->state.lasttimeplayed = lastmillis;
aiman::addclient(ci);
sendf(-1, 1, "ri3", N_SPECTATOR, ci->clientnum, 0);
- if(ci->clientmap[0] || ci->mapcrc) checkmaps();
if(!hasmap(ci)) rotatemap(true);
}
void sendservinfo(clientinfo *ci) {
@@ -2350,18 +2298,13 @@ namespace server {
}
copystring(ci->clientmap, text);
ci->mapcrc = text[0] ? crc : 1;
- checkmaps();
if(cq && cq != ci && cq->ownernum != ci->clientnum) cq = NULL;
break;
}
- case N_CHECKMAPS:
- checkmaps(sender);
- break;
case N_TRYSPAWN:
if(!ci || !cq || cq->state.state!=CS_DEAD || cq->state.lastspawn>=0) break;
if(!ci->clientmap[0] && !ci->mapcrc) {
ci->mapcrc = -1;
- checkmaps();
if(ci == cq) { if(ci->state.state != CS_DEAD) break; }
else if(cq->ownernum != ci->clientnum) { cq = NULL; break; }
}
@@ -2700,11 +2643,6 @@ namespace server {
if(ci) aiman::setbotlimit(ci, limit);
break;
}
- case N_BOTBALANCE: {
- int balance = getint(p);
- if(ci) aiman::setbotbalance(ci, balance!=0);
- break;
- }
case N_AUTHTRY: {
string desc, name;
getstring(desc, p, sizeof(desc));
@@ -2819,7 +2757,102 @@ namespace server {
const char *defaultmaster() { return "master.sauerbraten.org"; }
int masterport() { return SAUERBRATEN_MASTER_PORT; }
int numchannels() { return 3; }
- #include "extinfo.h"
+
+#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
+
+ 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(ci->team, 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, ci->state.armour);
+ 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, const char *team, int score) {
+ sendstring(team, p);
+ putint(p, score);
+ 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;
+ loopv(clients) {
+ clientinfo *ci = clients[i];
+ if(ci->state.state!=CS_SPECTATOR && ci->team[0] && scores.htfind(ci->team) < 0) {
+ teaminfo *ti = teaminfos.access(ci->team);
+ scores.add(teamscore(ci->team, ti ? ti->frags : 0));
+ }
+ }
+ 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);
+ }
+
void serverinforeply(ucharbuf &req, ucharbuf &p) {
if(req.remaining() && !getint(req)) {
extserverinforeply(req, p);
@@ -2840,6 +2873,183 @@ namespace server {
sendstring(serverdesc, p);
sendserverinforeply(p);
}
- #include "aiman.h"
+
+ // server-side ai manager
+ namespace aiman {
+ bool dorefresh = false;
+ VARN(serverbotlimit, botlimit, 0, 8, MAXBOTS);
+ void calcteams(vector<teamscore> &teams) {
+ static const char * const defaults[2] = { "good", "evil" };
+ loopv(clients) {
+ clientinfo *ci = clients[i];
+ if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue;
+ teamscore *t = NULL;
+ loopvj(teams) if(!strcmp(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() < int(sizeof(defaults)/sizeof(defaults[0]))) {
+ loopi(sizeof(defaults)/sizeof(defaults[0])) if(teams.htfind(defaults[i]) < 0) teams.add(teamscore(defaults[i], 0));
+ }
+ }
+
+ const char *chooseteam() {
+ vector<teamscore> teams;
+ calcteams(teams);
+ return teams.length() ? teams.last().team : "";
+ }
+ 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); }
+ const char *team = m_teammode ? chooseteam() : "";
+ 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;
+ copystring(ci->team, team, MAXTEAMLEN+1);
+ ci->playermodel = 0;
+ ci->aireinit = 2;
+ ci->connected = true;
+ dorefresh = true;
+ return true;
+ }
+ void deleteai(clientinfo *ci) {
+ int cn = ci->clientnum - MAXCLIENTS;
+ if(!bots.inrange(cn)) return;
+ 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, "ri6ss", N_INITAI, ci->clientnum, ci->ownernum, ci->state.aitype, ci->state.skill, ci->playermodel, ci->name, ci->team);
+ 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) {
+ 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() {
+ 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 changemap() {
+ dorefresh = true;
+ loopv(clients) if(clients[i]->local || clients[i]->privilege) return;
+ }
+ void addclient(clientinfo *ci) {
+ if(ci->state.aitype == AI_NONE) dorefresh = true;
+ }
+ void changeteam(clientinfo *ci) {
+ if(ci->state.aitype == AI_NONE) dorefresh = true;
+ }
+ }
}
diff --git a/src/fpsgame/weapon.cpp b/src/fpsgame/weapon.cpp
index 30d2da8..4c85a36 100644
--- a/src/fpsgame/weapon.cpp
+++ b/src/fpsgame/weapon.cpp
@@ -408,14 +408,13 @@ namespace game {
else p.o = v;
}
}
- extern int chainsawhudgun;
VARP(muzzleflash, 0, 1, 1);
VARP(muzzlelight, 0, 1, 1);
void shoteffects(int gun, const vec &from, const vec &to, fpsent *d, bool local, int id, int prevaction) { // create visual effect from a shot {
int sound = guns[gun].sound, pspeed = 25;
switch(gun) {
case GUN_FIST:
- if(d->type==ENT_PLAYER && chainsawhudgun) sound = S_CHAINSAW_ATTACK;
+ if(d->type==ENT_PLAYER) sound = S_CHAINSAW_ATTACK;
break;
case GUN_SG: {
if(!local) createrays(gun, from, to);
@@ -613,7 +612,7 @@ namespace game {
}
pitch = -bnc.roll;
if(bnc.bouncetype==BNC_GRENADE)
- rendermodel(&bnc.light, "projectiles/grenade", ANIM_MAPMODEL|ANIM_LOOP, pos, yaw, pitch, MDL_CULL_VFC|MDL_CULL_OCCLUDED|MDL_LIGHT|MDL_LIGHT_FAST|MDL_DYNSHADOW);
+ rendermodel(&bnc.light, "projectiles/grenade", ANIM_MAPMODEL|ANIM_LOOP, pos, yaw, pitch, MDL_CULL_VFC|MDL_CULL_OCCLUDED|MDL_LIGHT|MDL_LIGHT_FAST);
else {
const char *mdl = NULL;
int cull = MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED;
@@ -643,7 +642,7 @@ namespace game {
int gun = -1;
switch(d->attacksound) {
case S_CHAINSAW_ATTACK:
- if(chainsawhudgun) gun = GUN_FIST;
+ gun = GUN_FIST;
break;
default:
return;
@@ -660,7 +659,7 @@ namespace game {
int sound = -1, radius = 0;
if(d->clientnum >= 0 && d->state == CS_ALIVE) switch(d->gunselect) {
case GUN_FIST:
- if(chainsawhudgun && d->attacksound < 0) {
+ if(d->attacksound < 0) {
sound = S_CHAINSAW_IDLE;
radius = 50;
}
@@ -711,9 +710,10 @@ namespace game {
/// Rough accuracy code, client-side only.
int pwshotsfired [NUMGUNS] = { 0 };
-int pwshotshit [NUMGUNS] = { 0 };
+int pwshotshit [NUMGUNS] = { 0 };
int pwdamagedealt [NUMGUNS] = { 0 };
-int pwaccuracy [NUMGUNS] = { 0 };
+int pwaccuracy [NUMGUNS] = { 0 };
+
int pwavgaccuracy = 0;
void pwshot(int gun) {