From 0a1172b75f571685c264a8b9d8ee224bbf11381f Mon Sep 17 00:00:00 2001 From: xolatile Date: Wed, 6 Aug 2025 22:54:55 +0200 Subject: Please do not hate me, it makes sense... --- src/fpsgame/ai.cpp | 828 ++++++--------------- src/fpsgame/ai.h | 160 +--- src/fpsgame/aiman.h | 147 ++-- src/fpsgame/client.cpp | 874 ++++++---------------- src/fpsgame/entities.cpp | 211 ++---- src/fpsgame/extinfo.h | 57 +- src/fpsgame/fps.cpp | 654 ++++------------ src/fpsgame/game.h | 216 ++---- src/fpsgame/render.cpp | 224 ++---- src/fpsgame/scoreboard.cpp | 263 ++----- src/fpsgame/server.cpp | 1779 ++++++++++++-------------------------------- src/fpsgame/waypoint.cpp | 424 +++-------- src/fpsgame/weapon.cpp | 460 ++++-------- 13 files changed, 1719 insertions(+), 4578 deletions(-) (limited to 'src/fpsgame') diff --git a/src/fpsgame/ai.cpp b/src/fpsgame/ai.cpp index 0886245..b4e631b 100644 --- a/src/fpsgame/ai.cpp +++ b/src/fpsgame/ai.cpp @@ -1,100 +1,68 @@ #include "game.h" -namespace ai -{ +namespace ai { using namespace game; - avoidset obstacles; int updatemillis = 0, iteration = 0, itermillis = 0, forcegun = -1; vec aitarget(0, 0, 0); - VAR(aidebug, 0, 0, 6); VAR(aiforcegun, -1, -1, NUMGUNS-1); - 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) - { + float viewdist(int x) { return x <= 100 ? clamp((SIGHTMIN+(SIGHTMAX-SIGHTMIN))/100.f*float(x), float(SIGHTMIN), 10000.0f) : 10000.0f; } - - float viewfieldx(int x) - { + float viewfieldx(int x) { return x <= 100 ? clamp((VIEWMIN+(VIEWMAX-VIEWMIN))/100.f*float(x), float(VIEWMIN), float(VIEWMAX)) : float(VIEWMAX); } - - float viewfieldy(int x) - { + float viewfieldy(int x) { return viewfieldx(x)*3.f/4.f; } - - bool canmove(fpsent *d) - { + bool canmove(fpsent *d) { return d->state != CS_DEAD && !intermission; } - - float weapmindist(int weap) - { + float weapmindist(int weap) { return max(int(guns[weap].exprad), 2); } - - float weapmaxdist(int weap) - { + float weapmaxdist(int weap) { return guns[weap].range + 4; } - - bool weaprange(fpsent *d, int weap, float dist) - { + bool weaprange(fpsent *d, int weap, float dist) { float mindist = weapmindist(weap), maxdist = weapmaxdist(weap); return dist >= mindist*mindist && dist <= maxdist*maxdist; } - - bool targetable(fpsent *d, fpsent *e) - { + bool targetable(fpsent *d, fpsent *e) { if(d == e || !canmove(d)) return false; return e->state == CS_ALIVE && !isteam(d->team, e->team); } - - bool getsight(vec &o, float yaw, float pitch, vec &q, vec &v, float mdist, float fovx, float fovy) - { + bool getsight(vec &o, float yaw, float pitch, vec &q, vec &v, float mdist, float fovx, float fovy) { float dist = o.dist(q); - - if(dist <= mdist) - { + if(dist <= mdist) { float x = fmod(fabs(asin((q.z-o.z)/dist)/RAD-pitch), 360); float y = fmod(fabs(-atan2(q.x-o.x, q.y-o.y)/RAD-yaw), 360); if(min(x, 360-x) <= fovx && min(y, 360-y) <= fovy) return raycubelos(o, q, v); } return false; } - - bool cansee(fpsent *d, vec &x, vec &y, vec &targ) - { + bool cansee(fpsent *d, vec &x, vec &y, vec &targ) { aistate &b = d->ai->getstate(); if(canmove(d) && b.type != AI_S_WAIT) return getsight(x, d->yaw, d->pitch, y, targ, d->ai->views[2], d->ai->views[0], d->ai->views[1]); return false; } - - bool canshoot(fpsent *d, fpsent *e) - { + bool canshoot(fpsent *d, fpsent *e) { if(weaprange(d, d->gunselect, e->o.squaredist(d->o)) && targetable(d, e)) return d->ammo[d->gunselect] > 0 && lastmillis - d->lastaction >= d->gunwait; return false; } - - bool canshoot(fpsent *d) - { + bool canshoot(fpsent *d) { return !d->ai->becareful && d->ammo[d->gunselect] > 0 && lastmillis - d->lastaction >= d->gunwait; } - - bool hastarget(fpsent *d, aistate &b, fpsent *e, float yaw, float pitch, float dist) - { // add margins of error - if(weaprange(d, d->gunselect, dist) || (d->skill <= 100 && !rnd(d->skill))) - { + bool hastarget(fpsent *d, aistate &b, fpsent *e, float yaw, float pitch, float dist) { + // add margins of error + if(weaprange(d, d->gunselect, dist) || (d->skill <= 100 && !rnd(d->skill))) { if(d->gunselect == GUN_FIST) return true; float skew = clamp(float(lastmillis-d->ai->enemymillis)/float((d->skill*guns[d->gunselect].attackdelay/200.f)), 0.f, guns[d->gunselect].projspeed ? 0.25f : 1e16f), offy = yaw-d->yaw, offp = pitch-d->pitch; @@ -104,16 +72,12 @@ namespace ai } return false; } - - vec getaimpos(fpsent *d, fpsent *e) - { + vec getaimpos(fpsent *d, fpsent *e) { vec o = e->o; if(d->gunselect == GUN_RL) o.z += (e->aboveeye*0.2f)-(0.8f*d->eyeheight); else if(d->gunselect != GUN_GL) o.z += (e->aboveeye-e->eyeheight)*0.5f; - if(d->skill <= 100) - { - if(lastmillis >= d->ai->lastaimrnd) - { + if(d->skill <= 100) { + if(lastmillis >= d->ai->lastaimrnd) { const int aiskew[NUMGUNS] = { 1, 10, 50, 5, 20, 1, 100 }; #define rndaioffset(r) ((rnd(int(r*aiskew[d->gunselect]*2)+1)-(r*aiskew[d->gunselect]))*(1.f/float(max(d->skill, 1)))) loopk(3) d->ai->aimrnd[k] = rndaioffset(e->radius); @@ -124,55 +88,39 @@ namespace ai } return o; } - - void create(fpsent *d) - { + void create(fpsent *d) { if(!d->ai) d->ai = new aiinfo; } - - void destroy(fpsent *d) - { + void destroy(fpsent *d) { if(d->ai) DELETEP(d->ai); } - - void init(fpsent *d, int at, int ocn, int sk, int bn, int pm, const char *name, const char *team) - { + void init(fpsent *d, int at, int ocn, int sk, int bn, int pm, const char *name, const char *team) { loadwaypoints(); - fpsent *o = newclient(ocn); - d->aitype = at; - bool resetthisguy = false; - if(!d->name[0]) - { + if(!d->name[0]) { if(aidebug) conoutf(CON_DEBUG, "%s assigned to %s at skill %d", colorname(d, name), o ? colorname(o) : "?", sk); else conoutf("\f0join:\f7 %s", colorname(d, name)); resetthisguy = true; } - else - { - if(d->ownernum != ocn) - { + else { + if(d->ownernum != ocn) { if(aidebug) conoutf(CON_DEBUG, "%s reassigned to %s", colorname(d, name), o ? colorname(o) : "?"); resetthisguy = true; } if(d->skill != sk && aidebug) conoutf(CON_DEBUG, "%s changed skill to %d", colorname(d, name), sk); } - copystring(d->name, name, MAXNAMELEN+1); copystring(d->team, team, MAXTEAMLEN+1); d->ownernum = ocn; d->plag = 0; d->skill = sk; d->playermodel = 0; - if(resetthisguy) removeweapons(d); - if(d->ownernum >= 0 && player1->clientnum == d->ownernum) - { + if(d->ownernum >= 0 && player1->clientnum == d->ownernum) { create(d); - if(d->ai) - { + if(d->ai) { d->ai->views[0] = viewfieldx(d->skill); d->ai->views[1] = viewfieldy(d->skill); d->ai->views[2] = viewdist(d->skill); @@ -180,20 +128,15 @@ namespace ai } else if(d->ai) destroy(d); } - - void update() - { + void update() { if(intermission) { loopv(players) if(players[i]->ai) players[i]->stopmoving(); } - else // fixed rate logic done out-of-sequence at 1 frame per second for each ai - { - if(totalmillis-updatemillis > 1000) - { + else { // fixed rate logic done out-of-sequence at 1 frame per second for each ai { + if(totalmillis-updatemillis > 1000) { avoid(); forcegun = multiplayer(false) ? -1 : aiforcegun; updatemillis = totalmillis; } - if(!iteration && totalmillis-itermillis > 1000) - { + if(!iteration && totalmillis-itermillis > 1000) { iteration = 1; itermillis = totalmillis; } @@ -202,12 +145,10 @@ namespace ai if(++iteration > count) iteration = 0; } } - - bool checkothers(vector &targets, fpsent *d, int state, int targtype, int target, bool teams, int *members) - { // checks the states of other ai for a match + bool checkothers(vector &targets, fpsent *d, int state, int targtype, int target, bool teams, int *members) { + // checks the states of other ai for a match targets.setsize(0); - loopv(players) - { + loopv(players) { fpsent *e = players[i]; if(targets.find(e->clientnum) >= 0) continue; if(teams && d && !isteam(d->team, e->team)) continue; @@ -221,13 +162,10 @@ namespace ai } return !targets.empty(); } - - bool makeroute(fpsent *d, aistate &b, int node, bool changed, int retries) - { + bool makeroute(fpsent *d, aistate &b, int node, bool changed, int retries) { if(!iswaypoint(d->lastnode)) return false; if(changed && d->ai->route.length() > 1 && d->ai->route[0] == node) return true; - if(route(d, d->lastnode, node, d->ai->route, obstacles, retries)) - { + if(route(d, d->lastnode, node, d->ai->route, obstacles, retries)) { b.override = false; return true; } @@ -235,51 +173,37 @@ namespace ai if(retries <= 1) return makeroute(d, b, node, false, retries+1); return false; } - - bool makeroute(fpsent *d, aistate &b, const vec &pos, bool changed, int retries) - { + bool makeroute(fpsent *d, aistate &b, const vec &pos, bool changed, int retries) { int node = closestwaypoint(pos, SIGHTMIN, true); return makeroute(d, b, node, changed, retries); } - - bool randomnode(fpsent *d, aistate &b, const vec &pos, float guard, float wander) - { + bool randomnode(fpsent *d, aistate &b, const vec &pos, float guard, float wander) { static vector candidates; candidates.setsize(0); findwaypointswithin(pos, guard, wander, candidates); - - while(!candidates.empty()) - { + while(!candidates.empty()) { int w = rnd(candidates.length()), n = candidates.removeunordered(w); if(n != d->lastnode && !d->ai->hasprevnode(n) && !obstacles.find(n, d) && makeroute(d, b, n)) return true; } return false; } - - bool randomnode(fpsent *d, aistate &b, float guard, float wander) - { + bool randomnode(fpsent *d, aistate &b, float guard, float wander) { return randomnode(d, b, d->feetpos(), guard, wander); } - - bool badhealth(fpsent *d) - { + bool badhealth(fpsent *d) { if(d->skill <= 100) return d->health <= (111-d->skill)/4; return false; } - - bool enemy(fpsent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, int pursue = 0) - { + bool enemy(fpsent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, int pursue = 0) { fpsent *t = NULL; vec dp = d->headpos(); float mindist = guard*guard, bestdist = 1e16f; - loopv(players) - { + loopv(players) { fpsent *e = players[i]; if(e == d || !targetable(d, e)) continue; vec ep = getaimpos(d, e); float dist = ep.squaredist(dp); - if(dist < bestdist && (cansee(d, dp, ep) || dist <= mindist)) - { + if(dist < bestdist && (cansee(d, dp, ep) || dist <= mindist)) { t = e; bestdist = dist; } @@ -287,21 +211,16 @@ namespace ai if(t && violence(d, b, t, pursue)) return true; return false; } - - bool patrol(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk, bool retry) - { + bool patrol(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk, bool retry) { vec feet = d->feetpos(); - if(walk == 2 || b.override || (walk && feet.squaredist(pos) <= guard*guard) || !makeroute(d, b, pos)) - { // run away and back to keep ourselves busy - if(!b.override && randomnode(d, b, pos, guard, wander)) - { + if(walk == 2 || b.override || (walk && feet.squaredist(pos) <= guard*guard) || !makeroute(d, b, pos)) { + // run away and back to keep ourselves busy + if(!b.override && randomnode(d, b, pos, guard, wander)) { b.override = true; return true; } - else if(d->ai->route.empty()) - { - if(!retry) - { + else if(d->ai->route.empty()) { + if(!retry) { b.override = false; return patrol(d, b, pos, guard, wander, walk, true); } @@ -312,14 +231,10 @@ namespace ai b.override = false; return true; } - - bool defend(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk) - { + bool defend(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk) { bool hasenemy = enemy(d, b, pos, wander, d->gunselect == GUN_FIST ? 1 : 0); - if(!walk) - { - if(d->feetpos().squaredist(pos) <= guard*guard) - { + if(!walk) { + if(d->feetpos().squaredist(pos) <= guard*guard) { b.idle = hasenemy ? 2 : 1; return true; } @@ -327,19 +242,14 @@ namespace ai } return patrol(d, b, pos, guard, wander, walk); } - - bool violence(fpsent *d, aistate &b, fpsent *e, int pursue) - { - if(e && targetable(d, e)) - { - if(pursue) - { + bool violence(fpsent *d, aistate &b, fpsent *e, int pursue) { + if(e && targetable(d, e)) { + if(pursue) { if((b.targtype != AI_T_AFFINITY || !(pursue%2)) && makeroute(d, b, e->lastnode)) d->ai->switchstate(b, AI_S_PURSUE, AI_T_PLAYER, e->clientnum); else if(pursue >= 3) return false; // can't pursue } - if(d->ai->enemy != e->clientnum) - { + if(d->ai->enemy != e->clientnum) { d->ai->enemyseen = d->ai->enemymillis = lastmillis; d->ai->enemy = e->clientnum; } @@ -347,29 +257,23 @@ namespace ai } return false; } - - bool target(fpsent *d, aistate &b, int pursue = 0, bool force = false, float mindist = 0.f) - { + bool target(fpsent *d, aistate &b, int pursue = 0, bool force = false, float mindist = 0.f) { static vector hastried; hastried.setsize(0); vec dp = d->headpos(); - while(true) - { + while(true) { float dist = 1e16f; fpsent *t = NULL; - loopv(players) - { + loopv(players) { fpsent *e = players[i]; if(e == d || hastried.find(e) >= 0 || !targetable(d, e)) continue; vec ep = getaimpos(d, e); float v = ep.squaredist(dp); - if((!t || v < dist) && (mindist <= 0 || v <= mindist) && (force || cansee(d, dp, ep))) - { + if((!t || v < dist) && (mindist <= 0 || v <= mindist) && (force || cansee(d, dp, ep))) { t = e; dist = v; } } - if(t) - { + if(t) { if(violence(d, b, t, pursue)) return true; hastried.add(t); } @@ -377,21 +281,15 @@ namespace ai } return false; } - int isgoodammo(int gun) { return gun >= GUN_SG && gun <= GUN_GL; } - - bool hasgoodammo(fpsent *d) - { + bool hasgoodammo(fpsent *d) { static const int goodguns[] = { GUN_CG, GUN_RL, GUN_SG, GUN_RIFLE }; loopi(sizeof(goodguns)/sizeof(goodguns[0])) if(d->hasammo(goodguns[0])) return true; if(d->ammo[GUN_GL] > 5) return true; return false; } - - void assist(fpsent *d, aistate &b, vector &interests, bool all, bool force) - { - loopv(players) - { + void assist(fpsent *d, aistate &b, vector &interests, bool all, bool force) { + loopv(players) { fpsent *e = players[i]; if(e == d || (!all && e->aitype != AI_NONE) || !isteam(d->team, e->team)) continue; interest &n = interests.add(); @@ -402,28 +300,22 @@ namespace ai n.score = e->o.squaredist(d->o)/(hasgoodammo(d) ? 1e8f : (force ? 1e4f : 1e2f)); } } - - static void tryitem(fpsent *d, extentity &e, int id, aistate &b, vector &interests, bool force = false) - { + static void tryitem(fpsent *d, extentity &e, int id, aistate &b, vector &interests, bool force = false) { float score = 0; - switch(e.type) - { + switch(e.type) { case I_HEALTH: if(d->health < min(d->skill, 75)) score = 1e3f; break; case I_QUAD: score = 1e3f; break; case I_BOOST: score = 1e2f; break; - case I_GREENARMOUR: case I_YELLOWARMOUR: - { + case I_GREENARMOUR: case I_YELLOWARMOUR: { int atype = A_GREEN + e.type - I_GREENARMOUR; if(atype > d->armourtype) score = atype == A_YELLOW ? 1e2f : 1e1f; else if(d->armour < 50) score = 1e1f; break; } - default: - { - if(e.type >= I_SHELLS && e.type <= I_CARTRIDGES && !d->hasmaxammo(e.type)) - { + default: { + if(e.type >= I_SHELLS && e.type <= I_CARTRIDGES && !d->hasmaxammo(e.type)) { int gun = e.type - I_SHELLS + GUN_SG; // go get a weapon upgrade if(gun == d->ai->weappref) score = 1e8f; @@ -432,8 +324,7 @@ namespace ai break; } } - if(score != 0) - { + if(score != 0) { interest &n = interests.add(); n.state = AI_S_INTEREST; n.node = closestwaypoint(e.o, SIGHTMIN, true); @@ -442,61 +333,46 @@ namespace ai n.score = d->feetpos().squaredist(e.o)/(force ? -1 : score); } } - - void items(fpsent *d, aistate &b, vector &interests, bool force = false) - { - loopv(entities::ents) - { + void items(fpsent *d, aistate &b, vector &interests, bool force = false) { + loopv(entities::ents) { extentity &e = *(extentity *)entities::ents[i]; if(!e.spawned() || e.nopickup() || !d->canpickup(e.type)) continue; tryitem(d, e, i, b, interests, force); } } - static vector targets; - - bool parseinterests(fpsent *d, aistate &b, vector &interests, bool override, bool ignore) - { - while(!interests.empty()) - { + bool parseinterests(fpsent *d, aistate &b, vector &interests, bool override, bool ignore) { + while(!interests.empty()) { int q = interests.length()-1; loopi(interests.length()-1) if(interests[i].score < interests[q].score) q = i; interest n = interests.removeunordered(q); bool proceed = true; - if(!ignore) switch(n.state) - { - case AI_S_DEFEND: // don't get into herds - { + if(!ignore) switch(n.state) { + case AI_S_DEFEND: { // don't get into herds { int members = 0; proceed = !checkothers(targets, d, n.state, n.targtype, n.target, true, &members) && members > 1; break; } default: break; } - if(proceed && makeroute(d, b, n.node)) - { + if(proceed && makeroute(d, b, n.node)) { d->ai->switchstate(b, n.state, n.targtype, n.target); return true; } } return false; } - - bool find(fpsent *d, aistate &b, bool override = false) - { + bool find(fpsent *d, aistate &b, bool override = false) { static vector interests; interests.setsize(0); - if(!m_noitems) - { + if(!m_noitems) { if((!m_noammo && !hasgoodammo(d)) || d->health < min(d->skill - 15, 75)) items(d, b, interests); - else - { + else { static vector nearby; nearby.setsize(0); findents(I_SHELLS, I_QUAD, false, d->feetpos(), vec(32, 32, 24), nearby); - loopv(nearby) - { + loopv(nearby) { int id = nearby[i]; extentity &e = *(extentity *)entities::ents[id]; if(d->canpickup(e.type)) tryitem(d, e, id, b, interests); @@ -506,48 +382,37 @@ namespace ai if(m_teammode) assist(d, b, interests); return parseinterests(d, b, interests, override); } - - bool findassist(fpsent *d, aistate &b, bool override = false) - { + bool findassist(fpsent *d, aistate &b, bool override = false) { static vector interests; interests.setsize(0); assist(d, b, interests); - while(!interests.empty()) - { + while(!interests.empty()) { int q = interests.length()-1; loopi(interests.length()-1) if(interests[i].score < interests[q].score) q = i; interest n = interests.removeunordered(q); bool proceed = true; - switch(n.state) - { - case AI_S_DEFEND: // don't get into herds - { + switch(n.state) { + case AI_S_DEFEND: { // don't get into herds { int members = 0; proceed = !checkothers(targets, d, n.state, n.targtype, n.target, true, &members) && members > 1; break; } default: break; } - if(proceed && makeroute(d, b, n.node)) - { + if(proceed && makeroute(d, b, n.node)) { d->ai->switchstate(b, n.state, n.targtype, n.target); return true; } } return false; } - - void damaged(fpsent *d, fpsent *e) - { - if(d->ai && canmove(d) && targetable(d, e)) // see if this ai is interested in a grudge - { + void damaged(fpsent *d, fpsent *e) { + if(d->ai && canmove(d) && targetable(d, e)) { // see if this ai is interested in a grudge { aistate &b = d->ai->getstate(); if(violence(d, b, e, d->gunselect == GUN_FIST ? 1 : 0)) return; } - if(checkothers(targets, d, AI_S_DEFEND, AI_T_PLAYER, d->clientnum, true)) - { - loopv(targets) - { + if(checkothers(targets, d, AI_S_DEFEND, AI_T_PLAYER, d->clientnum, true)) { + loopv(targets) { fpsent *t = getclient(targets[i]); if(!t->ai || !canmove(t) || !targetable(t, e)) continue; aistate &c = t->ai->getstate(); @@ -555,23 +420,18 @@ namespace ai } } } - - void findorientation(vec &o, float yaw, float pitch, vec &pos) - { + void findorientation(vec &o, float yaw, float pitch, vec &pos) { vec dir; vecfromyawpitch(yaw, pitch, 1, 0, dir); if(raycubepos(o, dir, pos, 0, RAY_CLIPMAT|RAY_SKIPFIRST) == -1) pos = dir.mul(2*getworldsize()).add(o); } - - void setup(fpsent *d) - { + void setup(fpsent *d) { d->ai->clearsetup(); d->ai->reset(true); d->ai->lastrun = lastmillis; if(m_insta) d->ai->weappref = GUN_RIFLE; - else - { + else { if(forcegun >= 0 && forcegun < NUMGUNS) d->ai->weappref = forcegun; else if(m_noammo) d->ai->weappref = -1; else d->ai->weappref = rnd(GUN_GL-GUN_SG+1)+GUN_SG; @@ -579,50 +439,34 @@ namespace ai vec dp = d->headpos(); findorientation(dp, d->yaw, d->pitch, d->ai->target); } - - void spawned(fpsent *d) - { + void spawned(fpsent *d) { if(d->ai) setup(d); } - - void killed(fpsent *d, fpsent *e) - { + void killed(fpsent *d, fpsent *e) { if(d->ai) d->ai->reset(); } - - void itemspawned(int ent) - { - if(entities::ents.inrange(ent) && entities::ents[ent]->type >= I_SHELLS && entities::ents[ent]->type <= I_QUAD) - { - loopv(players) if(players[i] && players[i]->ai && players[i]->aitype == AI_BOT && players[i]->canpickup(entities::ents[ent]->type)) - { + void itemspawned(int ent) { + if(entities::ents.inrange(ent) && entities::ents[ent]->type >= I_SHELLS && entities::ents[ent]->type <= I_QUAD) { + loopv(players) if(players[i] && players[i]->ai && players[i]->aitype == AI_BOT && players[i]->canpickup(entities::ents[ent]->type)) { fpsent *d = players[i]; bool wantsitem = false; - switch(entities::ents[ent]->type) - { + switch(entities::ents[ent]->type) { case I_BOOST: - case I_HEALTH: wantsitem = badhealth(d); break; case I_GREENARMOUR: - case I_YELLOWARMOUR: - case I_QUAD: break; - default: - { + default: { itemstat &is = itemstats[entities::ents[ent]->type-I_SHELLS]; wantsitem = isgoodammo(is.info) && d->ammo[is.info] <= (d->ai->weappref == is.info ? is.add : is.add/2); break; } } - if(wantsitem) - { + if(wantsitem) { aistate &b = d->ai->getstate(); if(b.targtype == AI_T_AFFINITY) continue; - if(b.type == AI_S_INTEREST && b.targtype == AI_T_ENTITY) - { - if(entities::ents.inrange(b.target)) - { + if(b.type == AI_S_INTEREST && b.targtype == AI_T_ENTITY) { + if(entities::ents.inrange(b.target)) { if(d->o.squaredist(entities::ents[ent]->o) < d->o.squaredist(entities::ents[b.target]->o)) d->ai->switchstate(b, AI_S_INTEREST, AI_T_ENTITY, ent); } @@ -633,35 +477,27 @@ namespace ai } } } - - int dowait(fpsent *d, aistate &b) - { + int dowait(fpsent *d, aistate &b) { d->ai->clear(true); // ensure they're clean if(find(d, b)) return 1; if(target(d, b, 4, false)) return 1; if(target(d, b, 4, true)) return 1; - if(randomnode(d, b, SIGHTMIN, 1e16f)) - { + if(randomnode(d, b, SIGHTMIN, 1e16f)) { d->ai->switchstate(b, AI_S_INTEREST, AI_T_NODE, d->ai->route[0]); return 1; } return 0; // but don't pop the state } - - int dodefend(fpsent *d, aistate &b) - { - if(d->state == CS_ALIVE) - { - switch(b.targtype) - { + int dodefend(fpsent *d, aistate &b) { + if(d->state == CS_ALIVE) { + switch(b.targtype) { case AI_T_NODE: if(iswaypoint(b.target)) return defend(d, b, waypoints[b.target].o) ? 1 : 0; break; case AI_T_ENTITY: if(entities::ents.inrange(b.target)) return defend(d, b, entities::ents[b.target]->o) ? 1 : 0; break; - case AI_T_PLAYER: - { + case AI_T_PLAYER: { fpsent *e = getclient(b.target); if(e && e->state == CS_ALIVE) return defend(d, b, e->feetpos()) ? 1 : 0; break; @@ -671,12 +507,9 @@ namespace ai } return 0; } - - int dointerest(fpsent *d, aistate &b) - { + int dointerest(fpsent *d, aistate &b) { if(d->state != CS_ALIVE) return 0; - switch(b.targtype) - { + switch(b.targtype) { case AI_T_NODE: // this is like a wait state without sitting still.. if(find(d, b)) return 1; if(target(d, b, 4, true)) return 1; @@ -684,8 +517,7 @@ namespace ai return makeroute(d, b, waypoints[b.target].o) ? 1 : 0; break; case AI_T_ENTITY: - if(entities::ents.inrange(b.target)) - { + if(entities::ents.inrange(b.target)) { extentity &e = *(extentity *)entities::ents[b.target]; if(!e.spawned() || e.nopickup() || e.type < I_SHELLS || e.type > I_CARTRIDGES || d->hasmaxammo(e.type)) return 0; //if(d->feetpos().squaredist(e.o) <= CLOSEDIST*CLOSEDIST) @@ -699,25 +531,17 @@ namespace ai } return 0; } - - int dopursue(fpsent *d, aistate &b) - { - if(d->state == CS_ALIVE) - { - switch(b.targtype) - { - case AI_T_NODE: - { + int dopursue(fpsent *d, aistate &b) { + if(d->state == CS_ALIVE) { + switch(b.targtype) { + case AI_T_NODE: { if(iswaypoint(b.target)) return defend(d, b, waypoints[b.target].o) ? 1 : 0; break; } - - case AI_T_PLAYER: - { + case AI_T_PLAYER: { fpsent *e = getclient(b.target); - if(e && e->state == CS_ALIVE) - { + if(e && e->state == CS_ALIVE) { float guard = SIGHTMIN, wander = guns[d->gunselect].range; if(d->gunselect == GUN_FIST) guard = 0.f; return patrol(d, b, e->feetpos(), guard, wander) ? 1 : 0; @@ -729,20 +553,16 @@ namespace ai } return 0; } - - int closenode(fpsent *d) - { + int closenode(fpsent *d) { vec pos = d->feetpos(); int node1 = -1, node2 = -1; float mindist1 = CLOSEDIST*CLOSEDIST, mindist2 = CLOSEDIST*CLOSEDIST; - loopv(d->ai->route) if(iswaypoint(d->ai->route[i])) - { + loopv(d->ai->route) if(iswaypoint(d->ai->route[i])) { vec epos = waypoints[d->ai->route[i]].o; float dist = epos.squaredist(pos); if(dist > FARDIST*FARDIST) continue; int entid = obstacles.remap(d, d->ai->route[i], epos); - if(entid >= 0) - { + if(entid >= 0) { if(entid != i) dist = epos.squaredist(pos); if(dist < mindist1) { node1 = i; mindist1 = dist; } } @@ -750,15 +570,11 @@ namespace ai } return node1 >= 0 ? node1 : node2; } - - int wpspot(fpsent *d, int n, bool check = false) - { - if(iswaypoint(n)) loopk(2) - { + int wpspot(fpsent *d, int n, bool check = false) { + if(iswaypoint(n)) loopk(2) { vec epos = waypoints[n].o; int entid = obstacles.remap(d, n, epos, k!=0); - if(iswaypoint(entid)) - { + if(iswaypoint(entid)) { d->ai->spot = epos; d->ai->targnode = entid; return !check || d->feetpos().squaredist(epos) > MINWPDIST*MINWPDIST ? 1 : 2; @@ -766,15 +582,11 @@ namespace ai } return 0; } - - int randomlink(fpsent *d, int n) - { - if(iswaypoint(n) && waypoints[n].haslinks()) - { + int randomlink(fpsent *d, int n) { + if(iswaypoint(n) && waypoints[n].haslinks()) { waypoint &w = waypoints[n]; static vector linkmap; linkmap.setsize(0); - loopi(MAXWAYPOINTLINKS) - { + loopi(MAXWAYPOINTLINKS) { if(!w.links[i]) break; if(iswaypoint(w.links[i]) && !d->ai->hasprevnode(w.links[i]) && d->ai->route.find(w.links[i]) < 0) linkmap.add(w.links[i]); @@ -783,19 +595,14 @@ namespace ai } return -1; } - - bool anynode(fpsent *d, aistate &b, int len = NUMPREVNODES) - { - if(iswaypoint(d->lastnode)) loopk(2) - { + bool anynode(fpsent *d, aistate &b, int len = NUMPREVNODES) { + if(iswaypoint(d->lastnode)) loopk(2) { d->ai->clear(k ? true : false); int n = randomlink(d, d->lastnode); - if(wpspot(d, n)) - { + if(wpspot(d, n)) { d->ai->route.add(n); d->ai->route.add(d->lastnode); - loopi(len) - { + loopi(len) { n = randomlink(d, n); if(iswaypoint(n)) d->ai->route.insert(0, n); else break; @@ -805,29 +612,23 @@ namespace ai } return false; } - - bool checkroute(fpsent *d, int n) - { + bool checkroute(fpsent *d, int n) { if(d->ai->route.empty() || !d->ai->route.inrange(n)) return false; int last = d->ai->lastcheck ? lastmillis-d->ai->lastcheck : 0; if(last < 500 || n < 3) return false; // route length is too short d->ai->lastcheck = lastmillis; int w = iswaypoint(d->lastnode) ? d->lastnode : d->ai->route[n], c = min(n-1, NUMPREVNODES); - loopj(c) // check ahead to see if we need to go around something - { + loopj(c) { // check ahead to see if we need to go around something { int p = n-j-1, v = d->ai->route[p]; - if(d->ai->hasprevnode(v) || obstacles.find(v, d)) // something is in the way, try to remap around it - { + if(d->ai->hasprevnode(v) || obstacles.find(v, d)) { // something is in the way, try to remap around it { int m = p-1; if(m < 3) return false; // route length is too short from this point - loopirev(m) - { + loopirev(m) { int t = d->ai->route[i]; - if(!d->ai->hasprevnode(t) && !obstacles.find(t, d)) - { + if(!d->ai->hasprevnode(t) && !obstacles.find(t, d)) { static vector remap; remap.setsize(0); - if(route(d, w, t, remap, obstacles)) - { // kill what we don't want and put the remap in + if(route(d, w, t, remap, obstacles)) { + // kill what we don't want and put the remap in while(d->ai->route.length() > i) d->ai->route.pop(); loopvk(remap) d->ai->route.add(remap[k]); return true; @@ -840,28 +641,20 @@ namespace ai } return false; } - - bool hunt(fpsent *d, aistate &b) - { - if(!d->ai->route.empty()) - { + bool hunt(fpsent *d, aistate &b) { + if(!d->ai->route.empty()) { int n = closenode(d); if(d->ai->route.inrange(n) && checkroute(d, n)) n = closenode(d); - if(d->ai->route.inrange(n)) - { - if(!n) - { - switch(wpspot(d, d->ai->route[n], true)) - { + if(d->ai->route.inrange(n)) { + if(!n) { + switch(wpspot(d, d->ai->route[n], true)) { case 2: d->ai->clear(false); [[fallthrough]]; - case 1: return true; // not close enough to pop it yet default: break; } } - else - { + else { while(d->ai->route.length() > n+1) d->ai->route.pop(); // waka-waka-waka-waka int m = n-1; // next, please! if(d->ai->route.inrange(m) && wpspot(d, d->ai->route[m])) return true; @@ -871,30 +664,24 @@ namespace ai b.override = false; return anynode(d, b); } - - void jumpto(fpsent *d, aistate &b, const vec &pos) - { + void jumpto(fpsent *d, aistate &b, const vec &pos) { vec off = vec(pos).sub(d->feetpos()), dir(off.x, off.y, 0); bool sequenced = d->ai->blockseq || d->ai->targseq, offground = d->timeinair && !d->inwater, jump = !offground && lastmillis >= d->ai->jumpseed && (sequenced || off.z >= JUMPMIN || lastmillis >= d->ai->jumprand); - if(jump) - { + if(jump) { vec old = d->o; d->o = vec(pos).add(vec(0, 0, d->eyeheight)); if(collide(d, vec(0, 0, 1))) jump = false; d->o = old; - if(jump) - { + if(jump) { float radius = 18*18; - loopv(entities::ents) if(entities::ents[i]->type == JUMPPAD) - { + loopv(entities::ents) if(entities::ents[i]->type == JUMPPAD) { extentity &e = *(extentity *)entities::ents[i]; if(e.o.squaredist(pos) <= radius) { jump = false; break; } } } } - if(jump) - { + if(jump) { d->jumping = true; int seed = (111-d->skill)*(d->inwater ? 3 : 5); d->ai->jumpseed = lastmillis+seed+rnd(seed); @@ -902,18 +689,14 @@ namespace ai d->ai->jumprand = lastmillis+seed+rnd(seed); } } - - void fixfullrange(float &yaw, float &pitch, float &roll, bool full) - { - if(full) - { + void fixfullrange(float &yaw, float &pitch, float &roll, bool full) { + if(full) { while(pitch < -180.0f) pitch += 360.0f; while(pitch >= 180.0f) pitch -= 360.0f; while(roll < -180.0f) roll += 360.0f; while(roll >= 180.0f) roll -= 360.0f; } - else - { + else { if(pitch > 89.9f) pitch = 89.9f; if(pitch < -89.9f) pitch = -89.9f; if(roll > 89.9f) roll = 89.9f; @@ -922,95 +705,71 @@ namespace ai while(yaw < 0.0f) yaw += 360.0f; while(yaw >= 360.0f) yaw -= 360.0f; } - - void fixrange(float &yaw, float &pitch) - { + void fixrange(float &yaw, float &pitch) { float r = 0.f; fixfullrange(yaw, pitch, r, false); } - - void getyawpitch(const vec &from, const vec &pos, float &yaw, float &pitch) - { + void getyawpitch(const vec &from, const vec &pos, float &yaw, float &pitch) { float dist = from.dist(pos); yaw = -atan2(pos.x-from.x, pos.y-from.y)/RAD; pitch = asin((pos.z-from.z)/dist)/RAD; } - - void scaleyawpitch(float &yaw, float &pitch, float targyaw, float targpitch, float frame, float scale) - { + void scaleyawpitch(float &yaw, float &pitch, float targyaw, float targpitch, float frame, float scale) { if(yaw < targyaw-180.0f) yaw += 360.0f; if(yaw > targyaw+180.0f) yaw -= 360.0f; float offyaw = fabs(targyaw-yaw)*frame, offpitch = fabs(targpitch-pitch)*frame*scale; - if(targyaw > yaw) - { + if(targyaw > yaw) { yaw += offyaw; if(targyaw < yaw) yaw = targyaw; } - else if(targyaw < yaw) - { + else if(targyaw < yaw) { yaw -= offyaw; if(targyaw > yaw) yaw = targyaw; } - if(targpitch > pitch) - { + if(targpitch > pitch) { pitch += offpitch; if(targpitch < pitch) pitch = targpitch; } - else if(targpitch < pitch) - { + else if(targpitch < pitch) { pitch -= offpitch; if(targpitch > pitch) pitch = targpitch; } fixrange(yaw, pitch); } - - bool lockon(fpsent *d, fpsent *e, float maxdist) - { - if(d->gunselect == GUN_FIST && !d->blocked && !d->timeinair) - { + bool lockon(fpsent *d, fpsent *e, float maxdist) { + if(d->gunselect == GUN_FIST && !d->blocked && !d->timeinair) { vec dir = vec(e->o).sub(d->o); float xydist = dir.x*dir.x+dir.y*dir.y, zdist = dir.z*dir.z, mdist = maxdist*maxdist, ddist = d->radius*d->radius+e->radius*e->radius; if(zdist <= ddist && xydist >= ddist+4 && xydist <= mdist+ddist) return true; } return false; } - - int process(fpsent *d, aistate &b) - { + int process(fpsent *d, aistate &b) { int result = 0, stupify = d->skill <= 10+rnd(15) ? rnd(d->skill*1000) : 0, skmod = 101-d->skill; float frame = d->skill <= 100 ? float(lastmillis-d->ai->lastrun)/float(max(skmod,1)*10) : 1; vec dp = d->headpos(); - bool idle = b.idle == 1 || (stupify && stupify <= skmod); d->ai->dontmove = false; - if(idle) - { + if(idle) { d->ai->lastaction = d->ai->lasthunt = lastmillis; d->ai->dontmove = true; d->ai->spot = vec(0, 0, 0); } - else if(hunt(d, b)) - { + else if(hunt(d, b)) { getyawpitch(dp, vec(d->ai->spot).add(vec(0, 0, d->eyeheight)), d->ai->targyaw, d->ai->targpitch); d->ai->lasthunt = lastmillis; } - else - { + else { idle = d->ai->dontmove = true; d->ai->spot = vec(0, 0, 0); } - if(!d->ai->dontmove) jumpto(d, b, d->ai->spot); - fpsent *e = getclient(d->ai->enemy); bool enemyok = e && targetable(d, e); - if(!enemyok || d->skill >= 50) - { + if(!enemyok || d->skill >= 50) { fpsent *f = (fpsent *)intersectclosest(dp, d->ai->target, d); - if(f) - { - if(targetable(d, f)) - { + if(f) { + if(targetable(d, f)) { if(!enemyok) violence(d, b, f, d->gunselect == GUN_FIST ? 1 : 0); enemyok = true; e = f; @@ -1020,8 +779,7 @@ namespace ai else if(!enemyok && target(d, b, d->gunselect == GUN_FIST ? 1 : 0, false, SIGHTMIN)) enemyok = (e = getclient(d->ai->enemy)) != NULL; } - if(enemyok) - { + if(enemyok) { vec ep = getaimpos(d, e); float yaw, pitch; getyawpitch(dp, ep, yaw, pitch); @@ -1029,21 +787,17 @@ namespace ai bool insight = cansee(d, dp, ep), hasseen = d->ai->enemyseen && lastmillis-d->ai->enemyseen <= (d->skill*10)+3000, quick = d->ai->enemyseen && lastmillis-d->ai->enemyseen <= (d->gunselect == GUN_CG ? 300 : skmod)+30; if(insight) d->ai->enemyseen = lastmillis; - if(idle || insight || hasseen || quick) - { + if(idle || insight || hasseen || quick) { float sskew = insight || d->skill > 100 ? 1.5f : (hasseen ? 1.f : 0.5f); - if(insight && lockon(d, e, 16)) - { + if(insight && lockon(d, e, 16)) { d->ai->targyaw = yaw; d->ai->targpitch = pitch; if(!idle) frame *= 2; d->ai->becareful = false; } scaleyawpitch(d->yaw, d->pitch, yaw, pitch, frame, sskew); - if(insight || quick) - { - if(canshoot(d, e) && hastarget(d, b, e, yaw, pitch, dp.squaredist(ep))) - { + if(insight || quick) { + if(canshoot(d, e) && hastarget(d, b, e, yaw, pitch, dp.squaredist(ep))) { d->attacking = true; d->ai->lastaction = lastmillis; result = 3; @@ -1052,10 +806,8 @@ namespace ai } else result = 1; } - else - { - if(!d->ai->enemyseen || lastmillis-d->ai->enemyseen > (d->skill*50)+3000) - { + else { + if(!d->ai->enemyseen || lastmillis-d->ai->enemyseen > (d->skill*50)+3000) { d->ai->enemy = -1; d->ai->enemyseen = d->ai->enemymillis = 0; } @@ -1063,22 +815,17 @@ namespace ai result = 0; } } - else - { - if(!enemyok) - { + else { + if(!enemyok) { d->ai->enemy = -1; d->ai->enemyseen = d->ai->enemymillis = 0; } enemyok = false; result = 0; } - fixrange(d->ai->targyaw, d->ai->targpitch); if(!result) scaleyawpitch(d->yaw, d->pitch, d->ai->targyaw, d->ai->targpitch, frame*0.25f, 1.f); - - if(d->ai->becareful && d->physstate == PHYS_FALL) - { + if(d->ai->becareful && d->physstate == PHYS_FALL) { float offyaw, offpitch; vectoyawpitch(d->vel, offyaw, offpitch); offyaw -= d->yaw; offpitch -= d->pitch; @@ -1086,20 +833,18 @@ namespace ai else if(d->ai->becareful) d->ai->dontmove = true; } else d->ai->becareful = false; - if(d->ai->dontmove) d->move = d->strafe = 0; - else - { // our guys move one way.. but turn another?! :) - const struct aimdir { int move, strafe, offset; } aimdirs[8] = - { + else { + // our guys move one way.. but turn another?! :) + const struct aimdir { int move, strafe, offset; } aimdirs[8] = { { 1, 0, 0 }, - { 1, -1, 45 }, - { 0, -1, 90 }, - { -1, -1, 135 }, + { 1, -1, 45 }, + { 0, -1, 90 }, + { -1, -1, 135 }, { -1, 0, 180 }, - { -1, 1, 225 }, - { 0, 1, 270 }, - { 1, 1, 315 } + { -1, 1, 225 }, + { 0, 1, 270 }, + { 1, 1, 315 } }; float yaw = d->ai->targyaw-d->yaw; while(yaw < 0.0f) yaw += 360.0f; @@ -1112,31 +857,23 @@ namespace ai findorientation(dp, d->yaw, d->pitch, d->ai->target); return result; } - - bool hasrange(fpsent *d, fpsent *e, int weap) - { + bool hasrange(fpsent *d, fpsent *e, int weap) { if(!e) return true; - if(targetable(d, e)) - { + if(targetable(d, e)) { vec ep = getaimpos(d, e); float dist = ep.squaredist(d->headpos()); if(weaprange(d, weap, dist)) return true; } return false; } - - bool request(fpsent *d, aistate &b) - { + bool request(fpsent *d, aistate &b) { fpsent *e = getclient(d->ai->enemy); - if(!d->hasammo(d->gunselect) || !hasrange(d, e, d->gunselect) || (d->gunselect != d->ai->weappref && (!isgoodammo(d->gunselect) || d->hasammo(d->ai->weappref)))) - { + if(!d->hasammo(d->gunselect) || !hasrange(d, e, d->gunselect) || (d->gunselect != d->ai->weappref && (!isgoodammo(d->gunselect) || d->hasammo(d->ai->weappref)))) { static const int gunprefs[] = { GUN_CG, GUN_RL, GUN_SG, GUN_RIFLE, GUN_GL, GUN_PISTOL, GUN_FIST }; int gun = -1; if(d->hasammo(d->ai->weappref) && hasrange(d, e, d->ai->weappref)) gun = d->ai->weappref; - else - { - loopi(sizeof(gunprefs)/sizeof(gunprefs[0])) if(d->hasammo(gunprefs[i]) && hasrange(d, e, gunprefs[i])) - { + else { + loopi(sizeof(gunprefs)/sizeof(gunprefs[0])) if(d->hasammo(gunprefs[i]) && hasrange(d, e, gunprefs[i])) { gun = gunprefs[i]; break; } @@ -1145,17 +882,12 @@ namespace ai } return process(d, b) >= 2; } - - void timeouts(fpsent *d, aistate &b) - { - if(d->blocked) - { + void timeouts(fpsent *d, aistate &b) { + if(d->blocked) { d->ai->blocktime += lastmillis-d->ai->lastrun; - if(d->ai->blocktime > (d->ai->blockseq+1)*1000) - { + if(d->ai->blocktime > (d->ai->blockseq+1)*1000) { d->ai->blockseq++; - switch(d->ai->blockseq) - { + switch(d->ai->blockseq) { case 1: case 2: case 3: if(entities::ents.inrange(d->ai->targnode)) d->ai->addprevnode(d->ai->targnode); d->ai->clear(false); @@ -1167,15 +899,11 @@ namespace ai } } else d->ai->blocktime = d->ai->blockseq = 0; - - if(d->ai->targnode == d->ai->targlast) - { + if(d->ai->targnode == d->ai->targlast) { d->ai->targtime += lastmillis-d->ai->lastrun; - if(d->ai->targtime > (d->ai->targseq+1)*1000) - { + if(d->ai->targtime > (d->ai->targseq+1)*1000) { d->ai->targseq++; - switch(d->ai->targseq) - { + switch(d->ai->targseq) { case 1: case 2: case 3: if(entities::ents.inrange(d->ai->targnode)) d->ai->addprevnode(d->ai->targnode); d->ai->clear(false); @@ -1186,21 +914,16 @@ namespace ai } } } - else - { + else { d->ai->targtime = d->ai->targseq = 0; d->ai->targlast = d->ai->targnode; } - - if(d->ai->lasthunt) - { + if(d->ai->lasthunt) { int millis = lastmillis-d->ai->lasthunt; if(millis <= 1000) { d->ai->tryreset = false; d->ai->huntseq = 0; } - else if(millis > (d->ai->huntseq+1)*1000) - { + else if(millis > (d->ai->huntseq+1)*1000) { d->ai->huntseq++; - switch(d->ai->huntseq) - { + switch(d->ai->huntseq) { case 1: d->ai->reset(true); break; case 2: d->ai->reset(false); break; case 3: default: suicide(d); return; break; // this is our last resort.. @@ -1208,20 +931,15 @@ namespace ai } } } - - void logic(fpsent *d, aistate &b, bool run) - { + void logic(fpsent *d, aistate &b, bool run) { bool allowmove = canmove(d) && b.type != AI_S_WAIT; if(d->state != CS_ALIVE || !allowmove) d->stopmoving(); - if(d->state == CS_ALIVE) - { - if(allowmove) - { + if(d->state == CS_ALIVE) { + if(allowmove) { if(!request(d, b)) target(d, b, d->gunselect == GUN_FIST ? 1 : 0, b.idle ? true : false); shoot(d, d->ai->target); } - if(!intermission) - { + if(!intermission) { if(d->ragdoll) cleanragdoll(d); moveplayer(d, 10, true); if(allowmove && !b.idle) timeouts(d, b); @@ -1229,25 +947,20 @@ namespace ai entities::checkitems(d); } } - else if(d->state == CS_DEAD) - { + else if(d->state == CS_DEAD) { if(d->ragdoll) moveragdoll(d); - else if(lastmillis-d->lastpain<2000) - { + else if(lastmillis-d->lastpain<2000) { d->move = d->strafe = 0; moveplayer(d, 10, false); } } d->attacking = d->jumping = false; } - - void avoid() - { + void avoid() { // guess as to the radius of ai and other critters relying on the avoid set for now float guessradius = player1->radius; obstacles.clear(); - loopv(players) - { + loopv(players) { dynent *d = players[i]; if(d->state != CS_ALIVE) continue; obstacles.avoidnear(d, d->o.z + d->aboveeye + 1, d->feetpos(), guessradius + d->radius); @@ -1256,46 +969,36 @@ namespace ai obstacles.add(wpavoid); avoidweapons(obstacles, guessradius); } - - void think(fpsent *d, bool run) - { + void think(fpsent *d, bool run) { // the state stack works like a chain of commands, certain commands simply replace each other // others spawn new commands to the stack the ai reads the top command from the stack and executes // it or pops the stack and goes back along the history until it finds a suitable command to execute bool cleannext = false; if(d->ai->state.empty()) d->ai->addstate(AI_S_WAIT); - loopvrev(d->ai->state) - { + loopvrev(d->ai->state) { aistate &c = d->ai->state[i]; - if(cleannext) - { + if(cleannext) { c.millis = lastmillis; c.override = false; cleannext = false; } - if(d->state == CS_DEAD && d->respawned!=d->lifesequence && lastmillis - d->lastpain >= 500) - { + if(d->state == CS_DEAD && d->respawned!=d->lifesequence && lastmillis - d->lastpain >= 500) { addmsg(N_TRYSPAWN, "rc", d); d->respawned = d->lifesequence; } - else if(d->state == CS_ALIVE && run) - { + else if(d->state == CS_ALIVE && run) { int result = 0; c.idle = 0; - switch(c.type) - { + switch(c.type) { case AI_S_WAIT: result = dowait(d, c); break; case AI_S_DEFEND: result = dodefend(d, c); break; case AI_S_PURSUE: result = dopursue(d, c); break; case AI_S_INTEREST: result = dointerest(d, c); break; default: result = 0; break; } - if(result <= 0) - { - if(c.type != AI_S_WAIT) - { - switch(result) - { + if(result <= 0) { + if(c.type != AI_S_WAIT) { + switch(result) { case 0: default: d->ai->removestate(i); cleannext = true; break; case -1: i = d->ai->state.length()-1; break; } @@ -1309,17 +1012,12 @@ namespace ai if(d->ai->trywipe) d->ai->wipe(); d->ai->lastrun = lastmillis; } - - void drawroute(fpsent *d, float amt = 1.f) - { + void drawroute(fpsent *d, float amt = 1.f) { int last = -1; - loopvrev(d->ai->route) - { - if(d->ai->route.inrange(last)) - { + loopvrev(d->ai->route) { + if(d->ai->route.inrange(last)) { int index = d->ai->route[i], prev = d->ai->route[last]; - if(iswaypoint(index) && iswaypoint(prev)) - { + if(iswaypoint(index) && iswaypoint(prev)) { waypoint &e = waypoints[index], &f = waypoints[prev]; vec fr = f.o, dr = e.o; fr.z += amt; dr.z += amt; @@ -1328,45 +1026,22 @@ namespace ai } last = i; } - if(aidebug >= 5) - { - vec pos = d->feetpos(); - if(d->ai->spot != vec(0, 0, 0)) particle_flare(pos, d->ai->spot, 1, PART_LIGHTNING, 0x00FFFF); - if(iswaypoint(d->ai->targnode)) - particle_flare(pos, waypoints[d->ai->targnode].o, 1, PART_LIGHTNING, 0xFF00FF); - if(iswaypoint(d->lastnode)) - particle_flare(pos, waypoints[d->lastnode].o, 1, PART_LIGHTNING, 0xFFFF00); - loopi(NUMPREVNODES) if(iswaypoint(d->ai->prevnodes[i])) - { - particle_flare(pos, waypoints[d->ai->prevnodes[i]].o, 1, PART_LIGHTNING, 0x884400); - pos = waypoints[d->ai->prevnodes[i]].o; - } - } } - VAR(showwaypoints, 0, 0, 1); VAR(showwaypointsradius, 0, 200, 10000); - - const char *stnames[AI_S_MAX] = { - "wait", "defend", "pursue", "interest" - }, *sttypes[AI_T_MAX+1] = { - "none", "node", "player", "affinity", "entity" - }; - void render() - { - if(aidebug > 1) - { + const char *stnames[AI_S_MAX] = { "wait", "defend", "pursue", "interest" }, + *sttypes[AI_T_MAX+1] = { "none", "node", "player", "affinity", "entity" }; + void render() { + if(aidebug > 1) { int total = 0, alive = 0; loopv(players) if(players[i]->ai) total++; - loopv(players) if(players[i]->state == CS_ALIVE && players[i]->ai) - { + loopv(players) if(players[i]->state == CS_ALIVE && players[i]->ai) { fpsent *d = players[i]; vec pos = d->abovehead(); pos.z += 3; alive++; if(aidebug >= 4) drawroute(d, 4.f*(float(alive)/float(total))); - if(aidebug >= 3) - { + if(aidebug >= 3) { defformatstring(q, "node: %d route: %d (%d)", d->lastnode, !d->ai->route.empty() ? d->ai->route[0] : -1, @@ -1376,8 +1051,7 @@ namespace ai pos.z += 2; } bool top = true; - loopvrev(d->ai->state) - { + loopvrev(d->ai->state) { aistate &b = d->ai->state[i]; defformatstring(s, "%s%s (%d ms) %s:%d", top ? "\fg" : "\fy", @@ -1387,36 +1061,29 @@ namespace ai ); particle_textcopy(pos, s, PART_TEXT, 1); pos.z += 2; - if(top) - { + if(top) { if(aidebug >= 3) top = false; else break; } } - if(aidebug >= 3) - { - if(d->ai->weappref >= 0 && d->ai->weappref < NUMGUNS) - { + if(aidebug >= 3) { + if(d->ai->weappref >= 0 && d->ai->weappref < NUMGUNS) { particle_textcopy(pos, guns[d->ai->weappref].name, PART_TEXT, 1); pos.z += 2; } fpsent *e = getclient(d->ai->enemy); - if(e) - { + if(e) { particle_textcopy(pos, colorname(e), PART_TEXT, 1); pos.z += 2; } } } - if(aidebug >= 4) - { + if(aidebug >= 4) { int cur = 0; - loopv(obstacles.obstacles) - { + loopv(obstacles.obstacles) { const avoidset::obstacle &ob = obstacles.obstacles[i]; int next = cur + ob.numwaypoints; - for(; cur < next; cur++) - { + for(; cur < next; cur++) { int ent = obstacles.waypoints[cur]; if(iswaypoint(ent)) regular_particle_splash(PART_EDIT, 2, 40, waypoints[ent].o, 0xFF6600, 1.5f); @@ -1425,26 +1092,21 @@ namespace ai } } } - if(showwaypoints || aidebug >= 6) - { + if(showwaypoints || aidebug >= 6) { vector close; int len = waypoints.length(); - if(showwaypointsradius) - { + if(showwaypointsradius) { findwaypointswithin(camera1->o, 0, showwaypointsradius, close); len = close.length(); } - loopi(len) - { + loopi(len) { waypoint &w = waypoints[showwaypointsradius ? close[i] : i]; - loopj(MAXWAYPOINTLINKS) - { + loopj(MAXWAYPOINTLINKS) { int link = w.links[j]; if(!link) break; particle_flare(w.o, waypoints[link].o, 1, PART_STREAK, 0x0000FF); } } - } } } diff --git a/src/fpsgame/ai.h b/src/fpsgame/ai.h index 9ea7e41..b6db1fc 100644 --- a/src/fpsgame/ai.h +++ b/src/fpsgame/ai.h @@ -5,12 +5,10 @@ struct fpsent; enum { AI_NONE = 0, AI_BOT, AI_MAX }; #define isaitype(a) (a >= 0 && a <= AI_MAX-1) -namespace ai -{ +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 @@ -20,97 +18,71 @@ namespace ai 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 - { + 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) - { + int find(int wp) { loopi(MAXWAYPOINTLINKS) if(links[i] == wp) return i; return -1; } - bool haslinks() { return links[0]!=0; } }; extern vector waypoints; - - static inline bool iswaypoint(int n) - { + 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, fpsent *d = NULL); + extern int closestwaypoint(const vec &pos, float mindist, bool links); extern void findwaypointswithin(const vec &pos, float mindist, float maxdist, vector &results); extern void inferwaypoints(fpsent *d, const vec &o, const vec &v, float mindist = ai::CLOSEDIST); - - struct avoidset - { - struct obstacle - { + struct avoidset { + struct obstacle { void *owner; int numwaypoints; float above; - obstacle(void *owner, float above = -1) : owner(owner), numwaypoints(0), above(above) {} }; - vector obstacles; vector waypoints; - - void clear() - { + void clear() { obstacles.setsize(0); waypoints.setsize(0); } - - void add(void *owner, float above) - { + void add(void *owner, float above) { obstacles.add(obstacle(owner, above)); } - - void add(void *owner, float above, int wp) - { + 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) - { + void add(avoidset &avoid) { waypoints.put(avoid.waypoints.getbuf(), avoid.waypoints.length()); - loopv(avoid.obstacles) - { + 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()) \ - { \ + if(!(v).obstacles.empty()) { \ + \ int cur = 0; \ - loopv((v).obstacles) \ - { \ + loopv((v).obstacles) { \ + \ const ai::avoidset::obstacle &ob = (v).obstacles[i]; \ int next = cur + ob.numwaypoints; \ - if(ob.owner != d) \ - { \ - for(; cur < next; cur++) \ - { \ + if(ob.owner != d) { \ + \ + for(; cur < next; cur++) { \ + \ int wp = (v).waypoints[cur]; \ body; \ } \ @@ -118,72 +90,53 @@ namespace ai cur = next; \ } \ } - - bool find(int n, fpsent *d) const - { + bool find(int n, fpsent *d) const { loopavoid(*this, d, { if(wp == n) return true; }); return false; } - int remap(fpsent *d, int n, vec &pos, bool retry = false); }; - extern bool route(fpsent *d, int node, int goal, vector &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 - { + 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 - { + enum { AI_T_NODE, AI_T_PLAYER, AI_T_AFFINITY, AI_T_ENTITY, AI_T_MAX }; - - struct interest - { + struct interest { int state, node, target, targtype; float score; interest() : state(-1), node(-1), target(-1), targtype(-1), score(0.f) {} ~interest() {} }; - - struct aistate - { + 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) - { + aistate(int m, int t, int r = -1, int v = -1) : type(t), millis(m), targtype(r), target(v) { reset(); } ~aistate() {} - - void reset() - { + void reset() { idle = 0; override = false; } }; - const int NUMPREVNODES = 6; - - struct aiinfo - { + struct aiinfo { vector state; vector route; vec target, spot; @@ -191,17 +144,13 @@ namespace ai lastrun, lasthunt, lastaction, lastcheck, jumpseed, jumprand, blocktime, huntseq, blockseq, lastaimrnd; float targyaw, targpitch, views[3], aimrnd[3]; bool dontmove, becareful, tryreset, trywipe; - - aiinfo() - { + aiinfo() { clearsetup(); reset(); loopk(3) views[k] = 0.f; } ~aiinfo() {} - - void clearsetup() - { + void clearsetup() { weappref = GUN_PISTOL; spot = target = vec(0, 0, 0); lastaction = lasthunt = lastcheck = enemyseen = enemymillis = blocktime = huntseq = blockseq = targtime = targseq = lastaimrnd = 0; @@ -209,68 +158,47 @@ namespace ai jumprand = lastmillis+5000; targnode = targlast = enemy = -1; } - - void clear(bool prev = false) - { + void clear(bool prev = false) { if(prev) memset(prevnodes, -1, sizeof(prevnodes)); route.setsize(0); } - - void wipe(bool prev = false) - { + void wipe(bool prev = false) { clear(prev); state.setsize(0); addstate(AI_S_WAIT); trywipe = false; } - - void clean(bool tryit = 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 - { + bool hasprevnode(int n) const { loopi(NUMPREVNODES) if(prevnodes[i] == n) return true; return false; } - - void addprevnode(int n) - { - if(prevnodes[0] != n) - { + 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) - { + aistate &addstate(int t, int r = -1, int v = -1) { return state.add(aistate(lastmillis, t, r, v)); } - - void removestate(int index = -1) - { + 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) - { + 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)) - { + 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(); @@ -279,21 +207,17 @@ namespace ai 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(fpsent *d, fpsent *e); extern bool cansee(fpsent *d, vec &x, vec &y, vec &targ = aitarget); - extern void init(fpsent *d, int at, int on, int sk, int bn, int pm, const char *name, const char *team); extern void update(); extern void avoid(); extern void think(fpsent *d, bool run); - extern bool badhealth(fpsent *d); extern bool checkothers(vector &targets, fpsent *d = NULL, int state = -1, int targtype = -1, int target = -1, bool teams = false, int *members = NULL); extern bool makeroute(fpsent *d, aistate &b, int node, bool changed = true, int retries = 0); @@ -305,12 +229,10 @@ namespace ai extern bool defend(fpsent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, float wander = SIGHTMAX, int walk = 1); extern void assist(fpsent *d, aistate &b, vector &interests, bool all = false, bool force = false); extern bool parseinterests(fpsent *d, aistate &b, vector &interests, bool override = false, bool ignore = false); - extern void spawned(fpsent *d); extern void damaged(fpsent *d, fpsent *e); extern void killed(fpsent *d, fpsent *e); extern void itemspawned(int ent); - extern void render(); } diff --git a/src/fpsgame/aiman.h b/src/fpsgame/aiman.h index 940f13e..f926d44 100644 --- a/src/fpsgame/aiman.h +++ b/src/fpsgame/aiman.h @@ -1,15 +1,11 @@ // server-side ai manager -namespace aiman -{ +namespace aiman { bool dorefresh = false, botbalance = true; VARN(serverbotlimit, botlimit, 0, 8, MAXBOTS); VAR(serverbotbalance, 0, 1, 1); - - void calcteams(vector &teams) - { + void calcteams(vector &teams) { static const char * const defaults[2] = { "good", "evil" }; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; teamscore *t = NULL; @@ -18,83 +14,64 @@ namespace aiman else teams.add(teamscore(ci->team, 1)); } teams.sort(teamscore::compare); - if(teams.length() < int(sizeof(defaults)/sizeof(defaults[0]))) - { + 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() - { + void balanceteams() { vector teams; calcteams(teams); vector reassign; loopv(bots) if(bots[i]) reassign.add(bots[i]); - while(reassign.length() && teams.length() && teams[0].score > teams.last().score + 1) - { + 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)) - { + 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--) - { + 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(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() - { + const char *chooseteam() { vector teams; calcteams(teams); return teams.length() ? teams.last().team : ""; } - - static inline bool validaiclient(clientinfo *ci) - { + 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 *findaiclient(clientinfo *exclude = NULL) { clientinfo *least = NULL; - loopv(clients) - { + 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) - { + bool addai(int skill, int limit) { int numai = 0, cn = -1, maxai = limit >= 0 ? min(limit, MAXBOTS) : MAXBOTS; - loopv(bots) - { + 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)) - { + if(bots.inrange(cn)) { clientinfo *ci = bots[cn]; - if(ci) - { // reuse a slot that was going to removed - + 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); @@ -124,9 +101,7 @@ namespace aiman dorefresh = true; return true; } - - void deleteai(clientinfo *ci) - { + void deleteai(clientinfo *ci) { int cn = ci->clientnum - MAXCLIENTS; if(!bots.inrange(cn)) return; sendf(-1, 1, "ri2", N_CDIS, ci->clientnum); @@ -136,25 +111,18 @@ namespace aiman DELETEP(bots[cn]); dorefresh = true; } - - bool deleteai() - { - loopvrev(bots) if(bots[i] && bots[i]->ownernum >= 0) - { + bool deleteai() { + loopvrev(bots) if(bots[i] && bots[i]->ownernum >= 0) { deleteai(bots[i]); return true; } return false; } - - void reinitai(clientinfo *ci) - { + void reinitai(clientinfo *ci) { if(ci->ownernum < 0) deleteai(ci); - else if(ci->aireinit >= 1) - { + 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) - { + if(ci->aireinit == 2) { ci->reassign(); if(ci->state.state==CS_ALIVE) sendspawn(ci); else sendresume(ci); @@ -162,36 +130,27 @@ namespace aiman ci->aireinit = 0; } } - - void shiftai(clientinfo *ci, clientinfo *owner = NULL) - { + 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 - + 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() - { + bool reassignai() { clientinfo *hi = NULL, *lo = NULL; - loopv(clients) - { + 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) - { + if(hi && lo && hi->bots.length() - lo->bots.length() > 1) { + loopvrev(hi->bots) { shiftai(hi->bots[i], lo); return true; } @@ -199,53 +158,39 @@ namespace aiman return false; } - - void checksetup() - { + void checksetup() { if(m_teammode && botbalance) balanceteams(); loopvrev(bots) if(bots[i]) reinitai(bots[i]); } - - void clearai() - { // clear and remove all ai immediately + void clearai() { + // clear and remove all ai immediately loopvrev(bots) if(bots[i]) deleteai(bots[i]); } - - void checkai() - { + void checkai() { if(!dorefresh) return; dorefresh = false; - if(m_botmode && numclients(-1, false, true)) - { + if(m_botmode && numclients(-1, false, true)) { checksetup(); while(reassignai()); } else clearai(); } - - void reqadd(clientinfo *ci, int skill) - { + 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) - { + 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) - { + 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) - { + void setbotbalance(clientinfo *ci, bool balance) { if(ci && !ci->local && !ci->privilege) return; botbalance = balance ? 1 : 0; dorefresh = true; @@ -253,21 +198,15 @@ namespace aiman sendservmsg(msg); } - - void changemap() - { + 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) - { + void addclient(clientinfo *ci) { if(ci->state.aitype == AI_NONE) dorefresh = true; } - - void changeteam(clientinfo *ci) - { + 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 7155c00..2ad6a6f 100644 --- a/src/fpsgame/client.cpp +++ b/src/fpsgame/client.cpp @@ -1,98 +1,71 @@ #include "game.h" -namespace game -{ +namespace game { bool senditemstoserver = false, sendcrc = false; // after a map change, since server doesn't have map data int lastping = 0; - bool connected = false, remote = false, demoplayback = false, gamepaused = false; int sessionid = 0, mastermode = MM_OPEN, gamespeed = 100; string servinfo = "", servauth = "", connectpass = ""; - VARP(deadpush, 1, 2, 20); - - void switchname(const char *name) - { + void switchname(const char *name) { filtertext(player1->name, name, false, false, MAXNAMELEN); if(!player1->name[0]) copystring(player1->name, "Anonymous"); addmsg(N_SWITCHNAME, "rs", player1->name); } - void printname() - { + void printname() { conoutf("your name is: %s", colorname(player1)); } - ICOMMAND(name, "sN", (char *s, int *numargs), - { + ICOMMAND(name, "sN", (char *s, int *numargs), { if(*numargs > 0) switchname(s); else if(!*numargs) printname(); else result(colorname(player1)); }); ICOMMAND(getname, "", (), result(player1->name)); - - void switchteam(const char *team) - { + void switchteam(const char *team) { if(player1->clientnum < 0) filtertext(player1->team, team, false, false, MAXTEAMLEN); else addmsg(N_SWITCHTEAM, "rs", team); } - void printteam() - { + void printteam() { conoutf("your team is: %s", player1->team); } - ICOMMAND(team, "sN", (char *s, int *numargs), - { + ICOMMAND(team, "sN", (char *s, int *numargs), { if(*numargs > 0) switchteam(s); else if(!*numargs) printteam(); else result(player1->team); }); ICOMMAND(getteam, "", (), result(player1->team)); - - struct authkey - { + struct authkey { char *name, *key, *desc; int lastauth; - authkey(const char *name, const char *key, const char *desc) : name(newstring(name)), key(newstring(key)), desc(newstring(desc)), - lastauth(0) - { + lastauth(0) { } - - ~authkey() - { + ~authkey() { DELETEA(name); DELETEA(key); DELETEA(desc); } }; vector authkeys; - - authkey *findauthkey(const char *desc = "") - { + authkey *findauthkey(const char *desc = "") { loopv(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcasecmp(authkeys[i]->name, player1->name)) return authkeys[i]; loopv(authkeys) if(!strcmp(authkeys[i]->desc, desc)) return authkeys[i]; return NULL; } - VARP(autoauth, 0, 1, 1); - - void addauthkey(const char *name, const char *key, const char *desc) - { + void addauthkey(const char *name, const char *key, const char *desc) { loopvrev(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcmp(authkeys[i]->name, name)) delete authkeys.remove(i); if(name[0] && key[0]) authkeys.add(new authkey(name, key, desc)); } ICOMMAND(authkey, "sss", (char *name, char *key, char *desc), addauthkey(name, key, desc)); - - bool hasauthkey(const char *name, const char *desc) - { + bool hasauthkey(const char *name, const char *desc) { if(!name[0] && !desc[0]) return authkeys.length() > 0; loopvrev(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcmp(authkeys[i]->name, name)) return true; return false; } - ICOMMAND(hasauthkey, "ss", (char *name, char *desc), intret(hasauthkey(name, desc) ? 1 : 0)); - - void genauthkey(const char *secret) - { + void genauthkey(const char *secret) { if(!secret[0]) { conoutf(CON_ERROR, "you must specify a secret password"); return; } vector privkey, pubkey; genprivkey(secret, privkey, pubkey); @@ -101,9 +74,7 @@ namespace game result(privkey.getbuf()); } COMMAND(genauthkey, "s"); - - void getpubkey(const char *desc) - { + void getpubkey(const char *desc) { authkey *k = findauthkey(desc); if(!k) { if(desc[0]) conoutf(CON_ERROR, "no authkey found: %s", desc); else conoutf(CON_ERROR, "no global authkey found"); return; } vector pubkey; @@ -111,13 +82,10 @@ namespace game result(pubkey.getbuf()); } COMMAND(getpubkey, "s"); - - void saveauthkeys() - { + void saveauthkeys() { stream *f = openfile("auth.cfg", "w"); if(!f) { conoutf(CON_ERROR, "failed to open auth.cfg for writing"); return; } - loopv(authkeys) - { + loopv(authkeys) { authkey *a = authkeys[i]; f->printf("authkey %s %s %s\n", escapestring(a->name), escapestring(a->key), escapestring(a->desc)); } @@ -125,139 +93,104 @@ namespace game delete f; } COMMAND(saveauthkeys, ""); - - void sendmapinfo() - { + void sendmapinfo() { if(!connected) return; sendcrc = true; if(player1->state!=CS_SPECTATOR || player1->privilege || !remote) senditemstoserver = true; } - - void writeclientinfo(stream *f) - { + void writeclientinfo(stream *f) { f->printf("name %s\n", escapestring(player1->name)); } - - bool allowedittoggle() - { + bool allowedittoggle() { if(editmode) return true; - if(isconnected() && multiplayer(false) && !m_edit) - { + if(isconnected() && multiplayer(false) && !m_edit) { conoutf(CON_ERROR, "editing in multiplayer requires coop edit mode (1)"); return false; } return execidentbool("allowedittoggle", true); } - - void edittoggled(bool on) - { + void edittoggled(bool on) { addmsg(N_EDITMODE, "ri", on ? 1 : 0); if(player1->state==CS_DEAD) deathstate(player1, true); else if(player1->state==CS_EDITING && player1->editstate==CS_DEAD) showscores(false); disablezoom(); player1->suicided = player1->respawned = -2; } - - const char *getclientname(int cn) - { + const char *getclientname(int cn) { fpsent *d = getclient(cn); return d ? d->name : ""; } ICOMMAND(getclientname, "i", (int *cn), result(getclientname(*cn))); - - const char *getclientteam(int cn) - { + const char *getclientteam(int cn) { fpsent *d = getclient(cn); return d ? d->team : ""; } ICOMMAND(getclientteam, "i", (int *cn), result(getclientteam(*cn))); - - const char *getclienticon(int cn) - { + const char *getclienticon(int cn) { fpsent *d = getclient(cn); if(!d || d->state==CS_SPECTATOR) return "spectator"; const playermodelinfo &mdl = getplayermodelinfo(d); return m_teammode ? (isteam(player1->team, d->team) ? mdl.blueicon : mdl.redicon) : mdl.ffaicon; } ICOMMAND(getclienticon, "i", (int *cn), result(getclienticon(*cn))); - - bool ismaster(int cn) - { + bool ismaster(int cn) { fpsent *d = getclient(cn); return d && d->privilege >= PRIV_MASTER; } ICOMMAND(ismaster, "i", (int *cn), intret(ismaster(*cn) ? 1 : 0)); - - bool isauth(int cn) - { + bool isauth(int cn) { fpsent *d = getclient(cn); return d && d->privilege >= PRIV_AUTH; } ICOMMAND(isauth, "i", (int *cn), intret(isauth(*cn) ? 1 : 0)); - - bool isadmin(int cn) - { + bool isadmin(int cn) { fpsent *d = getclient(cn); return d && d->privilege >= PRIV_ADMIN; } ICOMMAND(isadmin, "i", (int *cn), intret(isadmin(*cn) ? 1 : 0)); - ICOMMAND(getmastermode, "", (), intret(mastermode)); ICOMMAND(mastermodename, "i", (int *mm), result(server::mastermodename(*mm, ""))); - - bool isspectator(int cn) - { + bool isspectator(int cn) { fpsent *d = getclient(cn); return d && d->state==CS_SPECTATOR; } ICOMMAND(isspectator, "i", (int *cn), intret(isspectator(*cn) ? 1 : 0)); - - bool isai(int cn, int type) - { + bool isai(int cn, int type) { fpsent *d = getclient(cn); int aitype = type > 0 && type < AI_MAX ? type : AI_BOT; return d && d->aitype==aitype; } ICOMMAND(isai, "ii", (int *cn, int *type), intret(isai(*cn, *type) ? 1 : 0)); - - int parseplayer(const char *arg) - { + int parseplayer(const char *arg) { char *end; int n = strtol(arg, &end, 10); - if(*arg && !*end) - { + if(*arg && !*end) { if(n!=player1->clientnum && !clients.inrange(n)) return -1; return n; } // try case sensitive first - loopv(players) - { + loopv(players) { fpsent *o = players[i]; if(!strcmp(arg, o->name)) return o->clientnum; } // nothing found, try case insensitive - loopv(players) - { + loopv(players) { fpsent *o = players[i]; if(!strcasecmp(arg, o->name)) return o->clientnum; } return -1; } ICOMMAND(getclientnum, "s", (char *name), intret(name[0] ? parseplayer(name) : player1->clientnum)); - - void listclients(bool local, bool bots) - { + void listclients(bool local, bool bots) { vector buf; string cn; int numclients = 0; - if(local && connected) - { + if(local && connected) { formatstring(cn, "%d", player1->clientnum); buf.put(cn, strlen(cn)); numclients++; } - loopv(clients) if(clients[i] && (bots || clients[i]->aitype == AI_NONE)) - { + loopv(clients) if(clients[i] && (bots || clients[i]->aitype == AI_NONE)) { formatstring(cn, "%d", clients[i]->clientnum); if(numclients++) buf.add(' '); buf.put(cn, strlen(cn)); @@ -266,26 +199,19 @@ namespace game result(buf.getbuf()); } ICOMMAND(listclients, "bb", (int *local, int *bots), listclients(*local>0, *bots!=0)); - - void clearbans() - { + void clearbans() { addmsg(N_CLEARBANS, "r"); } COMMAND(clearbans, ""); - - void kick(const char *victim, const char *reason) - { + void kick(const char *victim, const char *reason) { int vn = parseplayer(victim); if(vn>=0 && vn!=player1->clientnum) addmsg(N_KICK, "ris", vn, reason); } COMMAND(kick, "ss"); - - void authkick(const char *desc, const char *victim, const char *reason) - { + void authkick(const char *desc, const char *victim, const char *reason) { authkey *a = findauthkey(desc); int vn = parseplayer(victim); - if(a && vn>=0 && vn!=player1->clientnum) - { + if(a && vn>=0 && vn!=player1->clientnum) { a->lastauth = lastmillis; addmsg(N_AUTHKICK, "rssis", a->desc, a->name, vn, reason); } @@ -293,60 +219,45 @@ namespace game ICOMMAND(authkick, "ss", (const char *victim, const char *reason), authkick("", victim, reason)); ICOMMAND(sauthkick, "ss", (const char *victim, const char *reason), if(servauth[0]) authkick(servauth, victim, reason)); ICOMMAND(dauthkick, "sss", (const char *desc, const char *victim, const char *reason), if(desc[0]) authkick(desc, victim, reason)); - vector ignores; - - void ignore(int cn) - { + void ignore(int cn) { fpsent *d = getclient(cn); if(!d || d == player1) return; conoutf("ignoring %s", d->name); if(ignores.find(cn) < 0) ignores.add(cn); } - - void unignore(int cn) - { + void unignore(int cn) { if(ignores.find(cn) < 0) return; fpsent *d = getclient(cn); if(d) conoutf("stopped ignoring %s", d->name); ignores.removeobj(cn); } - bool isignored(int cn) { return ignores.find(cn) >= 0; } - ICOMMAND(ignore, "s", (char *arg), ignore(parseplayer(arg))); ICOMMAND(unignore, "s", (char *arg), unignore(parseplayer(arg))); ICOMMAND(isignored, "s", (char *arg), intret(isignored(parseplayer(arg)) ? 1 : 0)); - - void setteam(const char *arg1, const char *arg2) - { + void setteam(const char *arg1, const char *arg2) { int i = parseplayer(arg1); if(i>=0) addmsg(N_SETTEAM, "ris", i, arg2); } COMMAND(setteam, "ss"); - - void hashpwd(const char *pwd) - { + void hashpwd(const char *pwd) { if(player1->clientnum<0) return; string hash; server::hashpassword(player1->clientnum, sessionid, pwd, hash); result(hash); } COMMAND(hashpwd, "s"); - - void setmaster(const char *arg, const char *who) - { + void setmaster(const char *arg, const char *who) { if(!arg[0]) return; int val = 1, cn = player1->clientnum; - if(who[0]) - { + if(who[0]) { cn = parseplayer(who); if(cn < 0) return; } string hash = ""; if(!arg[1] && isdigit(arg[0])) val = parseint(arg); - else - { + else { if(cn != player1->clientnum) return; server::hashpassword(player1->clientnum, sessionid, arg, hash); } @@ -354,9 +265,7 @@ namespace game } COMMAND(setmaster, "ss"); ICOMMAND(mastermode, "i", (int *val), addmsg(N_MASTERMODE, "ri", *val)); - - bool tryauth(const char *desc) - { + bool tryauth(const char *desc) { authkey *a = findauthkey(desc); if(!a) return false; a->lastauth = lastmillis; @@ -366,45 +275,32 @@ namespace game ICOMMAND(auth, "s", (char *desc), tryauth(desc)); ICOMMAND(sauth, "", (), if(servauth[0]) tryauth(servauth)); ICOMMAND(dauth, "s", (char *desc), if(desc[0]) tryauth(desc)); - ICOMMAND(getservauth, "", (), result(servauth)); - - void togglespectator(int val, const char *who) - { + void togglespectator(int val, const char *who) { int i = who[0] ? parseplayer(who) : player1->clientnum; 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 - { - if(multiplayer(false) && !m_mp(mode)) - { + void changemapserv(const char *name, int mode) { // forced map change from the server { + if(multiplayer(false) && !m_mp(mode)) { conoutf(CON_ERROR, "mode %s (%d) not supported in multiplayer", server::modename(gamemode), gamemode); loopi(NUMGAMEMODES) if(m_mp(STARTGAMEMODE + i)) { mode = STARTGAMEMODE + i; break; } } - gamemode = mode; nextmode = mode; if(editmode) toggleedit(); if(m_demo) { entities::resetspawns(); return; } - if((m_edit && !name[0]) || !load_world(name)) - { + if((m_edit && !name[0]) || !load_world(name)) { emptymap(0, true, name); senditemstoserver = false; } startgame(); } - - void setmode(int mode) - { - if(multiplayer(false) && !m_mp(mode)) - { + void setmode(int mode) { + if(multiplayer(false) && !m_mp(mode)) { conoutf(CON_ERROR, "mode %s (%d) not supported in multiplayer", server::modename(mode), mode); intret(0); return; @@ -414,11 +310,9 @@ namespace game } ICOMMAND(mode, "i", (int *val), setmode(*val)); ICOMMAND(getmode, "", (), intret(gamemode)); - ICOMMAND(timeremaining, "i", (int *formatted), - { + ICOMMAND(timeremaining, "i", (int *formatted), { int val = max(maplimit - lastmillis + 999, 0)/1000; - if(*formatted) - { + if(*formatted) { defformatstring(str, "%d:%02d", val/60, val%60); result(str); } @@ -432,46 +326,32 @@ namespace game ICOMMANDS("m_demo", "i", (int *mode), { int gamemode = *mode; intret(m_demo); }); ICOMMANDS("m_edit", "i", (int *mode), { int gamemode = *mode; intret(m_edit); }); ICOMMANDS("m_lobby", "i", (int *mode), { int gamemode = *mode; intret(m_lobby); }); - - void changemap(const char *name, int mode) // request map change, server may ignore - { - if(!remote) - { + void changemap(const char *name, int mode) { // request map change, server may ignore { + if(!remote) { server::forcemap(name, mode); if(!isconnected()) localconnect(); } else if(player1->state!=CS_SPECTATOR || player1->privilege) addmsg(N_MAPVOTE, "rsi", name, mode); } - void changemap(const char *name) - { + void changemap(const char *name) { changemap(name, m_valid(nextmode) ? nextmode : (remote ? 0 : 1)); } ICOMMAND(map, "s", (char *name), changemap(name)); - - void forceintermission() - { + void forceintermission() { if(!remote && !hasnonlocalclients()) server::startintermission(); else addmsg(N_FORCEINTERMISSION, "r"); } - - void forceedit(const char *name) - { + void forceedit(const char *name) { changemap(name, 1); } - - void newmap(int size) - { + void newmap(int size) { addmsg(N_NEWMAP, "ri", size); } - int needclipboard = -1; - - void sendclipboard() - { + void sendclipboard() { uchar *outbuf = NULL; int inlen = 0, outlen = 0; - if(!packeditinfo(localedit, inlen, outbuf, outlen)) - { + if(!packeditinfo(localedit, inlen, outbuf, outlen)) { outbuf = NULL; inlen = outlen = 0; } @@ -483,22 +363,16 @@ namespace game sendclientpacket(p.finalize(), 1); needclipboard = -1; } - - void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs) - { - if(m_edit) switch(op) - { + void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs) { + if(m_edit) switch(op) { case EDIT_FLIP: case EDIT_COPY: case EDIT_PASTE: - case EDIT_DELCUBE: - { - switch(op) - { + case EDIT_DELCUBE: { + switch(op) { case EDIT_COPY: needclipboard = 0; break; case EDIT_PASTE: - if(needclipboard > 0) - { + if(needclipboard > 0) { c2sinfo(true); sendclipboard(); } @@ -509,8 +383,7 @@ namespace game sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner); break; } - case EDIT_ROTATE: - { + case EDIT_ROTATE: { addmsg(N_EDITF + op, "ri9i5", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, @@ -518,22 +391,19 @@ namespace game break; } case EDIT_MAT: - case EDIT_FACE: - { + case EDIT_FACE: { addmsg(N_EDITF + op, "ri9i6", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, arg1, arg2); break; } - case EDIT_TEX: - { + case EDIT_TEX: { int tex1 = shouldpacktex(arg1); if(addmsg(N_EDITF + op, "ri9i6", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, - tex1 ? tex1 : arg1, arg2)) - { + tex1 ? tex1 : arg1, arg2)) { messages.pad(2); int offset = messages.length(); if(tex1) packvslot(messages, arg1); @@ -541,14 +411,12 @@ namespace game } break; } - case EDIT_REPLACE: - { + case EDIT_REPLACE: { int tex1 = shouldpacktex(arg1), tex2 = shouldpacktex(arg2); if(addmsg(N_EDITF + op, "ri9i7", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, - tex1 ? tex1 : arg1, tex2 ? tex2 : arg2, arg3)) - { + tex1 ? tex1 : arg1, tex2 ? tex2 : arg2, arg3)) { messages.pad(2); int offset = messages.length(); if(tex1) packvslot(messages, arg1); @@ -557,18 +425,15 @@ namespace game } break; } - case EDIT_REMIP: - { + case EDIT_REMIP: { addmsg(N_EDITF + op, "r"); break; } - case EDIT_VSLOT: - { + case EDIT_VSLOT: { if(addmsg(N_EDITF + op, "ri9i6", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, - arg1, arg2)) - { + arg1, arg2)) { messages.pad(2); int offset = messages.length(); packvslot(messages, vs); @@ -577,12 +442,10 @@ namespace game break; } case EDIT_UNDO: - case EDIT_REDO: - { + case EDIT_REDO: { uchar *outbuf = NULL; int inlen = 0, outlen = 0; - if(packundo(op, inlen, outbuf, outlen)) - { + if(packundo(op, inlen, outbuf, outlen)) { if(addmsg(N_EDITF + op, "ri2", inlen, outlen)) messages.put(outbuf, outlen); delete[] outbuf; } @@ -590,13 +453,9 @@ namespace game } } } - - void printvar(fpsent *d, ident *id) - { - if(id) switch(id->type) - { - case ID_VAR: - { + void printvar(fpsent *d, ident *id) { + if(id) switch(id->type) { + case ID_VAR: { int val = *id->storage.i; string str; if(val < 0) @@ -616,20 +475,15 @@ namespace game break; } } - - void vartrigger(ident *id) - { + void vartrigger(ident *id) { if(!m_edit) return; - switch(id->type) - { + switch(id->type) { case ID_VAR: addmsg(N_EDITVAR, "risi", ID_VAR, id->name, *id->storage.i); break; - case ID_FVAR: addmsg(N_EDITVAR, "risf", ID_FVAR, id->name, *id->storage.f); break; - case ID_SVAR: addmsg(N_EDITVAR, "riss", ID_SVAR, id->name, *id->storage.s); break; @@ -637,83 +491,64 @@ namespace game } printvar(player1, id); } - - void pausegame(bool val) - { + void pausegame(bool val) { if(!connected) return; if(!remote) server::forcepaused(val); else addmsg(N_PAUSEGAME, "ri", val ? 1 : 0); } ICOMMAND(pausegame, "i", (int *val), pausegame(*val > 0)); - ICOMMAND(paused, "iN$", (int *val, int *numargs, ident *id), - { + ICOMMAND(paused, "iN$", (int *val, int *numargs, ident *id), { if(*numargs > 0) pausegame(clampvar(id, *val, 0, 1) > 0); else if(*numargs < 0) intret(gamepaused ? 1 : 0); else printvar(id, gamepaused ? 1 : 0); }); - bool ispaused() { return gamepaused; } - bool allowmouselook() { return !gamepaused || !remote || m_edit; } - - void changegamespeed(int val) - { + void changegamespeed(int val) { if(!connected) return; if(!remote) server::forcegamespeed(val); else addmsg(N_GAMESPEED, "ri", val); } - ICOMMAND(gamespeed, "iN$", (int *val, int *numargs, ident *id), - { + ICOMMAND(gamespeed, "iN$", (int *val, int *numargs, ident *id), { if(*numargs > 0) changegamespeed(clampvar(id, *val, 10, 1000)); else if(*numargs < 0) intret(gamespeed); else printvar(id, gamespeed); }); - int scaletime(int t) { return t*gamespeed; } - // collect c2s messages conveniently vector messages; int messagecn = -1, messagereliable = false; - - bool addmsg(int type, const char *fmt, ...) - { + bool addmsg(int type, const char *fmt, ...) { if(!connected) return false; static uchar buf[MAXTRANS]; ucharbuf p(buf, sizeof(buf)); putint(p, type); int numi = 1, numf = 0, nums = 0, mcn = -1; bool reliable = false; - if(fmt) - { + if(fmt) { va_list args; va_start(args, fmt); - while(*fmt) switch(*fmt++) - { + while(*fmt) switch(*fmt++) { case 'r': reliable = true; break; - case 'c': - { + case 'c': { fpsent *d = va_arg(args, fpsent *); mcn = !d || d == player1 ? -1 : d->clientnum; break; } - case 'v': - { + case 'v': { int n = va_arg(args, int); int *v = va_arg(args, int *); loopi(n) putint(p, v[i]); numi += n; break; } - - case 'i': - { + case 'i': { int n = isdigit(*fmt) ? *fmt++-'0' : 1; loopi(n) putint(p, va_arg(args, int)); numi += n; break; } - case 'f': - { + case 'f': { int n = isdigit(*fmt) ? *fmt++-'0' : 1; loopi(n) putfloat(p, (float)va_arg(args, double)); numf += n; @@ -726,8 +561,7 @@ namespace game int num = nums || numf ? 0 : numi, msgsize = server::msgsizelookup(type); if(msgsize && num!=msgsize) { fatal("inconsistent msg size for %d (%d != %d)", type, num, msgsize); } if(reliable) messagereliable = true; - if(mcn != messagecn) - { + if(mcn != messagecn) { static uchar mbuf[16]; ucharbuf m(mbuf, sizeof(mbuf)); putint(m, N_FROMAI); @@ -738,25 +572,17 @@ namespace game messages.put(buf, p.length()); return true; } - - void connectattempt(const char *name, const char *password, const ENetAddress &address) - { + void connectattempt(const char *name, const char *password, const ENetAddress &address) { copystring(connectpass, password); } - - void connectfail() - { + void connectfail() { memset(connectpass, 0, sizeof(connectpass)); } - - void gameconnect(bool _remote) - { + void gameconnect(bool _remote) { remote = _remote; if(editmode) toggleedit(); } - - void gamedisconnect(bool cleanup) - { + void gamedisconnect(bool cleanup) { if(remote) stopfollowing(); ignores.setsize(0); connected = remote = false; @@ -775,26 +601,19 @@ namespace game gamepaused = false; gamespeed = 100; clearclients(false); - if(cleanup) - { + if(cleanup) { nextmode = gamemode = INT_MAX; clientmap[0] = '\0'; } } - VARP(teamcolorchat, 0, 1, 1); const char *chatcolorname(fpsent *d) { return teamcolorchat ? teamcolorname(d, NULL) : colorname(d); } - void toserver(char *text) { conoutf(CON_CHAT, "%s:\f0 %s", chatcolorname(player1), text); addmsg(N_TEXT, "rcs", player1, text); } COMMANDN(say, toserver, "C"); - void sayteam(char *text) { conoutf(CON_TEAMCHAT, "\fs\f8[team]\fr %s: \f8%s", chatcolorname(player1), text); addmsg(N_SAYTEAM, "rcs", player1, text); } COMMAND(sayteam, "C"); - ICOMMAND(servcmd, "C", (char *cmd), addmsg(N_SERVCMD, "rs", cmd)); - - static void sendposition(fpsent *d, packetbuf &q) - { + static void sendposition(fpsent *d, packetbuf &q) { putint(q, N_POS); putuint(q, d->clientnum); // 3 bits phys state, 1 bit life sequence, 2 bits move, 2 bits strafe @@ -808,16 +627,14 @@ namespace game if(o.y < 0 || o.y > 0xFFFF) flags |= 1<<1; if(o.z < 0 || o.z > 0xFFFF) flags |= 1<<2; if(vel > 0xFF) flags |= 1<<3; - if(fall > 0) - { + if(fall > 0) { flags |= 1<<4; if(fall > 0xFF) flags |= 1<<5; if(d->falling.x || d->falling.y || d->falling.z > 0) flags |= 1<<6; } if((lookupmaterial(d->feetpos())&MATF_CLIP) == MAT_GAMECLIP) flags |= 1<<7; putuint(q, flags); - loopk(3) - { + loopk(3) { q.put(o[k]&0xFF); q.put((o[k]>>8)&0xFF); if(o[k] < 0 || o[k] > 0xFFFF) q.put((o[k]>>16)&0xFF); @@ -833,12 +650,10 @@ namespace game uint veldir = (velyaw < 0 ? 360 + int(velyaw)%360 : int(velyaw)%360) + clamp(int(velpitch+90), 0, 180)*360; q.put(veldir&0xFF); q.put((veldir>>8)&0xFF); - if(fall > 0) - { + if(fall > 0) { q.put(fall&0xFF); if(fall > 0xFF) q.put((fall>>8)&0xFF); - if(d->falling.x || d->falling.y || d->falling.z > 0) - { + if(d->falling.x || d->falling.y || d->falling.z > 0) { float fallyaw, fallpitch; vectoyawpitch(d->falling, fallyaw, fallpitch); uint falldir = (fallyaw < 0 ? 360 + int(fallyaw)%360 : int(fallyaw)%360) + clamp(int(fallpitch+90), 0, 180)*360; @@ -847,26 +662,19 @@ namespace game } } } - - void sendposition(fpsent *d, bool reliable) - { + void sendposition(fpsent *d, bool reliable) { if(d->state != CS_ALIVE && d->state != CS_EDITING) return; packetbuf q(100, reliable ? ENET_PACKET_FLAG_RELIABLE : 0); sendposition(d, q); sendclientpacket(q.finalize(), 0); } - - void sendpositions() - { - loopv(players) - { + void sendpositions() { + loopv(players) { fpsent *d = players[i]; - if((d == player1 || d->ai) && (d->state == CS_ALIVE || d->state == CS_EDITING)) - { + if((d == player1 || d->ai) && (d->state == CS_ALIVE || d->state == CS_EDITING)) { packetbuf q(100); sendposition(d, q); - for(int j = i+1; j < players.length(); j++) - { + for(int j = i+1; j < players.length(); j++) { fpsent *d = players[j]; if((d == player1 || d->ai) && (d->state == CS_ALIVE || d->state == CS_EDITING)) sendposition(d, q); @@ -876,12 +684,9 @@ namespace game } } } - - void sendmessages() - { + void sendmessages() { packetbuf p(MAXTRANS); - if(sendcrc) - { + if(sendcrc) { p.reliable(); sendcrc = false; const char *mname = getclientmap(); @@ -889,31 +694,26 @@ namespace game sendstring(mname, p); putint(p, mname[0] ? getmapcrc() : 0); } - if(senditemstoserver) - { + if(senditemstoserver) { if(!m_noitems) p.reliable(); if(!m_noitems) entities::putitems(p); senditemstoserver = false; } - if(messages.length()) - { + if(messages.length()) { p.put(messages.getbuf(), messages.length()); messages.setsize(0); if(messagereliable) p.reliable(); messagereliable = false; messagecn = -1; } - if(totalmillis-lastping>250) - { + if(totalmillis-lastping>250) { putint(p, N_PING); putint(p, totalmillis); lastping = totalmillis; } sendclientpacket(p.finalize(), 1); } - - void c2sinfo(bool force) // send update to the server - { + void c2sinfo(bool force) { // send update to the server { static int lastupdate = -1000; if(totalmillis - lastupdate < 33 && !force) return; // don't update faster than 30fps lastupdate = totalmillis; @@ -921,73 +721,58 @@ namespace game sendmessages(); flushclient(); } - - void sendintro() - { + void sendintro() { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putint(p, N_CONNECT); sendstring(player1->name, p); putint(p, player1->playermodel); string hash = ""; - if(connectpass[0]) - { + if(connectpass[0]) { server::hashpassword(player1->clientnum, sessionid, connectpass, hash); memset(connectpass, 0, sizeof(connectpass)); } sendstring(hash, p); authkey *a = servauth[0] && autoauth ? findauthkey(servauth) : NULL; - if(a) - { + if(a) { a->lastauth = lastmillis; sendstring(a->desc, p); sendstring(a->name, p); } - else - { + else { sendstring("", p); sendstring("", p); } sendclientpacket(p.finalize(), 1); } - - void updatepos(fpsent *d) - { + void updatepos(fpsent *d) { // update the position of other clients in the game in our world // don't care if he's in the scenery or other players, // just don't overlap with our client - const float r = player1->radius+d->radius; const float dx = player1->o.x-d->o.x; const float dy = player1->o.y-d->o.y; const float dz = player1->o.z-d->o.z; const float rz = player1->aboveeye+d->eyeheight; const float fx = (float)fabs(dx), fy = (float)fabs(dy), fz = (float)fabs(dz); - if(fxstate!=CS_SPECTATOR && d->state!=CS_DEAD) - { + if(fxstate!=CS_SPECTATOR && d->state!=CS_DEAD) { if(fxo.y += dy<0 ? r-fy : -(r-fy); // push aside else d->o.x += dx<0 ? r-fx : -(r-fx); } int lagtime = totalmillis-d->lastupdate; - if(lagtime) - { + if(lagtime) { if(d->state!=CS_SPAWNING && d->lastupdate) d->plag = (d->plag*5+lagtime)/6; d->lastupdate = totalmillis; } } - - void parsepositions(ucharbuf &p) - { + void parsepositions(ucharbuf &p) { int type; - while(p.remaining()) switch(type = getint(p)) - { + while(p.remaining()) switch(type = getint(p)) { case N_DEMOPACKET: break; - case N_POS: // position of another client - { + case N_POS: { // position of another client { int cn = getuint(p), physstate = p.get(), flags = getuint(p); vec o, vel, falling; float yaw, pitch, roll; - loopk(3) - { + loopk(3) { int n = p.get(); n |= p.get()<<8; if(flags&(1<physstate = physstate&7; updatephysstate(d); updatepos(d); - if(smoothmove && d->smoothmillis>=0 && oldpos.dist(d->o) < smoothdist) - { + if(smoothmove && d->smoothmillis>=0 && oldpos.dist(d->o) < smoothdist) { d->newpos = d->o; d->newyaw = d->yaw; d->newpitch = d->pitch; @@ -1050,36 +832,28 @@ namespace game if(d->state==CS_LAGGED || d->state==CS_SPAWNING) d->state = CS_ALIVE; break; } - - case N_TELEPORT: - { + case N_TELEPORT: { int cn = getint(p), tp = getint(p), td = getint(p); fpsent *d = getclient(cn); if(!d || d->lifesequence < 0 || d->state==CS_DEAD) continue; entities::teleporteffects(d, tp, td, false); break; } - - case N_JUMPPAD: - { + case N_JUMPPAD: { int cn = getint(p), jp = getint(p); fpsent *d = getclient(cn); if(!d || d->lifesequence < 0 || d->state==CS_DEAD) continue; entities::jumppadeffects(d, jp, false); break; } - default: neterr("type"); return; } } - - void parsestate(fpsent *d, ucharbuf &p, bool resume = false) - { + void parsestate(fpsent *d, ucharbuf &p, bool resume = false) { if(!d) { static fpsent dummy; d = &dummy; } - if(resume) - { + if(resume) { if(d==player1) getint(p); else d->state = getint(p); d->frags = getint(p); @@ -1094,36 +868,26 @@ namespace game d->armour = getint(p); d->maxarmour = getint(p); d->armourtype = getint(p); - if(resume && d==player1) - { + if(resume && d==player1) { getint(p); loopi(GUN_PISTOL-GUN_SG+1) getint(p); } - else - { + else { int gun = getint(p); d->gunselect = clamp(gun, int(GUN_FIST), int(GUN_PISTOL)); loopi(GUN_PISTOL-GUN_SG+1) d->ammo[GUN_SG+i] = getint(p); } } - extern int deathscore; - - void parsemessages(int cn, fpsent *d, ucharbuf &p) - { + void parsemessages(int cn, fpsent *d, ucharbuf &p) { static char text[MAXTRANS]; int type; bool mapchanged = false, demopacket = false; - - while(p.remaining()) switch(type = getint(p)) - { + while(p.remaining()) switch(type = getint(p)) { case N_DEMOPACKET: demopacket = true; break; - - case N_SERVINFO: // welcome messsage from the server - { + case N_SERVINFO: { // welcome messsage from the server { int mycn = getint(p), prot = getint(p); - if(prot!=PROTOCOL_VERSION) - { + if(prot!=PROTOCOL_VERSION) { conoutf(CON_ERROR, "you are using a different game protocol (you: %d, server: %d)", PROTOCOL_VERSION, prot); disconnect(); return; @@ -1136,21 +900,16 @@ namespace game sendintro(); break; } - - case N_WELCOME: - { + case N_WELCOME: { connected = true; notifywelcome(); break; } - - case N_PAUSEGAME: - { + case N_PAUSEGAME: { bool val = getint(p) > 0; int cn = getint(p); fpsent *a = cn >= 0 ? getclient(cn) : NULL; - if(!demopacket) - { + if(!demopacket) { gamepaused = val; player1->attacking = false; } @@ -1158,9 +917,7 @@ namespace game else conoutf("game is %s", val ? "paused" : "resumed"); break; } - - case N_GAMESPEED: - { + case N_GAMESPEED: { int val = clamp(getint(p), 10, 1000), cn = getint(p); fpsent *a = cn >= 0 ? getclient(cn) : NULL; if(!demopacket) gamespeed = val; @@ -1168,22 +925,17 @@ namespace game else conoutf("gamespeed is %d", val); break; } - - case N_CLIENT: - { + case N_CLIENT: { int cn = getint(p), len = getuint(p); ucharbuf q = p.subbuf(len); parsemessages(cn, getclient(cn), q); break; } - case N_SOUND: if(!d) return; playsound(getint(p), &d->o); break; - - case N_TEXT: - { + case N_TEXT: { if(!d) return; getstring(text, p); filtertext(text, text, true, true); @@ -1193,9 +945,7 @@ namespace game conoutf(CON_CHAT, "%s:\f0 %s", chatcolorname(d), text); break; } - - case N_SAYTEAM: - { + case N_SAYTEAM: { int tcn = getint(p); fpsent *t = getclient(tcn); getstring(text, p); @@ -1206,7 +956,6 @@ namespace game conoutf(CON_TEAMCHAT, "\fs\f8[team]\fr %s: \f8%s", chatcolorname(t), text); break; } - case N_MAPCHANGE: getstring(text, p); filtertext(text, text, false); @@ -1216,14 +965,11 @@ namespace game if(getint(p)) entities::spawnitems(); else senditemstoserver = false; break; - - case N_FORCEDEATH: - { + case N_FORCEDEATH: { int cn = getint(p); fpsent *d = cn==player1->clientnum ? player1 : newclient(cn); if(!d) break; - if(d==player1) - { + if(d==player1) { if(editmode) toggleedit(); stopfollowing(); if(deathscore) showscores(true); @@ -1232,24 +978,18 @@ namespace game d->state = CS_DEAD; break; } - - case N_ITEMLIST: - { + case N_ITEMLIST: { int n; - while((n = getint(p))>=0 && !p.overread()) - { + while((n = getint(p))>=0 && !p.overread()) { if(mapchanged) entities::setspawn(n, true); getint(p); // type } break; } - - case N_INITCLIENT: // another client either connected or changed name/team - { + case N_INITCLIENT: { // another client either connected or changed name/team { int cn = getint(p); fpsent *d = newclient(cn); - if(!d) - { + if(!d) { getstring(text, p); getstring(text, p); getint(p); @@ -1258,13 +998,11 @@ namespace game getstring(text, p); filtertext(text, text, false, false, MAXNAMELEN); if(!text[0]) copystring(text, "Anonymous"); - if(d->name[0]) // already connected - { + if(d->name[0]) { // already connected { if(strcmp(d->name, text) && !isignored(d->clientnum)) conoutf("%s is now known as %s", colorname(d), colorname(d, text)); } - else // new client - { + else { // new client { conoutf("\f0join:\f7 %s", colorname(d, text)); if(needclipboard >= 0) needclipboard++; } @@ -1275,32 +1013,24 @@ namespace game d->playermodel = 0; break; } - case N_SWITCHNAME: getstring(text, p); - if(d) - { + if(d) { filtertext(text, text, false, false, MAXNAMELEN); if(!text[0]) copystring(text, "Anonymous"); - if(strcmp(text, d->name)) - { + if(strcmp(text, d->name)) { if(!isignored(d->clientnum)) conoutf("%s is now known as %s", colorname(d), colorname(d, text)); copystring(d->name, text, MAXNAMELEN+1); } } break; - case N_SWITCHMODEL: break; - case N_CDIS: clientdisconnected(getint(p)); break; - - case N_SPAWN: - { - if(d) - { + case N_SPAWN: { + if(d) { if(d->state==CS_DEAD && d->lastpain) saveragdoll(d); d->respawn(); } @@ -1311,15 +1041,12 @@ namespace game lasthit = 0; break; } - - case N_SPAWNSTATE: - { + case N_SPAWNSTATE: { 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(s==player1) { if(editmode) toggleedit(); stopfollowing(); } @@ -1327,8 +1054,7 @@ namespace game parsestate(s, p); s->state = CS_ALIVE; pickgamespawn(s); - if(s == player1) - { + if(s == player1) { showscores(false); lasthit = 0; } @@ -1336,9 +1062,7 @@ namespace game addmsg(N_SPAWN, "rcii", s, s->lifesequence, s->gunselect); break; } - - case N_SHOTFX: - { + case N_SHOTFX: { int scn = getint(p), gun = getint(p), id = getint(p); vec from, to; loopk(3) from[k] = getint(p)/DMF; @@ -1354,17 +1078,14 @@ namespace game shoteffects(s->gunselect, from, to, s, false, id, prevaction); break; } - - case N_EXPLODEFX: - { + case N_EXPLODEFX: { int ecn = getint(p), gun = getint(p), id = getint(p); fpsent *e = getclient(ecn); if(!e) break; explodeeffects(gun, e, false, id); break; } - case N_DAMAGE: - { + case N_DAMAGE: { int tcn = getint(p), acn = getint(p), damage = getint(p), @@ -1379,9 +1100,7 @@ namespace game damaged(damage, target, actor, false); break; } - - case N_HITPUSH: - { + case N_HITPUSH: { int tcn = getint(p), gun = getint(p), damage = getint(p); fpsent *target = getclient(tcn); vec dir; @@ -1389,9 +1108,7 @@ namespace game if(target) target->hitpush(damage * (target->health<=0 ? deadpush : 1), dir, NULL, gun); break; } - - case N_DIED: - { + case N_DIED: { int vcn = getint(p), acn = getint(p), frags = getint(p), tfrags = getint(p); fpsent *victim = getclient(vcn), *actor = getclient(acn); @@ -1399,8 +1116,7 @@ namespace game actor->frags = frags; if(m_teammode) setteaminfo(actor->team, tfrags); extern int hidefrags; - if(actor!=player1 && (!hidefrags)) - { + if(actor!=player1 && (!hidefrags)) { defformatstring(ds, "%d", actor->frags); particle_textcopy(actor->abovehead(), ds, PART_TEXT, 2000, 0x32FF64, 4.0f, -8); } @@ -1408,10 +1124,8 @@ namespace game killed(victim, actor); break; } - case N_TEAMINFO: - for(;;) - { + for(;;) { getstring(text, p); if(p.overread() || !text[0]) break; int frags = getint(p); @@ -1419,27 +1133,20 @@ namespace game if(m_teammode) setteaminfo(text, frags); } break; - - case N_GUNSELECT: - { + case N_GUNSELECT: { if(!d) return; int gun = getint(p); d->gunselect = clamp(gun, int(GUN_FIST), int(GUN_PISTOL)); playsound(S_WEAPLOAD, &d->o); break; } - - case N_TAUNT: - { + case N_TAUNT: { if(!d) return; d->lasttaunt = lastmillis; break; } - - case N_RESUME: - { - for(;;) - { + case N_RESUME: { + for(;;) { int cn = getint(p); if(p.overread() || cn<0) break; fpsent *d = (cn == player1->clientnum ? player1 : newclient(cn)); @@ -1447,9 +1154,7 @@ namespace game } break; } - - case N_ITEMSPAWN: - { + case N_ITEMSPAWN: { int i = getint(p); if(!entities::ents.inrange(i)) break; entities::setspawn(i, true); @@ -1463,21 +1168,16 @@ namespace game if(icon >= 0) particle_icon(vec(0.0f, 0.0f, 4.0f).add(entities::ents[i]->o), icon%4, icon/4, PART_HUD_ICON, 2000, 0xFFFFFF, 2.0f, -8); break; } - - case N_ITEMACC: // server acknowledges that I picked up this item - { + case N_ITEMACC: { // server acknowledges that I picked up this item { int i = getint(p), cn = getint(p); - if(cn >= 0) - { + if(cn >= 0) { fpsent *d = getclient(cn); entities::pickupeffects(i, d); } else entities::setspawn(i, true); break; } - - case N_CLIPBOARD: - { + case N_CLIPBOARD: { int cn = getint(p), unpacklen = getint(p), packlen = getint(p); fpsent *d = getclient(cn); ucharbuf q = p.subbuf(max(packlen, 0)); @@ -1485,15 +1185,13 @@ namespace game break; } case N_UNDO: - case N_REDO: - { + case N_REDO: { int cn = getint(p), unpacklen = getint(p), packlen = getint(p); fpsent *d = getclient(cn); ucharbuf q = p.subbuf(max(packlen, 0)); if(d) unpackundo(q.buf, q.maxlen, unpacklen); break; } - case N_EDITF: // coop editing messages case N_EDITT: case N_EDITM: @@ -1503,8 +1201,7 @@ namespace game case N_ROTATE: case N_REPLACE: case N_DELCUBE: - case N_EDITVSLOT: - { + case N_EDITVSLOT: { if(!d) return; selinfo sel; sel.o.x = getint(p); sel.o.y = getint(p); sel.o.z = getint(p); @@ -1512,11 +1209,9 @@ namespace game sel.grid = getint(p); sel.orient = getint(p); sel.cx = getint(p); sel.cxs = getint(p); sel.cy = getint(p), sel.cys = getint(p); sel.corner = getint(p); - switch(type) - { + switch(type) { case N_EDITF: { int dir = getint(p), mode = getint(p); if(sel.validate()) mpeditface(dir, mode, sel, false); break; } - case N_EDITT: - { + case N_EDITT: { int tex = getint(p), allfaces = getint(p); if(p.remaining() < 2) return; @@ -1531,8 +1226,7 @@ namespace game case N_COPY: if(d && sel.validate()) mpcopy(d->edit, sel, false); break; case N_PASTE: if(d && sel.validate()) mppaste(d->edit, sel, false); break; case N_ROTATE: { int dir = getint(p); if(sel.validate()) mprotate(dir, sel, false); break; } - case N_REPLACE: - { + case N_REPLACE: { int oldtex = getint(p), newtex = getint(p), insel = getint(p); @@ -1544,8 +1238,7 @@ namespace game break; } case N_DELCUBE: if(sel.validate()) mpdelcube(sel, false); break; - case N_EDITVSLOT: - { + case N_EDITVSLOT: { int delta = getint(p), allfaces = getint(p); if(p.remaining() < 2) return; @@ -1558,48 +1251,40 @@ namespace game } break; } - case N_REMIP: - { + case N_REMIP: { if(!d) return; conoutf("%s remipped", colorname(d)); mpremip(false); break; } - case N_EDITENT: // coop edit of ent - { + case N_EDITENT: { // coop edit of ent { if(!d) return; int i = getint(p); float x = getint(p)/DMF, y = getint(p)/DMF, z = getint(p)/DMF; int type = getint(p); int attr1 = getint(p), attr2 = getint(p), attr3 = getint(p), attr4 = getint(p), attr5 = getint(p); - mpeditent(i, vec(x, y, z), type, attr1, attr2, attr3, attr4, attr5, false); break; } - case N_EDITVAR: - { + case N_EDITVAR: { if(!d) return; int type = getint(p); getstring(text, p); string name; filtertext(name, text, false); ident *id = getident(name); - switch(type) - { - case ID_VAR: - { + switch(type) { + case ID_VAR: { int val = getint(p); if(id && id->flags&IDF_OVERRIDE && !(id->flags&IDF_READONLY)) setvar(name, val); break; } - case ID_FVAR: - { + case ID_FVAR: { float val = getfloat(p); if(id && id->flags&IDF_OVERRIDE && !(id->flags&IDF_READONLY)) setfvar(name, val); break; } - case ID_SVAR: - { + case ID_SVAR: { getstring(text, p); if(id && id->flags&IDF_OVERRIDE && !(id->flags&IDF_READONLY)) setsvar(name, text); break; @@ -1608,40 +1293,31 @@ namespace game printvar(d, id); break; } - case N_PONG: addmsg(N_CLIENTPING, "i", player1->ping = (player1->ping*5+totalmillis-getint(p))/6); break; - case N_CLIENTPING: if(!d) return; d->ping = getint(p); break; - case N_TIMEUP: timeupdate(getint(p)); break; - case N_SERVMSG: getstring(text, p); conoutf("%s", text); break; - - case N_SENDDEMOLIST: - { + case N_SENDDEMOLIST: { int demos = getint(p); if(demos <= 0) conoutf("no demos available"); - else loopi(demos) - { + else loopi(demos) { getstring(text, p); if(p.overread()) break; conoutf("%d. %s", i+1, text); } break; } - - case N_DEMOPLAYBACK: - { + case N_DEMOPLAYBACK: { int on = getint(p); if(on) player1->state = CS_SPECTATOR; else clearclients(); @@ -1651,80 +1327,62 @@ namespace game execident(on ? "demostart" : "demoend"); break; } - - case N_CURRENTMASTER: - { + case N_CURRENTMASTER: { int mm = getint(p), mn; loopv(players) players[i]->privilege = PRIV_NONE; - while((mn = getint(p))>=0 && !p.overread()) - { + while((mn = getint(p))>=0 && !p.overread()) { fpsent *m = mn==player1->clientnum ? player1 : newclient(mn); int priv = getint(p); if(m) m->privilege = priv; } - if(mm != mastermode) - { + if(mm != mastermode) { mastermode = mm; conoutf("mastermode is %s (%d)", server::mastermodename(mastermode), mastermode); } break; } - - case N_MASTERMODE: - { + case N_MASTERMODE: { mastermode = getint(p); conoutf("mastermode is %s (%d)", server::mastermodename(mastermode), mastermode); break; } - - case N_EDITMODE: - { + case N_EDITMODE: { int val = getint(p); if(!d) break; - if(val) - { + if(val) { d->editstate = d->state; d->state = CS_EDITING; } - else - { + else { d->state = d->editstate; if(d->state==CS_DEAD) deathstate(d, true); } break; } - - case N_SPECTATOR: - { + case N_SPECTATOR: { int sn = getint(p), val = getint(p); fpsent *s; - if(sn==player1->clientnum) - { + if(sn==player1->clientnum) { s = player1; if(val && remote && !player1->privilege) senditemstoserver = false; } else s = newclient(sn); if(!s) return; - if(val) - { - if(s==player1) - { + if(val) { + if(s==player1) { if(editmode) toggleedit(); if(s->state==CS_DEAD) showscores(false); disablezoom(); } s->state = CS_SPECTATOR; } - else if(s->state==CS_SPECTATOR) - { + else if(s->state==CS_SPECTATOR) { if(s==player1) stopfollowing(); deathstate(s, true); } break; } - - case N_SETTEAM: - { + case N_SETTEAM: { int wn = getint(p); getstring(text, p); int reason = getint(p); @@ -1736,44 +1394,34 @@ namespace game conoutf(fmt[reason], colorname(w), w->team); break; } - - case N_ANNOUNCE: - { + case N_ANNOUNCE: { int t = getint(p); - if (t==I_QUAD) { playsound(S_V_QUAD10, NULL, NULL, 0, 0, 0, -1, 0, 3000); conoutf(CON_GAMEINFO, "\f2quad damage will spawn in 10 seconds!"); } + if (t==I_QUAD) { playsound(S_V_QUAD10, NULL, NULL, 0, 0, 0, -1, 0, 3000); conoutf(CON_GAMEINFO, "\f2quad damage will spawn in 10 seconds!"); } else if(t==I_BOOST) { playsound(S_V_BOOST10, NULL, NULL, 0, 0, 0, -1, 0, 3000); conoutf(CON_GAMEINFO, "\f2health boost will spawn in 10 seconds!"); } break; } - - case N_NEWMAP: - { + case N_NEWMAP: { int size = getint(p); if(size>=0) emptymap(size, true, NULL); else enlargemap(true); - if(d && d!=player1) - { + if(d && d!=player1) { int newsize = 0; while(1<=0 ? "%s started a new map of size %d" : "%s enlarged the map to size %d", colorname(d), newsize); } break; } - - case N_REQAUTH: - { + case N_REQAUTH: { getstring(text, p); if(autoauth && text[0] && tryauth(text)) conoutf("server requested authkey \"%s\"", text); break; } - - case N_AUTHCHAL: - { + case N_AUTHCHAL: { getstring(text, p); authkey *a = findauthkey(text); uint id = (uint)getint(p); getstring(text, p); - if(a && a->lastauth && lastmillis - a->lastauth < 60*1000) - { + if(a && a->lastauth && lastmillis - a->lastauth < 60*1000) { vector buf; answerchallenge(a->key, text, buf); //conoutf(CON_DEBUG, "answering %u, challenge %s with %s", id, text, buf.getbuf()); @@ -1786,9 +1434,7 @@ namespace game } break; } - - case N_INITAI: - { + case N_INITAI: { int bn = getint(p), on = getint(p), at = getint(p), sk = clamp(getint(p), 1, 101), pm = getint(p); string name, team; getstring(text, p); @@ -1800,45 +1446,35 @@ namespace game ai::init(b, at, on, sk, bn, pm, name, team); break; } - case N_SERVCMD: getstring(text, p); break; - default: neterr("type", cn < 0); return; } } - - struct demoreq - { + struct demoreq { int tag; string name; }; vector demoreqs; enum { MAXDEMOREQS = 7 }; static int lastdemoreq = 0; - - void receivefile(packetbuf &p) - { + void receivefile(packetbuf &p) { int type; - while(p.remaining()) switch(type = getint(p)) - { + while(p.remaining()) switch(type = getint(p)) { case N_DEMOPACKET: return; - case N_SENDDEMO: - { + case N_SENDDEMO: { string fname; fname[0] = '\0'; int tag = getint(p); - loopv(demoreqs) if(demoreqs[i].tag == tag) - { + loopv(demoreqs) if(demoreqs[i].tag == tag) { copystring(fname, demoreqs[i].name); demoreqs.remove(i); break; } - if(!fname[0]) - { + if(!fname[0]) { time_t t = time(NULL); size_t len = strftime(fname, sizeof(fname), "%Y-%m-%d_%H.%M.%S", localtime(&t)); fname[min(len, sizeof(fname)-1)] = '\0'; @@ -1855,9 +1491,7 @@ namespace game delete demo; break; } - - case N_SENDMAP: - { + case N_SENDMAP: { if(!m_edit) return; string oldname; copystring(oldname, getclientmap()); @@ -1876,69 +1510,52 @@ namespace game } } } - - void parsepacketclient(int chan, packetbuf &p) // processes any updates from the server - { + void parsepacketclient(int chan, packetbuf &p) { // processes any updates from the server { if(p.packet->flags&ENET_PACKET_FLAG_UNSEQUENCED) return; - switch(chan) - { + switch(chan) { case 0: parsepositions(p); break; - case 1: parsemessages(-1, NULL, p); break; - case 2: receivefile(p); break; } } - - void getmap() - { + void getmap() { if(!m_edit) { conoutf(CON_ERROR, "\"getmap\" only works in coop edit mode"); return; } conoutf("getting map..."); addmsg(N_GETMAP, "r"); } COMMAND(getmap, ""); - - void stopdemo() - { - if(remote) - { + void stopdemo() { + if(remote) { if(player1->privilegeprivilegeprivilege= MAXDEMOREQS) demoreqs.remove(0); demoreq &r = demoreqs.add(); r.tag = lastdemoreq; @@ -1947,29 +1564,23 @@ namespace game addmsg(N_GETDEMO, "rii", i, lastdemoreq); } ICOMMAND(getdemo, "ss", (char *val, char *name), getdemo(val, name)); - - void listdemos() - { + void listdemos() { conoutf("listing demos..."); addmsg(N_LISTDEMOS, "r"); } COMMAND(listdemos, ""); - - void sendmap() - { + void sendmap() { if(!m_edit || (player1->state==CS_SPECTATOR && remote && !player1->privilege)) { conoutf(CON_ERROR, "\"sendmap\" only works in coop edit mode"); return; } conoutf("sending map..."); defformatstring(mname, "sendmap_%d", lastmillis); save_world(mname, true); defformatstring(fname, "packages/maps/%s.ogz", mname); stream *map = openrawfile(path(fname), "rb"); - if(map) - { + if(map) { stream::offset len = map->size(); if(len > 4*1024*1024) conoutf(CON_ERROR, "map is too large"); else if(len <= 0) conoutf(CON_ERROR, "could not read map"); - else - { + else { sendfile(-1, 2, map); if(needclipboard >= 0) needclipboard++; } @@ -1979,13 +1590,10 @@ namespace game remove(findfile(fname, "rb")); } COMMAND(sendmap, ""); - - void gotoplayer(const char *arg) - { + void gotoplayer(const char *arg) { if(player1->state!=CS_SPECTATOR && player1->state!=CS_EDITING) return; int i = parseplayer(arg); - if(i>=0) - { + if(i>=0) { fpsent *d = getclient(i); if(!d || d==player1) return; player1->o = d->o; @@ -1996,9 +1604,7 @@ namespace game } } COMMANDN(goto, gotoplayer, "s"); - - void gotosel() - { + void gotosel() { if(player1->state!=CS_EDITING) return; player1->o = getselpos(); vec dir; diff --git a/src/fpsgame/entities.cpp b/src/fpsgame/entities.cpp index 93e3dc9..9336c4e 100644 --- a/src/fpsgame/entities.cpp +++ b/src/fpsgame/entities.cpp @@ -2,38 +2,27 @@ int pwitemspicked[7] = { 0 }; -namespace entities -{ +namespace entities { using namespace game; - int extraentinfosize() { return 0; } // size in bytes of what the 2 methods below read/write... so it can be skipped by other games #ifndef STANDALONE vector ents; - vector &getents() { return ents; } - bool mayattach(extentity &e) { return false; } bool attachent(extentity &e, extentity &a) { return false; } - - const char *itemname(int i) - { + const char *itemname(int i) { int t = ents[i]->type; if(tI_QUAD) return NULL; return itemstats[t-I_SHELLS].name; } - - int itemicon(int i) - { + int itemicon(int i) { int t = ents[i]->type; if(tI_QUAD) return -1; return itemstats[t-I_SHELLS].icon; } - - const char *entmdlname(int type) - { - static const char * const entmdlnames[] = - { + const char *entmdlname(int type) { + static const char * const entmdlnames[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "ammo/shells", "ammo/bullets", "ammo/rockets", "ammo/rrounds", "ammo/grenades", "ammo/cartridges", "health", "boost", "tinyhealth", "tinyarmour", "armor/green", "armor/yellow", "quad", "teleporter", @@ -47,23 +36,16 @@ namespace entities }; return entmdlnames[type]; } - - const char *entmodel(const entity &e) - { - if(e.type == TELEPORT) - { + const char *entmodel(const entity &e) { + if(e.type == TELEPORT) { if(e.attr2 > 0) return mapmodelname(e.attr2); if(e.attr2 < 0) return NULL; } return e.type < MAXENTTYPES ? entmdlname(e.type) : NULL; } - - void preloadentities() - { - loopi(MAXENTTYPES) - { - switch(i) - { + void preloadentities() { + loopi(MAXENTTYPES) { + switch(i) { case I_SHELLS: [[fallthrough]]; case I_BULLETS: @@ -97,30 +79,23 @@ namespace entities if(!mdl) continue; preloadmodel(mdl); } - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; - switch(e.type) - { + switch(e.type) { case TELEPORT: if(e.attr2 > 0) preloadmodel(mapmodelname(e.attr2)); [[fallthrough]]; - case JUMPPAD: if(e.attr4 > 0) preloadmapsound(e.attr4); break; } } } - - void renderentities() - { - loopv(ents) - { + void renderentities() { + loopv(ents) { extentity &e = *ents[i]; int revs = 10; - switch(e.type) - { + switch(e.type) { case TELEPORT: if(e.attr2 < 0) continue; break; @@ -128,33 +103,25 @@ namespace entities if(!e.spawned() || e.type < I_SHELLS || e.type > I_QUAD) continue; } const char *mdlname = entmodel(e); - if(mdlname) - { + 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); } } } - - void addammo(int type, int &v, bool local) - { + void addammo(int type, int &v, bool local) { itemstat &is = itemstats[type-I_SHELLS]; v += is.add; if(v>is.max) v = is.max; if(local) msgsound(is.sound); } - - void repammo(fpsent *d, int type, bool local) - { + void repammo(fpsent *d, int type, bool local) { addammo(type, d->ammo[type-I_SHELLS+GUN_SG], local); } - // these two functions are called when the server acknowledges that you really // picked up the item (in multiplayer someone may grab it before you). - - void pickupeffects(int n, fpsent *d) - { + void pickupeffects(int n, fpsent *d) { if(!ents.inrange(n)) return; extentity *e = ents[n]; int type = e->type; @@ -164,8 +131,7 @@ namespace entities if(!d) return; itemstat &is = itemstats[type-I_SHELLS]; fpsent *h = followingplayer(player1); - if(d!=h || isthirdperson()) - { + if(d!=h || isthirdperson()) { //particle_text(d->abovehead(), is.name, PART_TEXT, 2000, 0xFFC864, 4.0f, -8); particle_icon(d->abovehead(), is.icon%4, is.icon/4, PART_HUD_ICON_GREY, 2000, 0xFFFFFF, 2.0f, -8); } @@ -180,29 +146,22 @@ namespace entities case I_BOOST: pwitemspicked[5]++; break; case I_QUAD: pwitemspicked[6]++; break; } - if(d==h) switch(type) - { + if(d==h) switch(type) { case I_BOOST: conoutf(CON_GAMEINFO, "\f2you got the health boost!"); playsound(S_V_BOOST, NULL, NULL, 0, 0, 0, -1, 0, 3000); break; - case I_QUAD: conoutf(CON_GAMEINFO, "\f2you got the quad!"); playsound(S_V_QUAD, NULL, NULL, 0, 0, 0, -1, 0, 3000); break; } } - // these functions are called when the client touches the item - - void teleporteffects(fpsent *d, int tp, int td, bool local) - { - if(ents.inrange(tp) && ents[tp]->type == TELEPORT) - { + void teleporteffects(fpsent *d, int tp, int td, bool local) { + if(ents.inrange(tp) && ents[tp]->type == TELEPORT) { extentity &e = *ents[tp]; - if(e.attr4 >= 0) - { + if(e.attr4 >= 0) { int snd = S_TELEPORT, flags = 0; if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; } fpsent *h = followingplayer(player1); @@ -210,8 +169,7 @@ namespace entities if(d!=h && ents.inrange(td) && ents[td]->type == TELEDEST) playsound(snd, &ents[td]->o, NULL, flags); } } - if(local && d->clientnum >= 0) - { + if(local && d->clientnum >= 0) { sendposition(d); packetbuf p(32, ENET_PACKET_FLAG_RELIABLE); putint(p, N_TELEPORT); @@ -222,21 +180,16 @@ namespace entities flushclient(); } } - - void jumppadeffects(fpsent *d, int jp, bool local) - { - if(ents.inrange(jp) && ents[jp]->type == JUMPPAD) - { + void jumppadeffects(fpsent *d, int jp, bool local) { + if(ents.inrange(jp) && ents[jp]->type == JUMPPAD) { extentity &e = *ents[jp]; - if(e.attr4 >= 0) - { + if(e.attr4 >= 0) { int snd = S_JUMPPAD, flags = 0; if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; } playsound(snd, d == followingplayer(player1) ? NULL : &e.o, NULL, flags); } } - if(local && d->clientnum >= 0) - { + if(local && d->clientnum >= 0) { sendposition(d); packetbuf p(16, ENET_PACKET_FLAG_RELIABLE); putint(p, N_JUMPPAD); @@ -246,22 +199,17 @@ namespace entities flushclient(); } } - - void teleport(int n, fpsent *d) // also used by monsters - { + void teleport(int n, fpsent *d) { // also used by monsters { int e = -1, tag = ents[n]->attr1, beenhere = -1; - for(;;) - { + for(;;) { e = findentity(TELEDEST, e+1); if(e==beenhere || e<0) { conoutf(CON_WARN, "no teleport destination for tag %d", tag); return; } if(beenhere<0) beenhere = e; - if(ents[e]->attr2==tag) - { + if(ents[e]->attr2==tag) { teleporteffects(d, n, e, true); d->o = ents[e]->o; d->yaw = ents[e]->attr1; - if(ents[e]->attr3 > 0) - { + if(ents[e]->attr3 > 0) { vec dir; vecfromyawpitch(d->yaw, 0, 1, 0, dir); float speed = d->vel.magnitude2(); @@ -276,25 +224,18 @@ namespace entities } } } - - void trypickup(int n, fpsent *d) - { + void trypickup(int n, fpsent *d) { extentity *e = ents[n]; - switch(e->type) - { + switch(e->type) { default: - if(d->canpickup(e->type)) - { + if(d->canpickup(e->type)) { addmsg(N_ITEMPICKUP, "rci", d, n); e->setnopickup(); // even if someone else gets it first } break; - - case TELEPORT: - { + case TELEPORT: { if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<500) break; - if(e->attr3 > 0) - { + if(e->attr3 > 0) { defformatstring(hookname, "can_teleport_%d", e->attr3); if(!execidentbool(hookname, true)) break; } @@ -303,9 +244,7 @@ namespace entities teleport(n, d); break; } - - case JUMPPAD: - { + case JUMPPAD: { if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<300) break; d->lastpickup = e->type; d->lastpickupmillis = lastmillis; @@ -320,13 +259,10 @@ namespace entities } } } - - void checkitems(fpsent *d) - { + void checkitems(fpsent *d) { if(d->state!=CS_ALIVE) return; vec o = d->feetpos(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type==NOTUSED) continue; if((!e.spawned() || e.nopickup()) && e.type!=TELEPORT && e.type!=JUMPPAD) continue; @@ -334,97 +270,68 @@ namespace entities if(dist<(e.type==TELEPORT ? 16 : 12)) trypickup(i, d); } } - - void checkquad(int time, fpsent *d) - { - if(d->quadmillis && (d->quadmillis -= time)<=0) - { + void checkquad(int time, fpsent *d) { + if(d->quadmillis && (d->quadmillis -= time)<=0) { d->quadmillis = 0; fpsent *h = followingplayer(player1); playsound(S_PUPOUT, d==h ? NULL : &d->o); if(d==h) conoutf(CON_GAMEINFO, "\f2quad damage is over"); } } - - void putitems(packetbuf &p) // puts items in network stream and also spawns them locally - { + void putitems(packetbuf &p) { // puts items in network stream and also spawns them locally { putint(p, N_ITEMLIST); - loopv(ents) if(ents[i]->type>=I_SHELLS && ents[i]->type<=I_QUAD && (!m_noammo || ents[i]->typetype>I_CARTRIDGES)) - { + loopv(ents) if(ents[i]->type>=I_SHELLS && ents[i]->type<=I_QUAD && (!m_noammo || ents[i]->typetype>I_CARTRIDGES)) { putint(p, i); putint(p, ents[i]->type); } putint(p, -1); } - void resetspawns() { loopv(ents) { extentity *e = ents[i]; e->clearspawned(); e->clearnopickup(); } } - - void spawnitems(bool force) - { + void spawnitems(bool force) { if(m_noitems) return; - loopv(ents) - { + loopv(ents) { extentity *e = ents[i]; - if(e->type>=I_SHELLS && e->type<=I_QUAD && (!m_noammo || e->typetype>I_CARTRIDGES)) - { + if(e->type>=I_SHELLS && e->type<=I_QUAD && (!m_noammo || e->typetype>I_CARTRIDGES)) { e->setspawned(force || !server::delayspawn(e->type)); e->clearnopickup(); } } } - void setspawn(int i, bool on) { if(ents.inrange(i)) { extentity *e = ents[i]; e->setspawned(on); e->clearnopickup(); } } - extentity *newentity() { return new extentity(); } void deleteentity(extentity *e) { delete e; } - - void clearents() - { + void clearents() { while(ents.length()) deleteentity(ents.pop()); } - - void fixentity(extentity &e) - { + void fixentity(extentity &e) { if(e.type == TELEDEST) e.attr3 = e.attr2; } - - void entradius(extentity &e, bool color) - { - switch(e.type) - { - case TELEDEST: - { + void entradius(extentity &e, bool color) { + switch(e.type) { + case TELEDEST: { vec dir; vecfromyawpitch(e.attr1, 0, 1, 0, dir); renderentarrow(e, dir, 4); break; } case TELEPORT: - loopv(ents) if(ents[i]->type == TELEDEST && e.attr1==ents[i]->attr2) - { + loopv(ents) if(ents[i]->type == TELEDEST && e.attr1==ents[i]->attr2) { renderentarrow(e, vec(ents[i]->o).sub(e.o).normalize(), e.o.dist(ents[i]->o)); break; } break; - case JUMPPAD: renderentarrow(e, vec((int)(char)e.attr3*10.0f, (int)(char)e.attr2*10.0f, e.attr1*12.5f).normalize(), 4); break; - default: break; } } - - bool printent(extentity &e, char *buf, int len) - { + bool printent(extentity &e, char *buf, int len) { return false; } - const char *entnameinfo(entity &e) { return ""; } - const char *entname(int i) - { - static const char * const entnames[] = - { + const char *entname(int i) { + static const char * const entnames[] = { "none?", "light", "mapmodel", "playerstart", "none?", "particles", "sound", "spotlight", "shells", "bullets", "rockets", "riflerounds", "grenades", "cartridges", "health", "healthboost", "tinyhealth", "tinyarmour", "greenarmour", "yellowarmour", "quaddamage", @@ -434,9 +341,7 @@ namespace entities }; return i>=0 && size_t(i)clientnum); //add player id @@ -53,91 +48,65 @@ q.put((uchar*)&ip, 3); sendserverinforeply(q); } - - static inline void extinfoteamscore(ucharbuf &p, const char *team, int score) - { + 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) - { + 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 scores; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; - if(ci->state.state!=CS_SPECTATOR && ci->team[0] && scores.htfind(ci->team) < 0) - { + 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) - { + 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: - { + switch(extcmd) { + case EXT_UPTIME: { putint(p, totalsecs); //in seconds break; } - - case EXT_PLAYERSTATS: - { + case EXT_PLAYERSTATS: { int cn = getint(req); //a special player, -1 for all - clientinfo *ci = NULL; - if(cn >= 0) - { + if(cn >= 0) { loopv(clients) if(clients[i]->clientnum == cn) { ci = clients[i]; break; } - if(!ci) - { + 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: - { + case EXT_TEAMSCORE: { extinfoteams(p); break; } - - default: - { + default: { putint(p, EXT_ERROR); break; } } sendserverinforeply(p); } - diff --git a/src/fpsgame/fps.cpp b/src/fpsgame/fps.cpp index da678f6..c74f5f4 100644 --- a/src/fpsgame/fps.cpp +++ b/src/fpsgame/fps.cpp @@ -1,39 +1,28 @@ #include "game.h" -namespace game -{ +namespace game { bool intermission = false; int maptime = 0, maprealtime = 0, maplimit = -1; int respawnent = -1; int lasthit = 0, lastspawnattempt = 0; - int following = -1, followdir = 0; - fpsent *player1 = NULL; // our client vector players; // other clients int savedammo[NUMGUNS]; - bool clientoption(const char *arg) { return false; } - - void taunt() - { + void taunt() { if(player1->state!=CS_ALIVE || player1->physstatelasttaunt<1000) return; player1->lasttaunt = lastmillis; addmsg(N_TAUNT, "rc", player1); } COMMAND(taunt, ""); - - ICOMMAND(getfollow, "", (), - { + ICOMMAND(getfollow, "", (), { fpsent *f = followingplayer(); intret(f ? f->clientnum : -1); }); - - void follow(char *arg) - { - if(arg[0] ? player1->state==CS_SPECTATOR : following>=0) - { + void follow(char *arg) { + if(arg[0] ? player1->state==CS_SPECTATOR : following>=0) { following = arg[0] ? parseplayer(arg) : -1; if(following==player1->clientnum) following = -1; followdir = 0; @@ -41,20 +30,15 @@ namespace game } } COMMAND(follow, "s"); - - void nextfollow(int dir) - { - if(player1->state!=CS_SPECTATOR || clients.empty()) - { + void nextfollow(int dir) { + if(player1->state!=CS_SPECTATOR || clients.empty()) { stopfollowing(); return; } int cur = following >= 0 ? following : (dir < 0 ? clients.length() - 1 : 0); - loopv(clients) - { + loopv(clients) { cur = (cur + dir + clients.length()) % clients.length(); - if(clients[cur] && clients[cur]->state!=CS_SPECTATOR) - { + if(clients[cur] && clients[cur]->state!=CS_SPECTATOR) { if(following<0) conoutf("follow on"); following = cur; followdir = dir; @@ -65,117 +49,85 @@ namespace game } ICOMMAND(nextfollow, "i", (int *dir), nextfollow(*dir < 0 ? -1 : 1)); - const char *getclientmap() { return clientmap; } - - void resetgamestate() - { + void resetgamestate() { clearprojectiles(); clearbouncers(); } - - fpsent *spawnstate(fpsent *d) // reset player state not persistent accross spawns - { + fpsent *spawnstate(fpsent *d) { // reset player state not persistent accross spawns { d->respawn(); d->spawnstate(gamemode); return d; } - - void respawnself() - { + void respawnself() { if(ispaused()) return; - if(m_mp(gamemode)) - { + 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 - { + else { spawnplayer(player1); showscores(false); lasthit = 0; } } - - fpsent *pointatplayer() - { + fpsent *pointatplayer() { loopv(players) if(players[i] != player1 && intersect(players[i], player1->o, worldpos)) return players[i]; return NULL; } - - void stopfollowing() - { + void stopfollowing() { if(following<0) return; following = -1; followdir = 0; conoutf("follow off"); } - - fpsent *followingplayer(fpsent *fallback) - { + fpsent *followingplayer(fpsent *fallback) { if(player1->state!=CS_SPECTATOR || following<0) return fallback; fpsent *target = getclient(following); if(target && target->state!=CS_SPECTATOR) return target; return fallback; } - - fpsent *hudplayer() - { + fpsent *hudplayer() { if(thirdperson && allowthirdperson()) return player1; return followingplayer(player1); } - - void setupcamera() - { + void setupcamera() { fpsent *target = followingplayer(); - if(target) - { + if(target) { player1->yaw = target->yaw; player1->pitch = target->state==CS_DEAD ? 0 : target->pitch; player1->o = target->o; player1->resetinterp(); } } - - bool allowthirdperson(bool msg) - { + bool allowthirdperson(bool msg) { return player1->state==CS_SPECTATOR || player1->state==CS_EDITING || m_edit || !multiplayer(msg); } ICOMMAND(allowthirdperson, "b", (int *msg), intret(allowthirdperson(*msg!=0) ? 1 : 0)); - - bool detachcamera() - { + bool detachcamera() { fpsent *d = hudplayer(); return d->state==CS_DEAD; } - - bool collidecamera() - { - switch(player1->state) - { + bool collidecamera() { + switch(player1->state) { case CS_EDITING: return false; case CS_SPECTATOR: return followingplayer()!=NULL; } return true; } - VARP(smoothmove, 0, 75, 100); VARP(smoothdist, 0, 32, 64); - - void predictplayer(fpsent *d, bool move) - { + void predictplayer(fpsent *d, bool move) { d->o = d->newpos; d->yaw = d->newyaw; d->pitch = d->newpitch; d->roll = d->newroll; - if(move) - { + if(move) { moveplayer(d, 1, false); d->newpos = d->o; } float k = 1.0f - float(lastmillis - d->smoothmillis)/smoothmove; - if(k>0) - { + if(k>0) { d->o.add(vec(d->deltapos).mul(k)); d->yaw += d->deltayaw*k; if(d->yaw<0) d->yaw += 360; @@ -184,57 +136,42 @@ namespace game d->roll += d->deltaroll*k; } } - - void otherplayers(int curtime) - { - loopv(players) - { + void otherplayers(int curtime) { + loopv(players) { fpsent *d = players[i]; if(d == player1 || d->ai) continue; - if(d->state==CS_DEAD && d->ragdoll) moveragdoll(d); - else if(!intermission) - { + else if(!intermission) { if(lastmillis - d->lastaction >= d->gunwait) d->gunwait = 0; if(d->quadmillis) entities::checkquad(curtime, d); } - const int lagtime = totalmillis-d->lastupdate; if(!lagtime || intermission) continue; - else if(lagtime>1000 && d->state==CS_ALIVE) - { + else if(lagtime>1000 && d->state==CS_ALIVE) { d->state = CS_LAGGED; continue; } - if(d->state==CS_ALIVE || d->state==CS_EDITING) - { + if(d->state==CS_ALIVE || d->state==CS_EDITING) { 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); } } - - void checkslowmo() - { + void checkslowmo() { static int lastslowmohealth = 0; server::forcegamespeed(intermission ? 100 : clamp(player1->health, 25, 200)); - if(player1->healthmaxhealth && lastmillis-max(maptime, lastslowmohealth)>player1->health*player1->health/2) - { + if(player1->healthmaxhealth && lastmillis-max(maptime, lastslowmohealth)>player1->health*player1->health/2) { lastslowmohealth = lastmillis; player1->health++; } } - - void updateworld() // main game update loop - { + void updateworld() { // main game update loop { if(!maptime) { maptime = lastmillis; maprealtime = totalmillis; return; } if(!curtime) { gets2c(); if(player1->clientnum>=0) c2sinfo(); return; } - physicsframe(); ai::navigate(); - if(player1->state != CS_DEAD && !intermission) - { + if(player1->state != CS_DEAD && !intermission) { if(player1->quadmillis) entities::checkquad(curtime, player1); } updateweapons(curtime); @@ -242,19 +179,15 @@ namespace game ai::update(); moveragdolls(); gets2c(); - if(connected) - { - if(player1->state == CS_DEAD) - { + if(connected) { + if(player1->state == CS_DEAD) { if(player1->ragdoll) moveragdoll(player1); - else if(lastmillis-player1->lastpain<2000) - { + else if(lastmillis-player1->lastpain<2000) { player1->move = player1->strafe = 0; moveplayer(player1, 10, true); } } - else if(!intermission) - { + else if(!intermission) { if(player1->ragdoll) cleanragdoll(player1); moveplayer(player1, 10, true); swayhudgun(curtime); @@ -263,139 +196,98 @@ namespace game } if(player1->clientnum>=0) c2sinfo(); // do this last, to reduce the effective frame lag } - - float proximityscore(float x, float lower, float upper) - { + float proximityscore(float x, float lower, float upper) { if(x <= lower) return 1.0f; if(x >= upper) return 0.0f; 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) - { + float ratespawn(dynent *d, const extentity &e) { fpsent *p = (fpsent *)d; vec loc = vec(e.o).addz(p->eyeheight); float maxrange = !m_noitems ? 400.0f : 110.0f; float minplayerdist = maxrange; - loopv(players) - { + loopv(players) { const fpsent *o = players[i]; - if(o == p) - { + if(o == p) { if(m_noitems || (o->state != CS_ALIVE && lastmillis - o->lastpain > 3000)) continue; } else if(o->state != CS_ALIVE || isteam(o->team, p->team)) continue; - vec dir = vec(o->o).sub(loc); float dist = dir.squaredlen(); if(dist >= minplayerdist*minplayerdist) continue; dist = sqrtf(dist); dir.mul(1/dist); - // scale actual distance if not in line of sight if(raycube(loc, dir, dist) < dist) dist *= 1.5f; minplayerdist = min(minplayerdist, dist); } return 1.0f - proximityscore(minplayerdist, 80.0f, maxrange); } - - void pickgamespawn(fpsent *d) - { + void pickgamespawn(fpsent *d) { int ent = d == player1 && respawnent >= 0 ? respawnent : -1; findplayerspawn(d, ent, 0); } - - void spawnplayer(fpsent *d) // place at random spawn - { + void spawnplayer(fpsent *d) { // place at random spawn { pickgamespawn(d); spawnstate(d); - if(d==player1) - { + if(d==player1) { if(editmode) d->state = CS_EDITING; else if(d->state != CS_SPECTATOR) d->state = CS_ALIVE; } else d->state = CS_ALIVE; } - VARP(spawnwait, 0, 0, 1000); - - void respawn() - { - if(player1->state==CS_DEAD) - { + void respawn() { + if(player1->state==CS_DEAD) { player1->attacking = false; respawnself(); } } COMMAND(respawn, ""); - // inputs - VARP(attackspawn, 0, 1, 1); - - void doattack(bool on) - { + void doattack(bool on) { if(!connected || intermission) return; if((player1->attacking = on) && attackspawn) respawn(); } - VARP(jumpspawn, 0, 1, 1); - - bool canjump() - { + bool canjump() { if(!connected || intermission) return false; if(jumpspawn) respawn(); return player1->state!=CS_DEAD; } - - bool allowmove(physent *d) - { + bool allowmove(physent *d) { if(d->type!=ENT_PLAYER) return true; return !((fpsent *)d)->lasttaunt || lastmillis-((fpsent *)d)->lasttaunt>=1000; } - VARP(hitsound, 0, 0, 1); - - void damaged(int damage, fpsent *d, fpsent *actor, bool local) - { + void damaged(int damage, fpsent *d, fpsent *actor, bool local) { if((d->state!=CS_ALIVE && d->state != CS_LAGGED && d->state != CS_SPAWNING) || intermission) return; - if(local) damage = d->dodamage(damage); else if(actor==player1) return; - fpsent *h = hudplayer(); - if(h!=player1 && actor==h && d!=actor) - { + if(h!=player1 && actor==h && d!=actor) { if(hitsound && lasthit != lastmillis) playsound(S_HIT); lasthit = lastmillis; } - if(d==h) - { + if(d==h) { damagecompass(damage, actor->o); } damageeffect(damage, d, d!=h); - ai::damaged(d, actor); - if(d->health<=0) { if(local) killed(d, actor); } else if(d==h) playsound(S_PAIN6); else playsound(S_PAIN1+rnd(5), &d->o); } - VARP(deathscore, 0, 1, 1); - - void deathstate(fpsent *d, bool restore) - { + void deathstate(fpsent *d, bool restore) { d->state = CS_DEAD; d->lastpain = lastmillis; if(!restore) d->deaths++; - - if(d==player1) - { + if(d==player1) { if(deathscore) showscores(true); disablezoom(); if(!restore) loopi(NUMGUNS) savedammo[i] = player1->ammo[i]; @@ -403,53 +295,41 @@ namespace game d->roll = 0; playsound(S_DIE1+rnd(2)); } - else - { + else { d->move = d->strafe = 0; d->resetinterp(); d->smoothmillis = 0; playsound(S_DIE1+rnd(2), &d->o); } } - VARP(teamcolorfrags, 0, 1, 1); - /// xolatile: HUD frag messages #define fragmessageduration (2000) - string hudfragger, hudfragged; int hudfraggun, hudfragmillis; - - void sethudfragdata(char *fragger, char *fragged, int gunid) - { + void sethudfragdata(char *fragger, char *fragged, int gunid) { copystring(hudfragger, fragger ? fragger : ""); copystring(hudfragged, fragged); hudfraggun = gunid; hudfragmillis = lastmillis; } - - void killed(fpsent *d, fpsent *actor) - { - if(d->state==CS_EDITING) - { + void killed(fpsent *d, fpsent *actor) { + if(d->state==CS_EDITING) { d->editstate = CS_DEAD; d->deaths++; if(d!=player1) d->resetinterp(); return; } else if((d->state!=CS_ALIVE && d->state != CS_LAGGED && d->state != CS_SPAWNING) || intermission) return; - fpsent *h = followingplayer(player1); int contype = d==h || actor==h ? CON_FRAG_SELF : CON_FRAG_OTHER; const char *dname = "", *aname = ""; - if(m_teammode && teamcolorfrags) - { + if(m_teammode && teamcolorfrags) { dname = teamcolorname(d, "you"); aname = teamcolorname(actor, "you"); } - else - { + else { dname = colorname(d, NULL, "", "", "you"); aname = colorname(actor, NULL, "", "", "you"); } @@ -457,22 +337,18 @@ namespace game conoutf(contype, "\f2%s got killed by %s!", dname, aname); else if(d==actor || actor->type==ENT_INANIMATE) conoutf(contype, "\f2%s suicided%s", dname, d==player1 ? "!" : ""); - else if(isteam(d->team, actor->team)) - { + else if(isteam(d->team, actor->team)) { contype |= CON_TEAMKILL; if(actor==player1) conoutf(contype, "\f6%s fragged a teammate (%s)", aname, dname); else if(d==player1) conoutf(contype, "\f6%s got fragged by a teammate (%s)", dname, aname); else conoutf(contype, "\f2%s fragged a teammate (%s)", aname, dname); } - else - { - if(d==player1) - { + else { + if(d==player1) { conoutf(contype, "\f2%s got fragged by %s", dname, aname); sethudfragdata(actor->name, d->name, actor->gunselect); } - else - { + else { conoutf(contype, "\f2%s fragged %s", aname, dname); sethudfragdata(actor->name, d->name, actor->gunselect); } @@ -480,16 +356,12 @@ namespace game deathstate(d); ai::killed(d, actor); } - - void timeupdate(int secs) - { + void timeupdate(int secs) { server::timeupdate(secs); - if(secs > 0) - { + if(secs > 0) { maplimit = lastmillis + secs*1000; } - else - { + else { intermission = true; player1->attacking = false; conoutf(CON_GAMEINFO, "\f2intermission:"); @@ -497,36 +369,26 @@ namespace game conoutf(CON_GAMEINFO, "\f2player frags: %d, deaths: %d", player1->frags, player1->deaths); 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"); } } - ICOMMAND(getfrags, "", (), intret(player1->frags)); ICOMMAND(getflags, "", (), intret(player1->flags)); ICOMMAND(getdeaths, "", (), intret(player1->deaths)); ICOMMAND(getaccuracy, "", (), intret((player1->totaldamage*100)/max(player1->totalshots, 1))); ICOMMAND(gettotaldamage, "", (), intret(player1->totaldamage)); ICOMMAND(gettotalshots, "", (), intret(player1->totalshots)); - vector clients; - - fpsent *newclient(int cn) // ensure valid entity - { - if(cn < 0 || cn > max(0xFF, MAXCLIENTS + MAXBOTS)) - { + fpsent *newclient(int cn) { // ensure valid entity { + if(cn < 0 || cn > max(0xFF, MAXCLIENTS + MAXBOTS)) { neterr("clientnum", false); return NULL; } - if(cn == player1->clientnum) return player1; - while(cn >= clients.length()) clients.add(NULL); - if(!clients[cn]) - { + if(!clients[cn]) { fpsent *d = new fpsent; d->clientnum = cn; clients[cn] = d; @@ -534,18 +396,13 @@ namespace game } return clients[cn]; } - - fpsent *getclient(int cn) // ensure valid entity - { + fpsent *getclient(int cn) { // ensure valid entity { if(cn == player1->clientnum) return player1; return clients.inrange(cn) ? clients[cn] : NULL; } - - void clientdisconnected(int cn, bool notify) - { + void clientdisconnected(int cn, bool notify) { if(!clients.inrange(cn)) return; - if(following==cn) - { + if(following==cn) { if(followdir) nextfollow(followdir); else stopfollowing(); } @@ -560,32 +417,22 @@ namespace game DELETEP(clients[cn]); cleardynentcache(); } - - void clearclients(bool notify) - { + void clearclients(bool notify) { loopv(clients) if(clients[i]) clientdisconnected(i, notify); } - - void initclient() - { + void initclient() { player1 = spawnstate(new fpsent); filtertext(player1->name, "Anonymous", false, false, MAXNAMELEN); players.add(player1); } - VARP(showmodeinfo, 0, 1, 1); - - void startgame() - { + void startgame() { clearprojectiles(); clearbouncers(); clearragdolls(); - clearteaminfo(); - // reset perma-state - loopv(players) - { + loopv(players) { fpsent *d = players[i]; d->frags = d->flags = 0; d->deaths = 0; @@ -596,106 +443,74 @@ namespace game d->lifesequence = -1; d->respawned = d->suicided = -2; } - intermission = false; maptime = maprealtime = 0; maplimit = -1; - conoutf(CON_GAMEINFO, "\f2game mode is %s", server::modename(gamemode)); - const char *info = m_valid(gamemode) ? gamemodes[gamemode - STARTGAMEMODE].info : NULL; if(showmodeinfo && info) conoutf(CON_GAMEINFO, "\f0%s", info); - showscores(false); disablezoom(); lasthit = 0; - execident("mapstart"); } - - void loadingmap(const char *name) - { + void loadingmap(const char *name) { execident("playsong"); } - - void startmap(const char *name) // called just after a map load - { + void startmap(const char *name) { // called just after a map load { pwreset(); ai::savewaypoints(); ai::clearwaypoints(true); - respawnent = -1; // so we don't respawn at an old spot if(!m_mp(gamemode)) spawnplayer(player1); else findplayerspawn(player1, -1); entities::resetspawns(); copystring(clientmap, name ? name : ""); - sendmapinfo(); } - - const char *getmapinfo() - { + const char *getmapinfo() { return showmodeinfo && m_valid(gamemode) ? gamemodes[gamemode - STARTGAMEMODE].info : NULL; } - - const char *getscreenshotinfo() - { + const char *getscreenshotinfo() { return server::modename(gamemode, NULL); } - - void physicstrigger(physent *d, bool local, int floorlevel, int material) - { + void physicstrigger(physent *d, bool local, int floorlevel, int material) { if(d->type==ENT_INANIMATE) return; if (floorlevel>0) { if(d==player1 || d->type!=ENT_PLAYER || ((fpsent *)d)->ai) msgsound(S_JUMP, d); } else if(floorlevel<0) { if(d==player1 || d->type!=ENT_PLAYER || ((fpsent *)d)->ai) msgsound(S_LAND, d); } } - - void dynentcollide(physent *d, physent *o, const vec &dir) - { + void dynentcollide(physent *d, physent *o, const vec &dir) { return; } - - void msgsound(int n, physent *d) - { - if(!d || d==player1) - { + void msgsound(int n, physent *d) { + if(!d || d==player1) { addmsg(N_SOUND, "ci", d, n); playsound(n); } - else - { + else { if(d->type==ENT_PLAYER && ((fpsent *)d)->ai) addmsg(N_SOUND, "ci", d, n); playsound(n, &d->o); } } - int numdynents() { return players.length(); } - - dynent *iterdynents(int i) - { + dynent *iterdynents(int i) { if(iname; if(alt && d != player1 && !strcmp(name, alt)) return true; loopv(players) if(d!=players[i] && !strcmp(name, players[i]->name)) return true; return false; } - static string cname[3]; static int cidx = 0; - - const char *colorname(fpsent *d, const char *name, const char *prefix, const char *suffix, const char *alt) - { + const char *colorname(fpsent *d, const char *name, const char *prefix, const char *suffix, const char *alt) { if(!name) name = alt && d == player1 ? alt : d->name; bool dup = !name[0] || duplicatename(d, name, alt) || d->aitype != AI_NONE; - if(dup || prefix[0] || suffix[0]) - { + if(dup || prefix[0] || suffix[0]) { cidx = (cidx+1)%3; if(dup) formatstring(cname[cidx], d->aitype == AI_NONE ? "%s%s \fs\f5(%d)\fr%s" : "%s%s \fs\f5[%d]\fr%s", prefix, name, d->clientnum, suffix); else formatstring(cname[cidx], "%s%s%s", prefix, name, suffix); @@ -703,58 +518,40 @@ namespace game } return name; } - VARP(teamcolortext, 0, 1, 1); - - const char *teamcolorname(fpsent *d, const char *alt) - { + const char *teamcolorname(fpsent *d, const char *alt) { if(!teamcolortext || !m_teammode || d->state==CS_SPECTATOR) return colorname(d, NULL, "", "", alt); return colorname(d, NULL, isteam(d->team, player1->team) ? "\fs\f1" : "\fs\f3", "\fr", alt); } - - const char *teamcolor(const char *name, bool sameteam, const char *alt) - { + const char *teamcolor(const char *name, bool sameteam, const char *alt) { if(!teamcolortext || !m_teammode) return sameteam || !alt ? name : alt; cidx = (cidx+1)%3; formatstring(cname[cidx], sameteam ? "\fs\f1%s\fr" : "\fs\f3%s\fr", sameteam || !alt ? name : alt); return cname[cidx]; } - - const char *teamcolor(const char *name, const char *team, const char *alt) - { + const char *teamcolor(const char *name, const char *team, const char *alt) { return teamcolor(name, team && isteam(team, player1->team), alt); } - VARP(teamsounds, 0, 1, 1); - - void teamsound(bool sameteam, int n, const vec *loc) - { + void teamsound(bool sameteam, int n, const vec *loc) { playsound(n, loc, NULL, teamsounds ? (m_teammode && sameteam ? SND_USE_ALT : SND_NO_ALT) : 0); } - - void teamsound(fpsent *d, int n, const vec *loc) - { + void teamsound(fpsent *d, int n, const vec *loc) { teamsound(isteam(d->team, player1->team), n, loc); } - - void suicide(physent *d) - { - if(d==player1 || (d->type==ENT_PLAYER && ((fpsent *)d)->ai)) - { + void suicide(physent *d) { + if(d==player1 || (d->type==ENT_PLAYER && ((fpsent *)d)->ai)) { if(d->state!=CS_ALIVE) return; fpsent *pl = (fpsent *)d; if(!m_mp(gamemode)) killed(pl, pl); - else - { + 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)); - - void drawicon(int icon, float x, float y, float sz) - { + void drawicon(int icon, float x, float y, float sz) { settexture("packages/hud/items.png"); float tsz = 0.25f, tx = tsz*(icon%4), ty = tsz*(icon/4); gle::defvertex(2); @@ -766,11 +563,8 @@ namespace game gle::attribf(x+sz, y+sz); gle::attribf(tx+tsz, ty+tsz); gle::end(); } - - float abovegameplayhud(int w, int h) - { - switch(hudplayer()->state) - { + float abovegameplayhud(int w, int h) { + switch(hudplayer()->state) { case CS_EDITING: case CS_SPECTATOR: return 1; @@ -778,61 +572,47 @@ namespace game return 1650.0f/1800.0f; } } - int ammohudup[3] = { GUN_CG, GUN_RL, GUN_GL }, ammohuddown[3] = { GUN_RIFLE, GUN_SG, GUN_PISTOL }, ammohudcycle[7] = { -1, -1, -1, -1, -1, -1, -1 }; - - ICOMMAND(ammohudup, "V", (tagval *args, int numargs), - { + ICOMMAND(ammohudup, "V", (tagval *args, int numargs), { loopi(3) ammohudup[i] = i < numargs ? getweapon(args[i].getstr()) : -1; }); - - ICOMMAND(ammohuddown, "V", (tagval *args, int numargs), - { + ICOMMAND(ammohuddown, "V", (tagval *args, int numargs), { loopi(3) ammohuddown[i] = i < numargs ? getweapon(args[i].getstr()) : -1; }); - - ICOMMAND(ammohudcycle, "V", (tagval *args, int numargs), - { + ICOMMAND(ammohudcycle, "V", (tagval *args, int numargs), { loopi(7) ammohudcycle[i] = i < numargs ? getweapon(args[i].getstr()) : -1; }); - VARP(ammohud, 0, 1, 1); - - void drawammohud(fpsent *d) - { + void drawammohud(fpsent *d) { float x = HICON_X + 2*HICON_STEP, y = HICON_Y, sz = HICON_SIZE; pushhudmatrix(); hudmatrix.scale(1/3.2f, 1/3.2f, 1); flushhudmatrix(); float xup = (x+sz)*3.2f, yup = y*3.2f + 0.1f*sz; - loopi(3) - { + loopi(3) { int gun = ammohudup[i]; if(gun < GUN_FIST || gun > GUN_PISTOL || gun == d->gunselect || !d->ammo[gun]) continue; drawicon(HICON_FIST+gun, xup, yup, sz); yup += sz; } float xdown = x*3.2f - sz, ydown = (y+sz)*3.2f - 0.1f*sz; - loopi(3) - { + loopi(3) { int gun = ammohuddown[3-i-1]; if(gun < GUN_FIST || gun > GUN_PISTOL || gun == d->gunselect || !d->ammo[gun]) continue; ydown -= sz; drawicon(HICON_FIST+gun, xdown, ydown, sz); } int offset = 0, num = 0; - loopi(7) - { + loopi(7) { int gun = ammohudcycle[i]; if(gun < GUN_FIST || gun > GUN_PISTOL) continue; if(gun == d->gunselect) offset = i + 1; else if(d->ammo[gun]) num++; } float xcycle = (x+sz/2)*3.2f + 0.5f*num*sz, ycycle = y*3.2f-sz; - loopi(7) - { + loopi(7) { int gun = ammohudcycle[(i + offset)%7]; if(gun < GUN_FIST || gun > GUN_PISTOL || gun == d->gunselect || !d->ammo[gun]) continue; xcycle -= sz; @@ -840,9 +620,7 @@ namespace game } pophudmatrix(); } - - void hudquad(float x, float y, float w, float h, float r = 1, float g = 1, float b = 1, float tx = 0, float ty = 0, float tw = 1, float th = 1) - { + void hudquad(float x, float y, float w, float h, float r = 1, float g = 1, float b = 1, float tx = 0, float ty = 0, float tw = 1, float th = 1) { gle::defvertex(2); gle::deftexcoord0(); gle::colorf(r, g, b); @@ -853,20 +631,15 @@ namespace game gle::attribf(x+w, y+h); gle::attribf(tx + tw, ty + th); gle::end(); } - VARP(healthcolors, 0, 1, 1); - VARP(hudhealth, 0, 1, 1); FVARP(hudhealthx, 0, 0, 1); FVARP(hudhealthy, 0, 1, 1); FVARP(hudhealthscale, 0.1, 1.0, 1.0); - - void drawhudhealth(fpsent *d, int w, int h) - { + void drawhudhealth(fpsent *d, int w, int h) { pushhudmatrix(); hudmatrix.scale(hudhealthscale, hudhealthscale, 1); flushhudmatrix(); - bvec healthcolor = bvec::hexcolor(healthcolors && !m_insta ? (d->state==CS_DEAD ? 0x808080 : (d->health<=25 ? 0xc02020 : @@ -889,21 +662,16 @@ namespace game defformatstring(health, "%d", d->state==CS_DEAD ? 0 : d->health); float tw=0, th=0; text_boundsf(health, tw, th); draw_text(health, offset.x+(125*proportion-tw)/2, offset.y+(healthbarh-th)/2, healthcolor.r, healthcolor.g, healthcolor.b); - pophudmatrix(); } - VARP(hudmaxhealth, 0, 1, 1); FVARP(hudmaxhealthx, 0, 0.207, 1); FVARP(hudmaxhealthy, 0, 0.97, 1); FVARP(hudmaxhealthscale, 0.1, 1.0, 1.0); - - void drawhudmaxhealth(fpsent *d, int w, int h) - { + void drawhudmaxhealth(fpsent *d, int w, int h) { pushhudmatrix(); hudmatrix.scale(hudmaxhealthscale, hudmaxhealthscale, 1); flushhudmatrix(); - const float proportion = (w/15.0f)/160.0f; const float healthboostw = 160*proportion; const float healthboosth = 78*proportion; @@ -917,23 +685,17 @@ namespace game settexture("packages/hud/health_boost_quad.png"); hudquad(offset.x, offset.y, healthboostw, healthboosth); } - pophudmatrix(); } - VARP(armourcolors, 0, 1, 1); - VARP(hudarmour, 0, 1, 1); FVARP(hudarmourx, 0, 1, 1); FVARP(hudarmoury, 0, 1, 1); FVARP(hudarmourscale, 0.1, 1.0, 1.0); - - void drawhudarmour(fpsent *d, int w, int h) - { + void drawhudarmour(fpsent *d, int w, int h) { pushhudmatrix(); hudmatrix.scale(hudarmourscale, hudarmourscale, 1); flushhudmatrix(); - bvec armourcolor = bvec::hexcolor(d->armourtype == A_BLUE ? 0x83ade5 : (d->armourtype == A_GREEN ? 0x77f29e : (d->armourtype == A_YELLOW ? 0xf5f19b : 0xffffff))); const float proportion = (w/4.0f)/600.0f; const float armourbarw = 600*proportion; @@ -951,25 +713,19 @@ namespace game defformatstring(armour, "%d", d->state==CS_DEAD ? 0 : d->armour); float tw=0, th=0; text_boundsf(armour, tw, th); draw_text(armour, offset.x+(2*(600-63)*proportion-tw)/2, offset.y+(armourbarh-th)/2, armourcolor.r, armourcolor.g, armourcolor.b); - pophudmatrix(); } - - void drawhudicons(fpsent *d, int w, int h) - { + void drawhudicons(fpsent *d, int w, int h) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(hudhealth) drawhudhealth(d, w, h); if(hudmaxhealth) drawhudmaxhealth(d, w, h); if(hudarmour) drawhudarmour(d, w, h); - if(d->state!=CS_DEAD) { drawicon(HICON_FIST+d->gunselect, HICON_X + 2*HICON_STEP, HICON_Y); if(ammohud) drawammohud(d); } } - VARP(gameclock, 0, 0, 1); FVARP(gameclockscale, 1e-3f, 0.75f, 1e3f); HVARP(gameclockcolour, 0, 0xFFFFFF, 0xFFFFFF); @@ -978,34 +734,25 @@ namespace game VARP(gameclockalign, -1, 0, 1); FVARP(gameclockx, 0, 0.50f, 1); FVARP(gameclocky, 0, 0.03f, 1); - - void drawgameclock(int w, int h) - { + void drawgameclock(int w, int h) { int secs = max(maplimit-lastmillis + 999, 0)/1000, mins = secs/60; secs %= 60; - defformatstring(buf, "%d:%02d", mins, secs); int tw = 0, th = 0; text_bounds(buf, tw, th); - vec2 offset = vec2(gameclockx, gameclocky).mul(vec2(w, h).div(gameclockscale)); if(gameclockalign == 1) offset.x -= tw; else if(gameclockalign == 0) offset.x -= tw/2.0f; offset.y -= th/2.0f; - pushhudmatrix(); hudmatrix.scale(gameclockscale, gameclockscale, 1); flushhudmatrix(); - int color = mins < 1 ? gameclocklowcolour : gameclockcolour; draw_text(buf, int(offset.x), int(offset.y), (color>>16)&0xFF, (color>>8)&0xFF, color&0xFF, gameclockalpha); - pophudmatrix(); } - extern int hudscore; extern void drawhudscore(int w, int h); - VARP(ammobar, 0, 0, 1); VARP(ammobaralign, -1, 0, 1); VARP(ammobarhorizontal, 0, 0, 1); @@ -1017,77 +764,58 @@ namespace game FVARP(ammobarx, 0, 0.025f, 1.0f); FVARP(ammobary, 0, 0.5f, 1.0f); FVARP(ammobarscale, 0.1f, 0.5f, 1.0f); - - void drawammobarcounter(const vec2 ¢er, const fpsent *p, int gun) - { + void drawammobarcounter(const vec2 ¢er, const fpsent *p, int gun) { vec2 icondrawpos = vec2(center).sub(HICON_SIZE / 2); int alpha = p->ammo[gun] ? 0xFF : 0x7F; gle::color(bvec(0xFF, 0xFF, 0xFF), alpha); drawicon(HICON_FIST + gun, icondrawpos.x, icondrawpos.y); - int fw, fh; text_bounds("000", fw, fh); float labeloffset = HICON_SIZE / 2.0f + ammobarcountsep + ammobarcountscale * (ammobarhorizontal ? fh : fw) / 2.0f; vec2 offsetdir = (ammobarhorizontal ? vec2(0, 1) : vec2(1, 0)).mul(ammobarflip ? -1 : 1); vec2 labelorigin = vec2(offsetdir).mul(labeloffset).add(center); - pushhudmatrix(); hudmatrix.translate(labelorigin.x, labelorigin.y, 0); hudmatrix.scale(ammobarcountscale, ammobarcountscale, 1); flushhudmatrix(); - defformatstring(label, "%d", p->ammo[gun]); int tw, th; text_bounds(label, tw, th); vec2 textdrawpos = vec2(-tw, -th).div(2); float ammoratio = (float)p->ammo[gun] / itemstats[gun-GUN_SG].add; bvec color = bvec::hexcolor(p->ammo[gun] == 0 || ammoratio >= 1.0f ? 0xFFFFFF : (ammoratio >= 0.5f ? 0xFFC040 : 0xFF0000)); draw_text(label, textdrawpos.x, textdrawpos.y, color.r, color.g, color.b, alpha); - pophudmatrix(); } - - static inline bool ammobargunvisible(const fpsent *d, int gun) - { + static inline bool ammobargunvisible(const fpsent *d, int gun) { return d->ammo[gun] > 0 || d->gunselect == gun; } - - void drawammobar(int w, int h, fpsent *p) - { + void drawammobar(int w, int h, fpsent *p) { if(m_insta) return; - int NUMPLAYERGUNS = GUN_PISTOL - GUN_SG + 1; int numvisibleguns = NUMPLAYERGUNS; if(ammobarhideempty) loopi(NUMPLAYERGUNS) if(!ammobargunvisible(p, GUN_SG + i)) numvisibleguns--; - vec2 origin = vec2(ammobarx, ammobary).mul(vec2(w, h).div(ammobarscale)); vec2 offsetdir = ammobarhorizontal ? vec2(1, 0) : vec2(0, 1); float stepsize = HICON_SIZE + ammobarsep; float initialoffset = (ammobaralign - 1) * (numvisibleguns - 1) * stepsize / 2; - pushhudmatrix(); hudmatrix.scale(ammobarscale, ammobarscale, 1); flushhudmatrix(); - int numskippedguns = 0; - loopi(NUMPLAYERGUNS) if(ammobargunvisible(p, GUN_SG + i) || !ammobarhideempty) - { + loopi(NUMPLAYERGUNS) if(ammobargunvisible(p, GUN_SG + i) || !ammobarhideempty) { float offset = initialoffset + (i - numskippedguns) * stepsize; vec2 drawpos = vec2(offsetdir).mul(offset).add(origin); drawammobarcounter(drawpos, p, GUN_SG + i); } else numskippedguns++; - pophudmatrix(); } - VARP(speedometer, 0, 1, 1); FVARP(speedometerx, 0.0, 0.5, 1.0); FVARP(speedometery, 0.0, 0.6, 1.0); FVARP(speedometerscale, 0.1, 0.5, 1.0); VARP(speedometercolor, 0, 1, 1); FVARP(speedometeralpha, 0.0, 0.5, 1.0); - - void drawspeedometer(fpsent *d, int w, int h) - { + void drawspeedometer(fpsent *d, int w, int h) { int speedforreal = (int) (sqrtf(d->vel.squaredlen()) + 1.0f); speedforreal = (speedforreal == 1) ? 0 : speedforreal; vec colour = vec(255, 255, 255); @@ -1101,35 +829,26 @@ namespace game else if (speedforreal>180 && speedforreal<=240) colour = vec(90, 180, 60); else colour = vec(30, 240, 30); } - defformatstring(speedstring, "%d", speedforreal); text_boundsf(speedstring, realw, realh); vec2 offset = vec2(speedometerx, speedometery).mul(vec2(w, h).div(speedometerscale)); offset.x -= realw/2.0f; offset.y -= realh/2.0f; - pushhudmatrix(); hudmatrix.scale(speedometerscale, speedometerscale, 1); flushhudmatrix(); - const int speedow = 220; const int speedoh = 101; settexture("packages/hud/speedometer.png"); hudquad(offset.x+realw/2.0f-speedow/2, offset.y+realh/2.0f-speedoh/2, speedow, speedoh); - draw_text(speedstring, int(offset.x), int(offset.y), colour.x, colour.y, colour.z, (int)(speedometeralpha*255.0f)); - pophudmatrix(); } - - void gameplayhud(int w, int h) - { + void gameplayhud(int w, int h) { pushhudmatrix(); hudmatrix.scale(h/1800.0f, h/1800.0f, 1); flushhudmatrix(); - - if(player1->state==CS_SPECTATOR) - { + if(player1->state==CS_SPECTATOR) { int pw, ph, tw, th, fw, fh; text_bounds(" ", pw, ph); text_bounds("SPECTATOR", tw, th); @@ -1138,36 +857,25 @@ namespace game text_bounds(f ? colorname(f) : " ", fw, fh); fh = max(fh, ph); draw_text("SPECTATOR", w*1800/h - tw - pw, 1650 - th - fh); - if(f) - { + if(f) { int color = statuscolor(f, 0xFFFFFF); draw_text(colorname(f), w*1800/h - fw - pw, 1650 - fh, (color>>16)&0xFF, (color>>8)&0xFF, color&0xFF); } } - fpsent *d = hudplayer(); - pophudmatrix(); - if(d->state!=CS_EDITING && d->state!=CS_SPECTATOR) drawhudicons(d, w, h); - - if(d->state!=CS_EDITING && d->state!=CS_SPECTATOR && d->state!=CS_DEAD) - { + if(d->state!=CS_EDITING && d->state!=CS_SPECTATOR && d->state!=CS_DEAD) { if(ammobar) drawammobar(w, h, d); if(speedometer) drawspeedometer(d, w, h); } - - if(!m_edit) - { + if(!m_edit) { if(gameclock) drawgameclock(w, h); if(hudscore) drawhudscore(w, h); } - /// Frag message. - - if((hudfragmillis+fragmessageduration > lastmillis) && (lastmillis>fragmessageduration)) - { + if((hudfragmillis+fragmessageduration > lastmillis) && (lastmillis>fragmessageduration)) { vec2 center = vec2(0.5*w, 0.2*h); float width = 0, height = 0; pushhudmatrix(); @@ -1180,69 +888,49 @@ namespace game pophudmatrix(); } } - - int clipconsole(int w, int h) - { + int clipconsole(int w, int h) { return 0; } - VARP(teamcrosshair, 0, 1, 1); VARP(hitcrosshair, 0, 425, 1000); - - const char *defaultcrosshair(int index) - { - switch(index) - { + const char *defaultcrosshair(int index) { + switch(index) { case 2: return "data/hit.png"; case 1: return "data/teammate.png"; default: return "data/crosshair.png"; } } - - int selectcrosshair(vec &color) - { + int selectcrosshair(vec &color) { fpsent *d = hudplayer(); if(d->state==CS_SPECTATOR || d->state==CS_DEAD) return -1; - if(d->state!=CS_ALIVE) return 0; - int crosshair = 0; if(lasthit && lastmillis - lasthit < hitcrosshair) crosshair = 2; - else if(teamcrosshair) - { + else if(teamcrosshair) { dynent *o = intersectclosest(d->o, worldpos, d); - if(o && o->type==ENT_PLAYER && isteam(((fpsent *)o)->team, d->team)) - { + if(o && o->type==ENT_PLAYER && isteam(((fpsent *)o)->team, d->team)) { crosshair = 1; color = vec(0, 0, 1); } } - - if(crosshair!=1 && !editmode && !m_insta) - { + if(crosshair!=1 && !editmode && !m_insta) { if(d->health<=25) color = vec(1, 0, 0); else if(d->health<=50) color = vec(1, 0.5f, 0); } if(d->gunwait) color.mul(0.5f); return crosshair; } - - void lighteffects(dynent *e, vec &color, vec &dir) - { + void lighteffects(dynent *e, vec &color, vec &dir) { #if 0 fpsent *d = (fpsent *)e; - if(d->state!=CS_DEAD && d->quadmillis) - { + if(d->state!=CS_DEAD && d->quadmillis) { float t = 0.5f + 0.5f*sinf(2*M_PI*lastmillis/1000.0f); color.y = color.y*(1-t) + t; } #endif } - - int maxsoundradius(int n) - { - switch(n) - { + int maxsoundradius(int n) { + switch(n) { case S_JUMP: case S_LAND: case S_WEAPLOAD: @@ -1258,11 +946,9 @@ namespace game return 500; } } - - bool serverinfostartcolumn(g3d_gui *g, int i) - { + bool serverinfostartcolumn(g3d_gui *g, int i) { static const char * const names[] = { "ping ", "players ", "mode ", "map ", "time ", "master ", "host ", "port ", "description " }; - static const float struts[] = { 7, 7, 12.5f, 14, 7, 8, 14, 7, 24.5f }; + static const float struts[] = { 7, 7, 12.5f, 14, 7, 8, 14, 7, 24.5f }; if(size_t(i) >= sizeof(names)/sizeof(names[0])) return false; g->pushlist(); g->text(names[i], 0xFFFF80, !i ? " " : NULL); @@ -1270,34 +956,23 @@ namespace game g->mergehits(true); return true; } - - void serverinfoendcolumn(g3d_gui *g, int i) - { + void serverinfoendcolumn(g3d_gui *g, int i) { g->mergehits(false); g->column(i); g->poplist(); } - - const char *mastermodecolor(int n, const char *unknown) - { + const char *mastermodecolor(int n, const char *unknown) { return (n>=MM_START && size_t(n-MM_START)=MM_START && size_t(n-MM_START) &attr, int np) - { - if(ping < 0 || attr.empty() || attr[0]!=PROTOCOL_VERSION) - { - switch(i) - { + bool serverinfoentry(g3d_gui *g, int i, const char *name, int port, const char *sdesc, const char *map, int ping, const vector &attr, int np) { + if(ping < 0 || attr.empty() || attr[0]!=PROTOCOL_VERSION) { + switch(i) { case 0: if(g->button(" ", 0xFFFFDD, "serverunk")&G3D_UP) return true; break; - case 1: case 2: case 3: @@ -1305,18 +980,14 @@ namespace game case 5: if(g->button(" ", 0xFFFFDD)&G3D_UP) return true; break; - case 6: if(g->buttonf("%s ", 0xFFFFDD, NULL, name)&G3D_UP) return true; break; - case 7: if(g->buttonf("%d ", 0xFFFFDD, NULL, port)&G3D_UP) return true; break; - case 8: - if(ping < 0) - { + if(ping < 0) { if(g->button(sdesc, 0xFFFFDD)&G3D_UP) return true; } else if(g->buttonf("[%s protocol] ", 0xFFFFDD, NULL, attr.empty() ? "unknown" : (attr[0] < PROTOCOL_VERSION ? "older" : "newer"))&G3D_UP) return true; @@ -1324,35 +995,26 @@ namespace game } return false; } - - switch(i) - { - case 0: - { + switch(i) { + case 0: { const char *icon = attr.inrange(3) && np >= attr[3] ? "serverfull" : (attr.inrange(4) ? mastermodeicon(attr[4], "serverunk") : "serverunk"); if(g->buttonf("%d ", 0xFFFFDD, icon, ping)&G3D_UP) return true; break; } - case 1: - if(attr.length()>=4) - { + if(attr.length()>=4) { if(g->buttonf(np >= attr[3] ? "\f3%d/%d " : "%d/%d ", 0xFFFFDD, NULL, np, attr[3])&G3D_UP) return true; } else if(g->buttonf("%d ", 0xFFFFDD, NULL, np)&G3D_UP) return true; break; - case 2: if(g->buttonf("%s ", 0xFFFFDD, NULL, attr.length()>=2 ? server::modename(attr[1], "") : "")&G3D_UP) return true; break; - case 3: if(g->buttonf("%.25s ", 0xFFFFDD, NULL, map)&G3D_UP) return true; break; - case 4: - if(attr.length()>=3 && attr[2] > 0) - { + if(attr.length()>=3 && attr[2] > 0) { int secs = clamp(attr[2], 0, 59*60+59), mins = secs/60; secs %= 60; @@ -1363,36 +1025,28 @@ namespace game case 5: if(g->buttonf("%s%s ", 0xFFFFDD, NULL, attr.length()>=5 ? mastermodecolor(attr[4], "") : "", attr.length()>=5 ? server::mastermodename(attr[4], "") : "")&G3D_UP) return true; break; - case 6: if(g->buttonf("%s ", 0xFFFFDD, NULL, name)&G3D_UP) return true; break; - case 7: if(g->buttonf("%d ", 0xFFFFDD, NULL, port)&G3D_UP) return true; break; - case 8: if(g->buttonf("%.25s", 0xFFFFDD, NULL, sdesc)&G3D_UP) return true; break; } return false; } - // any data written into this vector will get saved with the map data. Must take care to do own versioning, and endianess if applicable. Will not get called when loading maps from other games, so provide defaults. void writegamedata(vector &extras) {} void readgamedata(vector &extras) {} - const char *savedconfig() { return "config.cfg"; } const char *restoreconfig() { return "restore.cfg"; } const char *defaultconfig() { return "data/defaults.cfg"; } const char *autoexec() { return "autoexec.cfg"; } const char *savedservers() { return "servers.cfg"; } - - void loadconfigs() - { + void loadconfigs() { execident("playsong"); - execfile("auth.cfg", false); } } diff --git a/src/fpsgame/game.h b/src/fpsgame/game.h index 3cdbba3..974f1f3 100644 --- a/src/fpsgame/game.h +++ b/src/fpsgame/game.h @@ -5,8 +5,7 @@ // console message types -enum -{ +enum { CON_CHAT = 1<<8, CON_TEAMCHAT = 1<<9, CON_GAMEINFO = 1<<10, @@ -20,8 +19,7 @@ enum #define DNF 100.0f // for normalized vectors #define DVELF 1.0f // for playerspeed based velocity vectors -enum // static entity types -{ +enum { // static entity types { NOTUSED = ET_EMPTY, // entity slot not in use in map LIGHT = ET_LIGHT, // lightsource, attr1 = radius, attr2 = intensity MAPMODEL = ET_MAPMODEL, // attr1 = angle, attr2 = idx @@ -41,10 +39,9 @@ enum // static entity types }; enum { GUN_FIST = 0, GUN_SG, GUN_CG, GUN_RL, GUN_RIFLE, GUN_GL, GUN_PISTOL, NUMGUNS }; -enum { A_BLUE, A_GREEN, A_YELLOW }; // armour types... take 20/40/60 % off +enum { A_BLUE, A_GREEN, A_YELLOW }; // armour types... take 20/40/60 % off INCORRECT! -enum -{ +enum { M_TEAM = 1<<0, M_NOITEMS = 1<<1, M_NOAMMO = 1<<2, @@ -56,21 +53,20 @@ enum M_LOBBY = 1<<15 }; -static struct gamemodeinfo -{ +static struct gamemodeinfo { const char *name; int flags; const char *info; -} gamemodes[] = -{ - { "demo", M_DEMO | M_LOCAL, NULL}, - { "ffa", M_LOBBY, "Free For All: Collect items for ammo. Frag everyone to score points." }, - { "coop edit", M_EDIT, "Cooperative Editing: Edit maps with multiple players simultaneously." }, - { "teamplay", M_TEAM, "Teamplay: Collect items for ammo. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, - { "instagib", M_NOITEMS | M_INSTA, "Instagib: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag everyone to score points." }, - { "insta team", M_NOITEMS | M_INSTA | M_TEAM, "Instagib Team: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, - { "efficiency", M_NOITEMS | M_EFFICIENCY, "Efficiency: You spawn with all weapons and armour. There are no items. Frag everyone to score points." }, - { "effic team", M_NOITEMS | M_EFFICIENCY | M_TEAM, "Efficiency Team: You spawn with all weapons and armour. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, +} gamemodes[] = { + { + "demo", M_DEMO | M_LOCAL, NULL}, { + "ffa", M_LOBBY, "Free For All: Collect items for ammo. Frag everyone to score points." }, { + "coop edit", M_EDIT, "Cooperative Editing: Edit maps with multiple players simultaneously." }, { + "teamplay", M_TEAM, "Teamplay: Collect items for ammo. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, { + "instagib", M_NOITEMS | M_INSTA, "Instagib: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag everyone to score points." }, { + "insta team", M_NOITEMS | M_INSTA | M_TEAM, "Instagib Team: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, { + "efficiency", M_NOITEMS | M_EFFICIENCY, "Efficiency: You spawn with all weapons and armour. There are no items. Frag everyone to score points." }, { + "effic team", M_NOITEMS | M_EFFICIENCY | M_TEAM, "Efficiency Team: You spawn with all weapons and armour. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, }; #define STARTGAMEMODE (-1) @@ -98,13 +94,12 @@ static struct gamemodeinfo enum { MM_AUTH = -1, MM_OPEN = 0, MM_VETO, MM_LOCKED, MM_PRIVATE, MM_PASSWORD, MM_START = MM_AUTH }; -static const char * const mastermodenames[] = { "auth", "open", "veto", "locked", "private", "password" }; +static const char * const mastermodenames[] = { "auth", "open", "veto", "locked", "private", "password" }; static const char * const mastermodecolors[] = { "", "\f0", "\f2", "\f2", "\f3", "\f3" }; -static const char * const mastermodeicons[] = { "server", "server", "serverlock", "serverlock", "serverpriv", "serverpriv" }; +static const char * const mastermodeicons[] = { "server", "server", "serverlock", "serverlock", "serverpriv", "serverpriv" }; // hardcoded sounds, defined in sounds.cfg -enum -{ +enum { S_JUMP = 0, S_LAND, S_RIFLE, S_PUNCH1, S_SG, S_CG, S_RLFIRE, S_RLHIT, S_WEAPLOAD, S_ITEMAMMO, S_ITEMHEALTH, S_ITEMARMOUR, S_ITEMPUP, S_ITEMSPAWN, S_TELEPORT, S_NOAMMO, S_PUPOUT, @@ -113,15 +108,12 @@ enum S_FLAUNCH, S_FEXPLODE, S_SPLASH1, S_SPLASH2, S_JUMPPAD, S_PISTOL, - S_V_FIGHT, S_V_BOOST, S_V_BOOST10, S_V_QUAD, S_V_QUAD10, - S_BURN, S_CHAINSAW_ATTACK, S_CHAINSAW_IDLE, - S_HIT }; @@ -129,8 +121,7 @@ enum enum { PRIV_NONE = 0, PRIV_MASTER, PRIV_AUTH, PRIV_ADMIN }; -enum -{ +enum { N_CONNECT = 0, N_SERVINFO, N_WELCOME, N_INITCLIENT, N_POS, N_TEXT, N_SOUND, N_CDIS, N_SHOOT, N_EXPLODE, N_SUICIDE, N_DIED, N_DAMAGE, N_HITPUSH, N_SHOTFX, N_EXPLODEFX, @@ -157,8 +148,7 @@ enum NUMMSG }; -static const int msgsizes[] = // size inclusive message token, 0 for variable or not-checked sizes -{ +static const int msgsizes[] = { // size inclusive message token, 0 for variable or not-checked sizes { N_CONNECT, 0, N_SERVINFO, 0, N_WELCOME, 1, N_INITCLIENT, 0, N_POS, 0, N_TEXT, 0, N_SOUND, 2, N_CDIS, 2, N_SHOOT, 0, N_EXPLODE, 0, N_SUICIDE, 1, N_DIED, 5, N_DAMAGE, 6, N_HITPUSH, 7, N_SHOTFX, 10, N_EXPLODEFX, 4, @@ -193,8 +183,7 @@ static const int msgsizes[] = // size inclusive message token, 0 for variab #define DEMO_VERSION 1 // bump when demo format changes #define DEMO_MAGIC "SAUERBRATEN_DEMO" -struct demoheader -{ +struct demoheader { char magic[16]; int version, protocol; }; @@ -202,14 +191,11 @@ struct demoheader #define MAXNAMELEN 15 #define MAXTEAMLEN 4 -enum -{ +enum { HICON_BLUE_ARMOUR = 0, HICON_GREEN_ARMOUR, HICON_YELLOW_ARMOUR, - HICON_HEALTH, - HICON_FIST, HICON_SG, HICON_CG, @@ -217,11 +203,8 @@ enum HICON_RIFLE, HICON_GL, HICON_PISTOL, - HICON_QUAD, - HICON_TOKEN, - HICON_X = 20, HICON_Y = 1650, HICON_TEXTY = 1644, @@ -234,20 +217,20 @@ static struct itemstat { int add, max, sound; const char *name; int icon, info; -} itemstats[] = { - {10, 30, S_ITEMAMMO, "SG", HICON_SG, GUN_SG}, - {20, 60, S_ITEMAMMO, "CG", HICON_CG, GUN_CG}, - {5, 15, S_ITEMAMMO, "RL", HICON_RL, GUN_RL}, - {5, 15, S_ITEMAMMO, "RI", HICON_RIFLE, GUN_RIFLE}, - {10, 30, S_ITEMAMMO, "GL", HICON_GL, GUN_GL}, - {30, 120, S_ITEMAMMO, "PI", HICON_PISTOL, GUN_PISTOL}, - {25, 100, S_ITEMHEALTH, "H", HICON_HEALTH, -1}, - {100, 200, S_ITEMHEALTH, "MH", HICON_HEALTH, 50}, - {5, 100, S_ITEMHEALTH, "TH", HICON_HEALTH, -1}, - {5, 50, S_ITEMARMOUR, "TA", HICON_BLUE_ARMOUR, A_BLUE}, - {50, 100, S_ITEMARMOUR, "GA", HICON_GREEN_ARMOUR, A_GREEN}, - {100, 200, S_ITEMARMOUR, "YA", HICON_YELLOW_ARMOUR, A_YELLOW}, - {20000, 30000, S_ITEMPUP, "Q", HICON_QUAD, -1}, +} itemstats[] = { { + 10, 30, S_ITEMAMMO, "SG", HICON_SG, GUN_SG}, { + 20, 60, S_ITEMAMMO, "CG", HICON_CG, GUN_CG}, { + 5, 15, S_ITEMAMMO, "RL", HICON_RL, GUN_RL}, { + 5, 15, S_ITEMAMMO, "RI", HICON_RIFLE, GUN_RIFLE}, { + 10, 30, S_ITEMAMMO, "GL", HICON_GL, GUN_GL}, { + 30, 120, S_ITEMAMMO, "PI", HICON_PISTOL, GUN_PISTOL}, { + 25, 100, S_ITEMHEALTH, "H", HICON_HEALTH, -1}, { + 100, 200, S_ITEMHEALTH, "MH", HICON_HEALTH, 50}, { + 5, 100, S_ITEMHEALTH, "TH", HICON_HEALTH, -1}, { + 5, 50, S_ITEMARMOUR, "TA", HICON_BLUE_ARMOUR, A_BLUE}, { + 50, 100, S_ITEMARMOUR, "GA", HICON_GREEN_ARMOUR, A_GREEN}, { + 100, 200, S_ITEMARMOUR, "YA", HICON_YELLOW_ARMOUR, A_YELLOW}, { + 20000, 30000, S_ITEMPUP, "Q", HICON_QUAD, -1}, }; #define MAXRAYS 12 @@ -260,7 +243,7 @@ static const struct guninfo { const char *name, *file; short part; } guns[NUMGUNS] = { - // delay| dmg| spr| spd| kck| rng| ray| pus| exp| + // delay| dmg| spr| spd| kck| rng| ray| pus| exp| { { S_PUNCH1, 100, 30, 0, 0, 0, 30, 1, 80, 0, 0, "fist", "fist", 0 }, { S_SG, 1000, 20, 280, 0, 20, 1024, MAXRAYS, 100, 0, 0, "shotgun", "shotg", 0 }, { S_CG, 100, 20, 70, 0, 10, 1024, 1, 80, 0, 0, "chaingun", "chaing", 0 }, @@ -287,61 +270,45 @@ extern void pwreset(void); #include "ai.h" // inherited by fpsent and server clients -struct fpsstate -{ +struct fpsstate { int health, maxhealth; int armour, maxarmour, armourtype; int quadmillis; int gunselect, gunwait; int ammo[NUMGUNS]; int aitype, skill; - fpsstate() : maxhealth(100), maxarmour(50), aitype(AI_NONE), skill(0) {} - - void baseammo(int gun, int k = 2, int scale = 1) - { + void baseammo(int gun, int k = 2, int scale = 1) { ammo[gun] = (itemstats[gun-GUN_SG].add*k)/scale; } - - void addammo(int gun, int k = 1, int scale = 1) - { + void addammo(int gun, int k = 1, int scale = 1) { itemstat &is = itemstats[gun-GUN_SG]; ammo[gun] = min(ammo[gun] + (is.add*k)/scale, is.max); } - - bool hasmaxammo(int type) - { + bool hasmaxammo(int type) { const itemstat &is = itemstats[type-I_SHELLS]; return ammo[type-I_SHELLS+GUN_SG]>=is.max; } - - bool canpickup(int type) - { + bool canpickup(int type) { if(typeI_QUAD) return false; itemstat &is = itemstats[type-I_SHELLS]; - switch(type) - { + switch(type) { case I_BOOST: return maxhealthI_QUAD) return; itemstat &is = itemstats[type-I_SHELLS]; - switch(type) - { + switch(type) { case I_TINYHEALTH: health = min(health+is.add, maxhealth); break; @@ -368,9 +335,7 @@ struct fpsstate break; } } - - void respawn() - { + void respawn() { maxhealth = 100; health = maxhealth; maxarmour = 50; @@ -382,39 +347,31 @@ struct fpsstate loopi(NUMGUNS) ammo[i] = 0; ammo[GUN_FIST] = 1; } - - void spawnstate(int gamemode) - { - if(m_demo) - { + void spawnstate(int gamemode) { + if(m_demo) { gunselect = GUN_FIST; } - else if(m_insta) - { + else if(m_insta) { armour = 0; health = 1; gunselect = GUN_RIFLE; ammo[GUN_RIFLE] = 100; } - else if(m_efficiency) - { + else if(m_efficiency) { armourtype = A_GREEN; armour = 100; loopi(NUMGUNS-1) baseammo(i+1); gunselect = GUN_CG; ammo[GUN_CG] /= 2; } - else - { + else { armourtype = A_BLUE; armour = 25; ammo[GUN_PISTOL] = 40; } } - // just subtract damage here, can set death, etc. later in code calling this - int dodamage(int damage) - { + int dodamage(int damage) { int ad = (damage*(armourtype+1)*30)/100; // let armour absorb when possible if(ad>armour) ad = armour; armour -= ad; @@ -422,17 +379,14 @@ struct fpsstate health -= damage; return damage; } - - int hasammo(int gun, int exclude = -1) - { + int hasammo(int gun, int exclude = -1) { return gun >= 0 && gun <= NUMGUNS && gun != exclude && ammo[gun] > 0; } }; extern int screenw, screenh; -struct fpsent : dynent, fpsstate -{ +struct fpsent : dynent, fpsstate { int weight; // affects the effectiveness of hitpush int clientnum, privilege, lastupdate, plag, ping; int lifesequence; // sequence id for each respawn, used in damage test @@ -448,48 +402,35 @@ struct fpsent : dynent, fpsstate editinfo *edit; float deltayaw, deltapitch, deltaroll, newyaw, newpitch, newroll; int smoothmillis; - string name, team, info; int playermodel; ai::aiinfo *ai; int ownernum, lastnode; - vec muzzle; - - fpsent() : weight(100), clientnum(-1), privilege(PRIV_NONE), lastupdate(0), plag(0), ping(0), lifesequence(0), respawned(-1), suicided(-1), lastpain(0), attacksound(-1), attackchan(-1), idlesound(-1), idlechan(-1), frags(0), flags(0), deaths(0), totaldamage(0), totalshots(0), edit(NULL), smoothmillis(-1), playermodel(-1), ai(NULL), ownernum(-1), muzzle(-1, -1, -1) - { + fpsent() : weight(100), clientnum(-1), privilege(PRIV_NONE), lastupdate(0), plag(0), ping(0), lifesequence(0), respawned(-1), suicided(-1), lastpain(0), attacksound(-1), attackchan(-1), idlesound(-1), idlechan(-1), frags(0), flags(0), deaths(0), totaldamage(0), totalshots(0), edit(NULL), smoothmillis(-1), playermodel(-1), ai(NULL), ownernum(-1), muzzle(-1, -1, -1) { name[0] = team[0] = info[0] = 0; respawn(); } - ~fpsent() - { + ~fpsent() { freeeditinfo(edit); if(attackchan >= 0) stopsound(attacksound, attackchan); if(idlechan >= 0) stopsound(idlesound, idlechan); if(ai) delete ai; } - - void hitpush(int damage, const vec &dir, fpsent *actor, int gun) - { + void hitpush(int damage, const vec &dir, fpsent *actor, int gun) { vec push(dir); push.mul((actor==this && guns[gun].exprad ? EXP_SELFPUSH : 1.0f)*guns[gun].hitpush*damage/weight); vel.add(push); } - - void stopattacksound() - { + void stopattacksound() { if(attackchan >= 0) stopsound(attacksound, attackchan, 250); attacksound = attackchan = -1; } - - void stopidlesound() - { + void stopidlesound() { if(idlechan >= 0) stopsound(idlesound, idlechan, 100); idlesound = idlechan = -1; } - - void respawn() - { + void respawn() { dynent::reset(); fpsstate::respawn(); respawned = suicided = -1; @@ -506,22 +447,17 @@ struct fpsent : dynent, fpsstate stopattacksound(); lastnode = -1; } - - int respawnwait(int secs, int delay = 0) - { + int respawnwait(int secs, int delay = 0) { return max(0, secs - (::lastmillis - lastpain - delay)/1000); } }; -struct teamscore -{ +struct teamscore { const char *team; int score; teamscore() {} teamscore(const char *s, int n) : team(s), score(n) {} - - static bool compare(const teamscore &x, const teamscore &y) - { + static bool compare(const teamscore &x, const teamscore &y) { if(x.score > y.score) return true; if(x.score < y.score) return false; return strcmp(x.team, y.team) < 0; @@ -533,8 +469,7 @@ static inline bool htcmp(const char *key, const teamscore &t) { return htcmp(key #define MAXTEAMS 128 -struct teaminfo -{ +struct teaminfo { char team[MAXTEAMLEN+1]; int frags; }; @@ -542,14 +477,11 @@ struct teaminfo static inline uint hthash(const teaminfo &t) { return hthash(t.team); } static inline bool htcmp(const char *team, const teaminfo &t) { return !strcmp(team, t.team); } -namespace entities -{ +namespace entities { extern vector ents; - extern const char *entmdlname(int type); extern const char *itemname(int i); extern int itemicon(int i); - extern void preloadentities(); extern void renderentities(); extern void checkitems(fpsent *d); @@ -562,12 +494,10 @@ namespace entities extern void pickupeffects(int n, fpsent *d); extern void teleporteffects(fpsent *d, int tp, int td, bool local = true); extern void jumppadeffects(fpsent *d, int jp, bool local = true); - extern void repammo(fpsent *d, int type, bool local = true); } -namespace game -{ +namespace game { // fps extern int gamemode, nextmode; extern string clientmap; @@ -580,7 +510,6 @@ namespace game extern int respawnent; extern int following; extern int smoothmove, smoothdist; - extern bool clientoption(const char *arg); extern fpsent *getclient(int cn); extern fpsent *newclient(int cn); @@ -608,12 +537,10 @@ namespace game extern void drawicon(int icon, float x, float y, float sz = 120); const char *mastermodecolor(int n, const char *unknown); const char *mastermodeicon(int n, const char *unknown); - // client extern bool connected, remote, demoplayback; extern string servinfo; extern vector messages; - extern int parseplayer(const char *arg); extern void ignore(int cn); extern void unignore(int cn); @@ -627,7 +554,6 @@ namespace game extern void forceintermission(); extern void c2sinfo(bool force = false); extern void sendposition(fpsent *d, bool reliable = false); - // weapon extern int getweapon(const char *name); extern void shoot(fpsent *d, const vec &targ); @@ -652,7 +578,6 @@ namespace game extern void gunselect(int gun, fpsent *d); extern void weaponswitch(fpsent *d); extern void avoidweapons(ai::avoidset &obstacles, float radius); - // scoreboard extern void showscores(bool on); extern void getbestplayers(vector &best); @@ -660,18 +585,14 @@ namespace game extern void clearteaminfo(); extern void setteaminfo(const char *team, int frags); extern int statuscolor(fpsent *d, int color); - // render - struct playermodelinfo - { + struct playermodelinfo { 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(); @@ -680,8 +601,7 @@ namespace game extern vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d); } -namespace server -{ +namespace server { extern const char *modename(int n, const char *unknown = "unknown"); extern const char *mastermodename(int n, const char *unknown = "unknown"); extern void startintermission(); diff --git a/src/fpsgame/render.cpp b/src/fpsgame/render.cpp index f35daec..dacdcd9 100644 --- a/src/fpsgame/render.cpp +++ b/src/fpsgame/render.cpp @@ -3,21 +3,16 @@ struct spawninfo { const extentity *e; float weight; }; extern float gatherspawninfos(dynent *d, int tag, vector &spawninfos); -namespace game -{ +namespace game { vector bestplayers; vector 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 ragdolls; - - void saveragdoll(fpsent *d) - { + 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; @@ -28,49 +23,38 @@ namespace game ragdolls.add(r); d->ragdoll = NULL; } - - void clearragdolls() - { + void clearragdolls() { ragdolls.deletecontents(); } - - void moveragdolls() - { - loopv(ragdolls) - { + void moveragdolls() { + loopv(ragdolls) { fpsent *d = ragdolls[i]; - if(lastmillis > d->lastupdate + ragdollmillis) - { + 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] = { + { + "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 }, }; - - const playermodelinfo *getplayermodelinfo(int n) - { + const playermodelinfo *getplayermodelinfo(int n) { (void) n; return &playermodels[0]; } - - const playermodelinfo &getplayermodelinfo(fpsent *d) - { + const playermodelinfo &getplayermodelinfo(fpsent *d) { + (void) d; const playermodelinfo *mdl = getplayermodelinfo(0); if(!mdl) mdl = getplayermodelinfo(playermodel); return *mdl; } - - void preloadplayermodel() - { + void preloadplayermodel() { const playermodelinfo *mdl = getplayermodelinfo(0); - if(m_teammode) - { + if(m_teammode) { preloadmodel(mdl->blueteam); preloadmodel(mdl->redteam); } @@ -79,23 +63,18 @@ namespace game if(mdl->quad) preloadmodel(mdl->quad); loopj(3) if(mdl->armour[j]) preloadmodel(mdl->armour[j]); } - VAR(testquad, 0, 0, 1); VAR(testarmour, 0, 0, 1); VAR(testteam, 0, 0, 3); - - void renderplayer(fpsent *d, const playermodelinfo &mdl, int team, float fade, bool mainpass) - { + void renderplayer(fpsent *d, const playermodelinfo &mdl, int team, float fade, bool mainpass) { int lastaction = d->lastaction, hold = mdl.vwep || d->gunselect==GUN_PISTOL ? 0 : (ANIM_HOLD1+d->gunselect)|ANIM_LOOP, attack = ANIM_ATTACK1+d->gunselect, delay = mdl.vwep ? 300 : guns[d->gunselect].attackdelay+50; - if(intermission && d->state!=CS_DEAD) - { + if(intermission && d->state!=CS_DEAD) { lastaction = 0; hold = attack = ANIM_LOSE|ANIM_LOOP; delay = 0; if(m_teammode ? bestteams.htfind(d->team)>=0 : bestplayers.find(d)>=0) hold = attack = ANIM_WIN|ANIM_LOOP; } - else if(d->state==CS_ALIVE && d->lasttaunt && lastmillis-d->lasttaunt<1000 && lastmillis-d->lastaction>delay) - { + else if(d->state==CS_ALIVE && d->lasttaunt && lastmillis-d->lasttaunt<1000 && lastmillis-d->lastaction>delay) { lastaction = d->lasttaunt; hold = attack = ANIM_TAUNT; delay = 1000; @@ -103,94 +82,75 @@ namespace game modelattach a[5]; static const char * const vweps[] = {"vwep/fist", "vwep/shotg", "vwep/chaing", "vwep/rocket", "vwep/rifle", "vwep/gl", "vwep/pistol"}; int ai = 0; - if((!mdl.vwep || d->gunselect!=GUN_FIST) && d->gunselect<=GUN_PISTOL) - { + if((!mdl.vwep || d->gunselect!=GUN_FIST) && d->gunselect<=GUN_PISTOL) { int vanim = ANIM_VWEP_IDLE|ANIM_LOOP, vtime = 0; - if(lastaction && d->lastattackgun==d->gunselect && lastmillis < lastaction + delay) - { + if(lastaction && d->lastattackgun==d->gunselect && lastmillis < lastaction + delay) { vanim = ANIM_VWEP_SHOOT; vtime = lastaction; } a[ai++] = modelattach("tag_weapon", mdl.vwep ? mdl.vwep : vweps[d->gunselect], vanim, vtime); } - if(d->state==CS_ALIVE) - { + if(d->state==CS_ALIVE) { if((testquad || d->quadmillis) && mdl.quad) a[ai++] = modelattach("tag_powerup", mdl.quad, ANIM_POWERUP|ANIM_LOOP, 0); - if(testarmour || d->armour) - { + if(testarmour || d->armour) { int type = clamp(d->armourtype, (int)A_BLUE, (int)A_YELLOW); if(mdl.armour[type]) a[ai++] = modelattach("tag_shield", mdl.armour[type], ANIM_SHIELD|ANIM_LOOP, 0); } } - if(mainpass) - { + if(mainpass) { d->muzzle = vec(-1, -1, -1); a[ai++] = modelattach("tag_muzzle", &d->muzzle); } const char *mdlname = mdl.ffa; - switch(testteam ? testteam-1 : team) - { + switch(testteam ? testteam-1 : team) { 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); } - VARP(teamskins, 0, 0, 1); - VARP(statusicons, 0, 1, 1); - - void renderstatusicons(fpsent *d, int team, float yoffset)///TODO - { + void renderstatusicons(fpsent *d, int team, float yoffset) {///TODO { vec p = d->abovehead().madd(camup, yoffset); int icons = 0; const itemstat &boost = itemstats[I_BOOST-I_SHELLS]; - if(statusicons && (d->state==CS_ALIVE || d->state==CS_LAGGED)) - { + if(statusicons && (d->state==CS_ALIVE || d->state==CS_LAGGED)) { if(d->quadmillis) icons++; if(d->maxhealth>100) icons += (min(d->maxhealth, boost.max) - 100 + boost.info-1) / boost.info; if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) icons++; } if(icons) concatstring(d->info, " "); particle_text(p, d->info, PART_TEXT, 1, team ? (team==1 ? 0x6496FF : 0xFF4B19) : 0x1EC850, 2.0f, 0, icons); - if(icons) - { + if(icons) { float tw, th; text_boundsf(d->info, tw, th); float offset = (tw - icons*th)/2; - if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) - { + if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) { int icon = itemstats[(d->armourtype==A_YELLOW ? I_YELLOWARMOUR : I_GREENARMOUR)-I_SHELLS].icon; particle_texticon(p, icon%4, icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f); offset += th; } - for(int i = 100; i < min(d->maxhealth, boost.max); i += boost.info) - { + for(int i = 100; i < min(d->maxhealth, boost.max); i += boost.info) { particle_texticon(p, boost.icon%4, boost.icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f); offset += th; } - if(d->quadmillis) - { + if(d->quadmillis) { int icon = itemstats[I_QUAD-I_SHELLS].icon; particle_texticon(p, icon%4, icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f); offset += th; } } } - VARP(statusbars, 0, 1, 2); FVARP(statusbarscale, 0, 1, 2); - - float renderstatusbars(fpsent *d, int team)///TODO - { + float renderstatusbars(fpsent *d, int team) {///TODO { if(!statusbars || m_insta || (player1->state==CS_SPECTATOR ? statusbars <= 1 : team != 1) || (d->state!=CS_ALIVE && d->state!=CS_LAGGED)) return 0; vec p = d->abovehead().msub(camdir, 50/80.0f).msub(camup, 2.0f); float offset = 0; float scale = statusbarscale; - if(d->armour > 0) - { + if(d->armour > 0) { int limit = d->armourtype==A_YELLOW ? 200 : (d->armourtype==A_GREEN ? 100 : 50); int color = d->armourtype==A_YELLOW ? 0xFFC040 : (d->armourtype==A_GREEN ? 0x008C00 : 0x0B5899); float size = scale*sqrtf(max(d->armour, limit)/100.0f); @@ -205,48 +165,36 @@ namespace game particle_meter(vec(p).madd(camup, offset), fill, PART_METER, 1, color, 0, size); return offset; } - - void rendergame(bool mainpass) - { + void rendergame(bool mainpass) { if(mainpass) ai::render(); - - if(intermission) - { + if(intermission) { bestteams.shrink(0); bestplayers.shrink(0); if(m_teammode) getbestteams(bestteams); else getbestplayers(bestplayers); } - startmodelbatches(); - fpsent *exclude = isthirdperson() ? NULL : followingplayer(); - loopv(players) - { + loopv(players) { fpsent *d = players[i]; if(d == player1 || d->state==CS_SPECTATOR || d->state==CS_SPAWNING || d->lifesequence < 0 || d == exclude || (d->state==CS_DEAD && hidedead)) continue; int team = 0; if(teamskins || m_teammode) team = isteam(player1->team, d->team) ? 1 : 2; renderplayer(d, getplayermodelinfo(d), team, 1, mainpass); - vec dir = vec(d->o).sub(camera1->o); float dist = dir.magnitude(); dir.div(dist); - if(d->state!=CS_EDITING && raycube(camera1->o, dir, dist, 0) < dist) - { + if(d->state!=CS_EDITING && raycube(camera1->o, dir, dist, 0) < dist) { d->info[0] = '\0'; continue; } - copystring(d->info, colorname(d)); - if(d->state!=CS_DEAD) - { + if(d->state!=CS_DEAD) { float offset = renderstatusbars(d, team); renderstatusicons(d, team, offset); } } - loopv(ragdolls) - { + loopv(ragdolls) { fpsent *d = ragdolls[i]; int team = 0; if(teamskins || m_teammode) team = isteam(player1->team, d->team) ? 1 : 2; @@ -259,42 +207,32 @@ namespace game entities::renderentities(); renderbouncers(); renderprojectiles(); - endmodelbatches(); } - 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); FVAR(swayup, -1, 0.05f, 1); - float swayfade = 0, swayspeed = 0, swaydist = 0; vec swaydir(0, 0, 0); - - void swayhudgun(int curtime) - { + void swayhudgun(int curtime) { fpsent *d = hudplayer(); - if(d->state != CS_SPECTATOR) - { - if(d->physstate >= PHYS_SLOPE) - { + if(d->state != CS_SPECTATOR) { + if(d->physstate >= PHYS_SLOPE) { swayspeed = min(sqrtf(d->vel.x*d->vel.x + d->vel.y*d->vel.y), d->maxspeed); swaydist += swayspeed*curtime/1000.0f; swaydist = fmod(swaydist, 2*swaystep); swayfade = 1; } - else if(swayfade > 0) - { + else if(swayfade > 0) { swaydist += swayspeed*swayfade*curtime/1000.0f; swaydist = fmod(swaydist, 2*swaystep); swayfade -= 0.5f*(curtime*d->maxspeed)/(swaystep*1000.0f); } - float k = pow(0.7f, curtime/10.0f); swaydir.mul(k); vec vel(d->vel); @@ -302,18 +240,12 @@ namespace game swaydir.add(vec(vel).mul((1-k)/(15*max(vel.magnitude(), d->maxspeed)))); } } - - struct hudent : dynent - { + struct hudent : dynent { hudent() { type = ENT_CAMERA; } } guninterp; - SVARP(hudgunsdir, ""); - - void drawhudmodel(fpsent *d, int anim, float speed = 0, int base = 0) - { + void drawhudmodel(fpsent *d, int anim, float speed = 0, int base = 0) { if(d->gunselect>GUN_PISTOL) return; - vec sway; vecfromyawpitch(d->yaw, 0, 0, 1, sway); float steps = swaydist/swaystep*M_PI; @@ -323,8 +255,7 @@ namespace game if(!hudgunsway) sway = d->o; #if 0 - if(player1->state!=CS_DEAD && player1->quadmillis) - { + if(player1->state!=CS_DEAD && player1->quadmillis) { float t = 0.5f + 0.5f*sinf(2*M_PI*lastmillis/1000.0f); color.y = color.y*(1-t) + t; } @@ -339,8 +270,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 && chainsawhudgun) { anim |= ANIM_LOOP; base = 0; interp = &guninterp; @@ -348,37 +278,26 @@ namespace game rendermodel(NULL, gunname, anim, sway, testhudgun ? 0 : d->yaw+90, testhudgun ? 0 : d->pitch, MDL_LIGHT|MDL_HUD, interp, a, base, (int)ceil(speed)); if(d->muzzle.x >= 0) d->muzzle = calcavatarpos(d->muzzle, 12); } - - void drawhudgun() - { + void drawhudgun() { fpsent *d = hudplayer(); - if(d->state==CS_SPECTATOR || d->state==CS_EDITING || !hudgun || editmode) - { + if(d->state==CS_SPECTATOR || d->state==CS_EDITING || !hudgun || editmode) { d->muzzle = player1->muzzle = vec(-1, -1, -1); return; } - int rtime = guns[d->gunselect].attackdelay; - if(d->lastaction && d->lastattackgun==d->gunselect && lastmillis-d->lastactionlastaction && d->lastattackgun==d->gunselect && lastmillis-d->lastactionlastaction); } - else - { + else { drawhudmodel(d, ANIM_GUN_IDLE|ANIM_LOOP); } } - - void renderavatar() - { + void renderavatar() { drawhudgun(); } - - void renderplayerpreview(int model, int team, int weap) - { + void renderplayerpreview(int model, int team, int weap) { static fpsent *previewent = NULL; - if(!previewent) - { + if(!previewent) { previewent = new fpsent; previewent->light.color = vec(1, 1, 1); previewent->light.dir = vec(0, -1, 2).normalize(); @@ -394,18 +313,15 @@ namespace game if(!mdlinfo) return; renderplayer(previewent, *mdlinfo, team >= 0 && team <= 2 ? team : 0, 1, false); } - - vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d) - { + vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d) { + (void) gun; if(d->muzzle.x >= 0) return d->muzzle; vec offset(from); - if(d!=hudplayer() || isthirdperson()) - { + if(d!=hudplayer() || isthirdperson()) { vec front, right; vecfromyawpitch(d->yaw, d->pitch, 1, 0, front); offset.add(front.mul(d->radius)); - if(d->type!=ENT_AI) - { + if(d->type!=ENT_AI) { offset.z += (d->aboveeye + d->eyeheight)*0.75f - d->eyeheight; vecfromyawpitch(d->yaw, 0, 0, -1, right); offset.add(right.mul(0.5f*d->radius)); @@ -414,30 +330,24 @@ namespace game return offset; } offset.add(vec(to).sub(from).normalize().mul(2)); - if(hudgun) - { + if(hudgun) { offset.sub(vec(camup).mul(1.0f)); offset.add(vec(camright).mul(0.8f)); } else offset.sub(vec(camup).mul(0.8f)); return offset; } - - void preloadweapons() - { + void preloadweapons() { const playermodelinfo &mdl = getplayermodelinfo(player1); - loopi(NUMGUNS) - { + loopi(NUMGUNS) { const char *file = guns[i].file; if(!file) continue; string fname; - if((m_teammode || teamskins) && teamhudguns) - { + if((m_teammode || teamskins) && teamhudguns) { formatstring(fname, "%s/%s/blue", hudgunsdir[0] ? hudgunsdir : mdl.hudguns, file); preloadmodel(fname); } - else - { + else { formatstring(fname, "%s/%s", hudgunsdir[0] ? hudgunsdir : mdl.hudguns, file); preloadmodel(fname); } @@ -445,14 +355,10 @@ namespace game preloadmodel(fname); } } - - void preloadsounds() - { + void preloadsounds() { for(int i = S_JUMP; i <= S_HIT; i++) preloadsound(i); } - - void preload() - { + void preload() { if(hudgun) preloadweapons(); preloadbouncers(); preloadplayermodel(); diff --git a/src/fpsgame/scoreboard.cpp b/src/fpsgame/scoreboard.cpp index 96f8868..81f93a1 100644 --- a/src/fpsgame/scoreboard.cpp +++ b/src/fpsgame/scoreboard.cpp @@ -1,8 +1,7 @@ // creation of scoreboard #include "game.h" -namespace game -{ +namespace game { VARP(scoreboard2d, 0, 1, 1); VARP(showservinfo, 0, 1, 1); VARP(showclientnum, 0, 1, 1); @@ -15,25 +14,17 @@ namespace game VARP(hidefrags, 0, 0, 1); VARP(showdeaths, 0, 1, 1); VARP(showdamagedealt, 0, 1, 1); - static hashset teaminfos; - - void clearteaminfo() - { + void clearteaminfo() { teaminfos.clear(); } - - void setteaminfo(const char *team, int frags) - { + void setteaminfo(const char *team, int frags) { teaminfo *t = teaminfos.access(team); if(!t) { t = &teaminfos[team]; copystring(t->team, team, sizeof(t->team)); } t->frags = frags; } - - static inline bool playersort(const fpsent *a, const fpsent *b) - { - if(a->state==CS_SPECTATOR) - { + static inline bool playersort(const fpsent *a, const fpsent *b) { + if(a->state==CS_SPECTATOR) { if(b->state==CS_SPECTATOR) return strcmp(a->name, b->name) < 0; else return false; } @@ -42,51 +33,38 @@ namespace game if(a->frags < b->frags) return false; return strcmp(a->name, b->name) < 0; } - - void getbestplayers(vector &best) - { - loopv(players) - { + void getbestplayers(vector &best) { + loopv(players) { fpsent *o = players[i]; if(o->state!=CS_SPECTATOR) best.add(o); } best.sort(playersort); while(best.length() > 1 && best.last()->frags < best[0]->frags) best.drop(); } - - void getbestteams(vector &best) - { - if(!hidefrags) - { + void getbestteams(vector &best) { + if(!hidefrags) { vector teamscores; teamscores.sort(teamscore::compare); while(teamscores.length() > 1 && teamscores.last().score < teamscores[0].score) teamscores.drop(); loopv(teamscores) best.add(teamscores[i].team); } - else - { + else { int bestfrags = INT_MIN; enumerate(teaminfos, teaminfo, t, bestfrags = max(bestfrags, t.frags)); - if(bestfrags <= 0) loopv(players) - { + if(bestfrags <= 0) loopv(players) { fpsent *o = players[i]; if(o->state!=CS_SPECTATOR && !teaminfos.access(o->team) && best.htfind(o->team) < 0) { bestfrags = 0; best.add(o->team); } } enumerate(teaminfos, teaminfo, t, if(t.frags >= bestfrags) best.add(t.team)); } } - - struct scoregroup : teamscore - { + struct scoregroup : teamscore { vector players; }; static vector groups; static vector spectators; - - static inline bool scoregroupcmp(const scoregroup *x, const scoregroup *y) - { - if(!x->team) - { + static inline bool scoregroupcmp(const scoregroup *x, const scoregroup *y) { + if(!x->team) { if(y->team) return false; } else if(!y->team) return true; @@ -96,20 +74,16 @@ namespace game if(x->players.length() < y->players.length()) return false; return x->team && y->team && strcmp(x->team, y->team) < 0; } - - static int groupplayers() - { + static int groupplayers() { int numgroups = 0; spectators.setsize(0); - loopv(players) - { + loopv(players) { fpsent *o = players[i]; if(!showconnecting && !o->name[0]) continue; if(o->state==CS_SPECTATOR) { spectators.add(o); continue; } const char *team = m_teammode && o->team[0] ? o->team : NULL; bool found = false; - loopj(numgroups) - { + loopj(numgroups) { scoregroup &g = *groups[j]; if(team!=g.team && (!team || !g.team || strcmp(team, g.team))) continue; g.players.add(o); @@ -129,31 +103,23 @@ namespace game groups.sort(scoregroupcmp, 0, numgroups); return numgroups; } - - int statuscolor(fpsent *d, int color) - { - if(d->privilege) - { + int statuscolor(fpsent *d, int color) { + if(d->privilege) { color = d->privilege>=PRIV_ADMIN ? 0xFF8000 : (d->privilege>=PRIV_AUTH ? 0xC040C0 : 0x40FF80); if(d->state==CS_DEAD) color = (color>>1)&0x7F7F7F; } else if(d->state==CS_DEAD) color = 0x606060; return color; } - - void renderscoreboard(g3d_gui &g, bool firstpass) - { + void renderscoreboard(g3d_gui &g, bool firstpass) { const ENetAddress *address = connectedpeer(); - if(showservinfo && address) - { + if(showservinfo && address) { string hostname; - if(enet_address_get_host_ip(address, hostname, sizeof(hostname)) >= 0) - { + if(enet_address_get_host_ip(address, hostname, sizeof(hostname)) >= 0) { if(servinfo[0]) g.titlef("%.25s", 0xFFFF80, NULL, servinfo); else g.titlef("%s:%d", 0xFFFF80, NULL, hostname, address->port); } } - g.pushlist(); g.spring(); g.text(server::modename(gamemode), 0xFFFF80); @@ -162,12 +128,10 @@ namespace game g.text(mname[0] ? mname : "[new map]", 0xFFFF80); extern int gamespeed; if(gamespeed != 100) { g.separator(); g.textf("%d.%02dx", 0xFFFF80, NULL, gamespeed/100, gamespeed%100); } - if(m_timed && mname[0] && (maplimit >= 0 || intermission)) - { + if(m_timed && mname[0] && (maplimit >= 0 || intermission)) { g.separator(); if(intermission) g.text("intermission", 0xFFFF80); - else - { + else { int secs = max(maplimit-lastmillis+999, 0)/1000, mins = secs/60; secs %= 60; g.pushlist(); @@ -179,41 +143,31 @@ namespace game if(ispaused()) { g.separator(); g.text("paused", 0xFFFF80); } g.spring(); g.poplist(); - g.separator(); - int numgroups = groupplayers(); - loopk(numgroups) - { + loopk(numgroups) { if((k%2)==0) g.pushlist(); // horizontal - scoregroup &sg = *groups[k]; int bgcolor = sg.team && m_teammode ? (isteam(player1->team, sg.team) ? 0x3030C0 : 0xC03030) : 0, fgcolor = 0xFFFF80; - g.pushlist(); // vertical g.pushlist(); // horizontal - #define loopscoregroup(o, b) \ - loopv(sg.players) \ - { \ + loopv(sg.players) { \ + \ fpsent *o = sg.players[i]; \ b; \ } - g.pushlist(); - if(sg.team && m_teammode) - { + if(sg.team && m_teammode) { g.pushlist(); g.background(bgcolor, numgroups>1 ? 3 : 5); g.strut(1); g.poplist(); } g.text("", 0, " "); - loopscoregroup(o, - { - if(o==player1 && highlightscore && (multiplayer(false) || demoplayback || players.length() > 1)) - { + loopscoregroup(o, { + if(o==player1 && highlightscore && (multiplayer(false) || demoplayback || players.length() > 1)) { g.pushlist(); g.background(0x808080, numgroups>1 ? 3 : 5); } @@ -223,104 +177,79 @@ namespace game if(o==player1 && highlightscore && (multiplayer(false) || demoplayback || players.length() > 1)) g.poplist(); }); g.poplist(); - - if(sg.team && m_teammode) - { + if(sg.team && m_teammode) { g.pushlist(); // vertical - if(sg.score>=10000) g.textf("%s: WIN", fgcolor, NULL, sg.team); else g.textf("%s: %d", fgcolor, NULL, sg.team, sg.score); - g.pushlist(); // horizontal } - - if(!hidefrags) - { + if(!hidefrags) { g.pushlist(); g.strut(6); g.text("frags", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->frags)); g.poplist(); } - - if(showdeaths) - { + if(showdeaths) { g.pushlist(); g.strut(6); g.text("deaths", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->deaths)); g.poplist(); } - - if(showdamagedealt) - { + if(showdamagedealt) { g.pushlist(); g.strut(7); g.text("damage", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->totaldamage)); g.poplist(); } - g.pushlist(); g.text("name", fgcolor); g.strut(12); loopscoregroup(o, { g.textf("%s ", statuscolor(o, 0xFFFFDD), NULL, colorname(o)); }); g.poplist(); - - if(multiplayer(false) || demoplayback) - { + if(multiplayer(false) || demoplayback) { if(showpj || showping) g.space(1); - - if(showpj && showping <= 1) - { + if(showpj && showping <= 1) { g.pushlist(); g.strut(6); g.text("pj", fgcolor); - loopscoregroup(o, - { + loopscoregroup(o, { if(o->state==CS_LAGGED) g.text("LAG", 0xFFFFDD); else g.textf("%d", 0xFFFFDD, NULL, o->plag); }); g.poplist(); } - - if(showping > 1) - { + if(showping > 1) { g.pushlist(); g.strut(6); - g.pushlist(); g.text("ping", fgcolor); g.space(1); g.spring(); g.text("pj", fgcolor); g.poplist(); - - loopscoregroup(o, - { + loopscoregroup(o, { fpsent *p = o->ownernum >= 0 ? getclient(o->ownernum) : o; if(!p) p = o; g.pushlist(); if(p->state==CS_LAGGED) g.text("LAG", 0xFFFFDD); - else - { + else { g.textf("%d", 0xFFFFDD, NULL, p->ping); g.space(1); g.spring(); g.textf("%d", 0xFFFFDD, NULL, o->plag); } g.poplist(); - }); g.poplist(); } - else if(showping) - { + else if(showping) { g.pushlist(); g.text("ping", fgcolor); g.strut(6); - loopscoregroup(o, - { + loopscoregroup(o, { fpsent *p = o->ownernum >= 0 ? getclient(o->ownernum) : o; if(!p) p = o; if(!showpj && p->state==CS_LAGGED) g.text("LAG", 0xFFFFDD); @@ -329,43 +258,31 @@ namespace game g.poplist(); } } - - if(showclientnum || player1->privilege>=PRIV_MASTER) - { + if(showclientnum || player1->privilege>=PRIV_MASTER) { g.space(1); g.pushlist(); g.text("cn", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->clientnum)); g.poplist(); } - - if(sg.team && m_teammode) - { + if(sg.team && m_teammode) { g.poplist(); // horizontal g.poplist(); // vertical } - g.poplist(); // horizontal g.poplist(); // vertical - if(k+1privilege>=PRIV_MASTER) - { + if(showspectators && spectators.length()) { + if(showclientnum || player1->privilege>=PRIV_MASTER) { g.pushlist(); - g.pushlist(); g.text("spectator", 0xFFFF80, " "); g.strut(12); - loopv(spectators) - { + loopv(spectators) { fpsent *o = spectators[i]; - if(o==player1 && highlightscore) - { + if(o==player1 && highlightscore) { g.pushlist(); g.background(0x808080, 3); } @@ -373,15 +290,12 @@ namespace game if(o==player1 && highlightscore) g.poplist(); } g.poplist(); - - if((multiplayer(false) || demoplayback) && showspectatorping) - { + if((multiplayer(false) || demoplayback) && showspectatorping) { g.space(1); g.pushlist(); g.text("ping", 0xFFFF80); g.strut(6); - loopv(spectators) - { + loopv(spectators) { fpsent *o = spectators[i]; fpsent *p = o->ownernum >= 0 ? getclient(o->ownernum) : o; if(!p) p = o; @@ -390,28 +304,22 @@ namespace game } g.poplist(); } - g.space(1); g.pushlist(); g.text("cn", 0xFFFF80); loopv(spectators) g.textf("%d", 0xFFFFDD, NULL, spectators[i]->clientnum); g.poplist(); - g.poplist(); } - else - { + else { g.textf("%d spectator%s", 0xFFFF80, " ", spectators.length(), spectators.length()!=1 ? "s" : ""); - loopv(spectators) - { - if((i%3)==0) - { + loopv(spectators) { + if((i%3)==0) { g.pushlist(); g.text("", 0xFFFFDD, "spectator"); } fpsent *o = spectators[i]; - if(o==player1 && highlightscore) - { + if(o==player1 && highlightscore) { g.pushlist(); g.background(0x808080); } @@ -422,7 +330,6 @@ namespace game } } } - /// PW g.separator(); g.pushlist(); @@ -445,53 +352,36 @@ namespace game g.textf(" x %d ", 0xffffff, "quad_damage.png", pwitemspicked[6]); g.poplist(); } - - struct scoreboardgui : g3d_callback - { + struct scoreboardgui : g3d_callback { bool showing; vec menupos; int menustart; - scoreboardgui() : showing(false) {} - - void show(bool on) - { - if(!showing && on) - { + void show(bool on) { + if(!showing && on) { menupos = menuinfrontofplayer(); menustart = starttime(); } showing = on; } - - void gui(g3d_gui &g, bool firstpass) - { + void gui(g3d_gui &g, bool firstpass) { g.start(menustart, 0.03f, NULL, false); renderscoreboard(g, firstpass); g.end(); } - - void render() - { + void render() { if(showing) g3d_addgui(this, menupos, (scoreboard2d ? GUI_FORCE_2D : GUI_2D | GUI_FOLLOW) | GUI_BOTTOM); } - } scoreboard; - - void g3d_gamemenus() - { + void g3d_gamemenus() { scoreboard.render(); } - VARFN(scoreboard, showscoreboard, 0, 0, 1, scoreboard.show(showscoreboard!=0)); - - void showscores(bool on) - { + void showscores(bool on) { showscoreboard = on ? 1 : 0; scoreboard.show(on); } ICOMMAND(showscores, "D", (int *down), showscores(*down!=0)); - VARP(hudscore, 0, 0, 1); FVARP(hudscorescale, 1e-3f, 1.0f, 1e3f); VARP(hudscorealign, -1, 0, 1); @@ -501,61 +391,48 @@ namespace game HVARP(hudscoreenemycolour, 0, 0xFF4040, 0xFFFFFF); VARP(hudscorealpha, 0, 255, 255); VARP(hudscoresep, 0, 200, 1000); - - void drawhudscore(int w, int h) - { + void drawhudscore(int w, int h) { int numgroups = groupplayers(); if(!numgroups) return; - scoregroup *g = groups[0]; int score = INT_MIN, score2 = INT_MIN; bool best = false; - if(m_teammode) - { + if(m_teammode) { score = g->score; best = isteam(player1->team, g->team); - if(numgroups > 1) - { + if(numgroups > 1) { if(best) score2 = groups[1]->score; else for(int i = 1; i < groups.length(); ++i) if(isteam(player1->team, groups[i]->team)) { score2 = groups[i]->score; break; } - if(score2 == INT_MIN) - { + if(score2 == INT_MIN) { fpsent *p = followingplayer(player1); if(p->state==CS_SPECTATOR) score2 = groups[1]->score; } } } - else - { + else { fpsent *p = followingplayer(player1); score = g->players[0]->frags; best = p == g->players[0]; - if(g->players.length() > 1) - { + if(g->players.length() > 1) { if(best || p->state==CS_SPECTATOR) score2 = g->players[1]->frags; else score2 = p->frags; } } if(score == score2 && !best) best = true; - score = clamp(score, -999, 9999); defformatstring(buf, "%d", score); int tw = 0, th = 0; text_bounds(buf, tw, th); - string buf2; int tw2 = 0, th2 = 0; - if(score2 > INT_MIN) - { + if(score2 > INT_MIN) { score2 = clamp(score2, -999, 9999); formatstring(buf2, "%d", score2); text_bounds(buf2, tw2, th2); } - int fw = 0, fh = 0; text_bounds("00", fw, fh); fw = max(fw, max(tw, tw2)); - vec2 offset = vec2(hudscorex, hudscorey).mul(vec2(w, h).div(hudscorescale)); if(hudscorealign == 1) offset.x -= 2*fw + hudscoresep; else if(hudscorealign == 0) offset.x -= (2*fw + hudscoresep) / 2.0f; @@ -564,17 +441,13 @@ namespace game offset.y -= th/2.0f; offset2.x += fw + hudscoresep + (fw-tw2)/2.0f; offset2.y -= th2/2.0f; - pushhudmatrix(); hudmatrix.scale(hudscorescale, hudscorescale, 1); flushhudmatrix(); - int color = hudscoreplayercolour, color2 = hudscoreenemycolour; if(!best) swap(color, color2); - draw_text(buf, int(offset.x), int(offset.y), (color>>16)&0xFF, (color>>8)&0xFF, color&0xFF, hudscorealpha); if(score2 > INT_MIN) draw_text(buf2, int(offset2.x), int(offset2.y), (color2>>16)&0xFF, (color2>>8)&0xFF, color2&0xFF, hudscorealpha); - pophudmatrix(); } } diff --git a/src/fpsgame/server.cpp b/src/fpsgame/server.cpp index ec781c6..2095dd1 100644 --- a/src/fpsgame/server.cpp +++ b/src/fpsgame/server.cpp @@ -1,9 +1,7 @@ #include "game.h" -namespace game -{ - void parseoptions(vector &args) - { +namespace game { + void parseoptions(vector &args) { loopv(args) #ifndef STANDALONE if(!game::clientoption(args[i])) @@ -11,7 +9,6 @@ namespace game if(!server::serveroption(args[i])) conoutf(CON_ERROR, "unknown command-line option: %s", args[i]); } - const char *gameident() { return "fps"; } } @@ -19,105 +16,69 @@ VAR(regenbluearmour, 0, 1, 1); extern ENetAddress masteraddress; -namespace server -{ - struct server_entity // server side version of "entity" type - { +namespace server { + struct server_entity { // server side version of "entity" type { int type; int spawntime; bool spawned; }; - static const int DEATHMILLIS = 300; - struct clientinfo; - - struct gameevent - { + struct gameevent { virtual ~gameevent() {} - virtual bool flush(clientinfo *ci, int fmillis); - virtual void process(clientinfo *ci) {} - + virtual void process(clientinfo *) {} virtual bool keepable() const { return false; } }; - - struct timedevent : gameevent - { + struct timedevent : gameevent { int millis; - bool flush(clientinfo *ci, int fmillis); }; - - struct hitinfo - { + struct hitinfo { int target; int lifesequence; int rays; float dist; vec dir; }; - - struct shotevent : timedevent - { + struct shotevent : timedevent { int id, gun; vec from, to; vector hits; - void process(clientinfo *ci); }; - - struct explodeevent : timedevent - { + struct explodeevent : timedevent { int id, gun; vector hits; - bool keepable() const { return true; } - void process(clientinfo *ci); }; - - struct suicideevent : gameevent - { + struct suicideevent : gameevent { void process(clientinfo *ci); }; - - struct pickupevent : gameevent - { + struct pickupevent : gameevent { int ent; - void process(clientinfo *ci); }; - template - struct projectilestate - { + struct projectilestate { int projs[N]; int numprojs; - projectilestate() : numprojs(0) {} - void reset() { numprojs = 0; } - - void add(int val) - { + void add(int val) { if(numprojs>=N) numprojs = 0; projs[numprojs++] = val; } - - bool remove(int val) - { - loopi(numprojs) if(projs[i]==val) - { + bool remove(int val) { + loopi(numprojs) if(projs[i]==val) { projs[i] = projs[--numprojs]; return true; } return false; } }; - - struct gamestate : fpsstate - { + struct gamestate : fpsstate { vec o; int state, editstate; int lastdeath, deadflush, lastspawn, lifesequence; @@ -126,38 +87,26 @@ namespace server int frags, flags, deaths, teamkills, shotdamage, damage, tokens; int lasttimeplayed, timeplayed; float effectiveness; - gamestate() : state(CS_DEAD), editstate(CS_DEAD), lifesequence(0) {} - - bool isalive(int gamemillis) - { + bool isalive(int gamemillis) { return state==CS_ALIVE || (state==CS_DEAD && gamemillis - lastdeath <= DEATHMILLIS); } - - bool waitexpired(int gamemillis) - { + bool waitexpired(int gamemillis) { return gamemillis - lastshot >= gunwait; } - - void reset() - { + void reset() { if(state!=CS_SPECTATOR) state = editstate = CS_DEAD; maxhealth = 100; maxarmour = 50; rockets.reset(); grenades.reset(); - timeplayed = 0; effectiveness = 0; frags = flags = deaths = teamkills = shotdamage = damage = tokens = 0; - lastdeath = 0; - respawn(); } - - void respawn() - { + void respawn() { fpsstate::respawn(); o = vec(-1e10f, -1e10f, -1e10f); deadflush = 0; @@ -165,25 +114,19 @@ namespace server lastshot = 0; tokens = 0; } - - void reassign() - { + void reassign() { respawn(); rockets.reset(); grenades.reset(); } }; - - struct savedscore - { + struct savedscore { uint ip; string name; int frags, flags, deaths, teamkills, shotdamage, damage; int timeplayed; float effectiveness; - - void save(gamestate &gs) - { + void save(gamestate &gs) { frags = gs.frags; flags = gs.flags; deaths = gs.deaths; @@ -193,9 +136,7 @@ namespace server timeplayed = gs.timeplayed; effectiveness = gs.effectiveness; } - - void restore(gamestate &gs) - { + void restore(gamestate &gs) { gs.frags = frags; gs.flags = flags; gs.deaths = deaths; @@ -206,11 +147,8 @@ namespace server gs.effectiveness = effectiveness; } }; - extern int gamemillis, nextexceeded; - - struct clientinfo - { + struct clientinfo { int clientnum, ownernum, connectmillis, sessionid, overflow; string name, team, mapvote; int playermodel; @@ -236,58 +174,39 @@ namespace server void *authchallenge; int authkickvictim; char *authkickreason; - clientinfo() : getdemo(NULL), getmap(NULL), clipboard(NULL), authchallenge(NULL), authkickreason(NULL) { reset(); } ~clientinfo() { events.deletecontents(); cleanclipboard(); cleanauth(); } - - void addevent(gameevent *e) - { + void addevent(gameevent *e) { if(state.state==CS_SPECTATOR || events.length()>100) delete e; else events.add(e); } - - enum - { + enum { PUSHMILLIS = 3000 }; - - int calcpushrange() - { + int calcpushrange() { ENetPeer *peer = getclientpeer(ownernum); return PUSHMILLIS + ((peer) ? (int) (peer->roundTripTime + peer->roundTripTimeVariance) : (int) ENET_PEER_DEFAULT_ROUND_TRIP_TIME); } - - bool checkpushed(int millis, int range) - { + bool checkpushed(int millis, int range) { return millis >= pushed - range && millis <= pushed + range; } - - void scheduleexceeded() - { + void scheduleexceeded() { if(state.state!=CS_ALIVE || !exceeded) return; int range = calcpushrange(); if(!nextexceeded || exceeded + range < nextexceeded) nextexceeded = exceeded + range; } - - void setexceeded() - { + void setexceeded() { if(state.state==CS_ALIVE && !exceeded && !checkpushed(gamemillis, calcpushrange())) exceeded = gamemillis; scheduleexceeded(); } - - void setpushed() - { + void setpushed() { pushed = max(pushed, gamemillis); if(exceeded && checkpushed(exceeded, calcpushrange())) exceeded = 0; } - - bool checkexceeded() - { + bool checkexceeded() { return state.state==CS_ALIVE && exceeded && gamemillis > exceeded + calcpushrange(); } - - void mapchange() - { + void mapchange() { mapvote[0] = 0; modevote = INT_MAX; state.reset(); @@ -302,36 +221,26 @@ namespace server warned = false; gameclip = false; } - - void reassign() - { + void reassign() { state.reassign(); events.deletecontents(); timesync = false; lastevent = 0; } - - void cleanclipboard(bool fullclean = true) - { + void cleanclipboard(bool fullclean = true) { if(clipboard) { if(--clipboard->referenceCount <= 0) enet_packet_destroy(clipboard); clipboard = NULL; } if(fullclean) lastclipboard = 0; } - - void cleanauthkick() - { + void cleanauthkick() { authkickvictim = -1; DELETEA(authkickreason); } - - void cleanauth(bool full = true) - { + void cleanauth(bool full = true) { authreq = 0; if(authchallenge) { freechallenge(authchallenge); authchallenge = NULL; } if(full) cleanauthkick(); } - - void reset() - { + void reset() { name[0] = team[0] = 0; playermodel = -1; privilege = PRIV_NONE; @@ -346,11 +255,8 @@ namespace server cleanauth(); mapchange(); } - - int geteventmillis(int servmillis, int clientmillis) - { - if(!timesync || (events.empty() && state.waitexpired(servmillis))) - { + int geteventmillis(int servmillis, int clientmillis) { + if(!timesync || (events.empty() && state.waitexpired(servmillis))) { timesync = true; gameoffset = servmillis - clientmillis; return servmillis; @@ -358,15 +264,11 @@ namespace server else return gameoffset + clientmillis; } }; - - struct ban - { + struct ban { int time, expire; uint ip; }; - - namespace aiman - { + namespace aiman { extern void removeai(clientinfo *ci); extern void clearai(); extern void checkai(); @@ -378,29 +280,23 @@ namespace server extern void addclient(clientinfo *ci); extern void changeteam(clientinfo *ci); } - #define MM_MODE 0xF #define MM_AUTOAPPROVE 0x1000 #define MM_PRIVSERV (MM_MODE | MM_AUTOAPPROVE) #define MM_PUBSERV ((1< allowedips; vector bannedips; - - void addban(uint ip, int expire) - { + void addban(uint ip, int expire) { allowedips.removeobj(ip); ban b; b.time = totalmillis; @@ -409,71 +305,49 @@ namespace server loopv(bannedips) if(bannedips[i].expire - b.expire > 0) { bannedips.insert(i, b); return; } bannedips.add(b); } - vector connects, clients, bots; - - void kickclients(uint ip, clientinfo *actor = NULL, int priv = PRIV_NONE) - { - loopvrev(clients) - { + void kickclients(clientinfo *actor = NULL, int priv = PRIV_NONE) { + loopvrev(clients) { clientinfo &c = *clients[i]; if(c.state.aitype != AI_NONE || c.privilege >= PRIV_ADMIN || c.local) continue; if(actor && ((c.privilege > priv && !actor->local) || c.clientnum == actor->clientnum)) continue; - //~if(getclientip(c.clientnum) == ip) disconnect_client(c.clientnum, DISC_KICK); } } - - struct maprotation - { + struct maprotation { static int exclude; int modes; string map; - int calcmodemask() const { return modes&(1< maprotations; int curmaprotation = 0; - VAR(lockmaprotation, 0, 0, 2); - - void maprotationreset() - { + void maprotationreset() { maprotations.setsize(0); curmaprotation = 0; maprotation::exclude = 0; } - - void nextmaprotation() - { + void nextmaprotation() { curmaprotation++; if(maprotations.inrange(curmaprotation) && maprotations[curmaprotation].modes) return; do curmaprotation--; while(maprotations.inrange(curmaprotation) && maprotations[curmaprotation].modes); curmaprotation++; } - - int findmaprotation(int mode, const char *map) - { - for(int i = max(curmaprotation, 0); i < maprotations.length(); i++) - { + int findmaprotation(int mode, const char *map) { + for(int i = max(curmaprotation, 0); i < maprotations.length(); i++) { maprotation &rot = maprotations[i]; if(!rot.modes) break; if(rot.match(mode, map)) return i; @@ -481,35 +355,28 @@ namespace server int start; for(start = max(curmaprotation, 0) - 1; start >= 0; start--) if(!maprotations[start].modes) break; start++; - for(int i = start; i < curmaprotation; i++) - { + for(int i = start; i < curmaprotation; i++) { maprotation &rot = maprotations[i]; if(!rot.modes) break; if(rot.match(mode, map)) return i; } int best = -1; - loopv(maprotations) - { + loopv(maprotations) { maprotation &rot = maprotations[i]; if(rot.match(mode, map) && (best < 0 || maprotations[best].includes(rot))) best = i; } return best; } - - bool searchmodename(const char *haystack, const char *needle) - { + bool searchmodename(const char *haystack, const char *needle) { if(!needle[0]) return true; - do - { - if(needle[0] != '.') - { + do { + if(needle[0] != '.') { haystack = strchr(haystack, needle[0]); if(!haystack) break; haystack++; } const char *h = haystack, *n = needle+1; - for(; *h && *n; h++) - { + for(; *h && *n; h++) { if(*h == *n) n++; else if(*h != ' ') break; } @@ -518,16 +385,12 @@ namespace server } while(needle[0] != '.'); return false; } - - int genmodemask(vector &modes) - { + int genmodemask(vector &modes) { int modemask = 0; - loopv(modes) - { + loopv(modes) { const char *mode = modes[i]; int op = mode[0]; - switch(mode[0]) - { + switch(mode[0]) { case '*': modemask |= 1< modes, maps; - for(int i = 0; i + 1 < numargs; i += 2) - { + for(int i = 0; i + 1 < numargs; i += 2) { explodelist(args[i].getstr(), modes); explodelist(args[i+1].getstr(), maps); int modemask = genmodemask(modes); @@ -582,74 +438,54 @@ namespace server modes.deletearrays(); maps.deletearrays(); } - if(maprotations.length() && maprotations.last().modes) - { + if(maprotations.length() && maprotations.last().modes) { maprotation &rot = maprotations.add(); rot.modes = 0; rot.map[0] = '\0'; } } - COMMAND(maprotationreset, ""); COMMANDN(maprotation, addmaprotations, "ss2V"); - - struct demofile - { + struct demofile { string info; uchar *data; int len; }; - vector demos; - bool demonextmatch = false; stream *demotmp = NULL, *demorecord = NULL, *demoplayback = NULL; int nextplayback = 0; - VAR(maxdemos, 0, 5, 25); VAR(maxdemosize, 0, 16, 31); VAR(restrictdemos, 0, 1, 1); VARF(autorecorddemo, 0, 0, 1, demonextmatch = autorecorddemo!=0); - VAR(restrictpausegame, 0, 1, 1); VAR(restrictgamespeed, 0, 1, 1); - SVAR(serverdesc, ""); SVAR(serverpass, ""); SVAR(adminpass, ""); VARF(publicserver, 0, 0, 2, { - switch(publicserver) - { + switch(publicserver) { case 0: default: mastermask = MM_PRIVSERV; break; case 1: mastermask = MM_PUBSERV; break; case 2: mastermask = MM_COOPSERV; break; } }); SVAR(servermotd, ""); - - struct teamkillkick - { + struct teamkillkick { int modes, limit, ban; - - bool match(int mode) const - { + bool match(int mode) const { return (modes&(1<<(mode-STARTGAMEMODE)))!=0; } - - bool includes(const teamkillkick &tk) const - { + bool includes(const teamkillkick &tk) const { return tk.modes != modes && (tk.modes & modes) == tk.modes; } }; vector teamkillkicks; - - void teamkillkickreset() - { + void teamkillkickreset() { teamkillkicks.setsize(0); } - - void addteamkillkick(char *modestr, int *limit, int *ban) - { + void addteamkillkick(char *modestr, int *limit, int *ban) { vector modes; explodelist(modestr, modes); teamkillkick &kick = teamkillkicks.add(); @@ -658,25 +494,19 @@ namespace server kick.ban = *ban > 0 ? *ban*60000 : (*ban < 0 ? 0 : 30*60000); modes.deletearrays(); } - COMMAND(teamkillkickreset, ""); COMMANDN(teamkillkick, addteamkillkick, "sii"); - - struct teamkillinfo - { + struct teamkillinfo { uint ip; int teamkills; }; vector teamkills; bool shouldcheckteamkills = false; - - void addteamkill(clientinfo *actor, clientinfo *victim, int n) - { + void addteamkill(clientinfo *actor, clientinfo *victim, int n) { if(!m_timed || actor->state.aitype != AI_NONE || actor->local || actor->privilege || (victim && victim->state.aitype != AI_NONE)) return; shouldcheckteamkills = true; uint ip = getclientip(actor->clientnum); - loopv(teamkills) if(teamkills[i].ip == ip) - { + loopv(teamkills) if(teamkills[i].ip == ip) { teamkills[i].teamkills += n; return; } @@ -684,92 +514,67 @@ namespace server tk.ip = ip; tk.teamkills = n; } - - void checkteamkills() - { + void checkteamkills() { teamkillkick *kick = NULL; if(m_timed) loopv(teamkillkicks) if(teamkillkicks[i].match(gamemode) && (!kick || kick->includes(teamkillkicks[i]))) kick = &teamkillkicks[i]; - if(kick) loopvrev(teamkills) - { + if(kick) loopvrev(teamkills) { teamkillinfo &tk = teamkills[i]; - if(tk.teamkills >= kick->limit) - { + if(tk.teamkills >= kick->limit) { if(kick->ban > 0) addban(tk.ip, kick->ban); - kickclients(tk.ip); + kickclients(); teamkills.removeunordered(i); } } shouldcheckteamkills = false; } - void *newclientinfo() { return new clientinfo; } void deleteclientinfo(void *ci) { delete (clientinfo *)ci; } - - clientinfo *getinfo(int n) - { + clientinfo *getinfo(int n) { if(n < MAXCLIENTS) return (clientinfo *)getclientinfo(n); n -= MAXCLIENTS; return bots.inrange(n) ? bots[n] : NULL; } - uint mcrc = 0; vector ments; vector sents; vector scores; - - int msgsizelookup(int msg) - { + int msgsizelookup(int msg) { static int sizetable[NUMMSG] = { -1 }; - if(sizetable[0] < 0) - { + if(sizetable[0] < 0) { memset(sizetable, -1, sizeof(sizetable)); for(const int *p = msgsizes; *p >= 0; p += 2) sizetable[p[0]] = p[1]; } return msg >= 0 && msg < NUMMSG ? sizetable[msg] : -1; } - - const char *modename(int n, const char *unknown) - { + const char *modename(int n, const char *unknown) { if(m_valid(n)) return gamemodes[n - STARTGAMEMODE].name; return unknown; } - - const char *mastermodename(int n, const char *unknown) - { + const char *mastermodename(int n, const char *unknown) { return (n>=MM_START && size_t(n-MM_START)clientnum!=exclude && (!nospec || ci->state.state!=CS_SPECTATOR || (priv && (ci->privilege || ci->local))) && (!noai || ci->state.aitype == AI_NONE)) n++; } return n; } - - bool duplicatename(clientinfo *ci, const char *name) - { + bool duplicatename(clientinfo *ci, const char *name) { if(!name) name = ci->name; loopv(clients) if(clients[i]!=ci && !strcmp(name, clients[i]->name)) return true; return false; } - - const char *colorname(clientinfo *ci, const char *name = NULL) - { + const char *colorname(clientinfo *ci, const char *name = NULL) { if(!name) name = ci->name; if(name[0] && !duplicatename(ci, name) && ci->state.aitype == AI_NONE) return name; static string cname[3]; @@ -812,16 +608,12 @@ namespace server formatstring(cname[cidx], ci->state.aitype == AI_NONE ? "%s \fs\f5(%d)\fr" : "%s \fs\f5[%d]\fr", name, ci->clientnum); return cname[cidx]; } - bool canspawnitem(int type) { return !m_noitems && (type>=I_SHELLS && type<=I_QUAD && (!m_noammo || typeI_CARTRIDGES)); } - - int spawntime(int type) - { + int spawntime(int type) { int np = numclients(-1, true, false); np = np<3 ? 4 : (np>4 ? 2 : 3); // spawn times are dependent on number of players int sec = 0; - switch(type) - { + switch(type) { case I_SHELLS: case I_BULLETS: case I_ROCKETS: @@ -838,11 +630,8 @@ namespace server } return sec*1000; } - - bool delayspawn(int type) - { - switch(type) - { + bool delayspawn(int type) { + switch(type) { case I_GREENARMOUR: case I_YELLOWARMOUR: case I_BOOST: @@ -852,14 +641,11 @@ namespace server return false; } } - - bool pickup(int i, int sender) // server side item pickup, acknowledge first client that gets it - { + bool pickup(int i, int sender) { // server side item pickup, acknowledge first client that gets it { if((m_timed && gamemillis>=gamelimit) || !sents.inrange(i) || !sents[i].spawned) return false; clientinfo *ci = getinfo(sender); if(!ci) return false; - if(!ci->local && !ci->state.canpickup(sents[i].type)) - { + if(!ci->local && !ci->state.canpickup(sents[i].type)) { sendf(sender, 1, "ri3", N_ITEMACC, i, -1); return false; } @@ -869,30 +655,21 @@ namespace server ci->state.pickup(sents[i].type); return true; } - static hashset teaminfos; - - void clearteaminfo() - { + void clearteaminfo() { teaminfos.clear(); } - bool teamhasplayers(const char *team) { loopv(clients) if(!strcmp(clients[i]->team, team)) return true; return false; } - - bool pruneteaminfo() - { + bool pruneteaminfo() { int oldteams = teaminfos.numelems; enumerate(teaminfos, teaminfo, old, if(!old.frags && !teamhasplayers(old.team)) teaminfos.remove(old.team); ); return teaminfos.numelems < oldteams; } - - teaminfo *addteaminfo(const char *team) - { + teaminfo *addteaminfo(const char *team) { teaminfo *t = teaminfos.access(team); - if(!t) - { + if(!t) { if(teaminfos.numelems >= MAXTEAMS && !pruneteaminfo()) return NULL; t = &teaminfos[team]; copystring(t->team, team, sizeof(t->team)); @@ -900,13 +677,10 @@ namespace server } return t; } - - clientinfo *choosebestclient(float &bestrank) - { + clientinfo *choosebestclient(float &bestrank) { clientinfo *best = NULL; bestrank = -1; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.timeplayed<0) continue; float rank = ci->state.state!=CS_SPECTATOR ? ci->state.effectiveness/max(ci->state.timeplayed, 1) : -1; @@ -914,19 +688,14 @@ namespace server } return best; } - VAR(persistteams, 0, 0, 1); - - void autoteam() - { + void autoteam() { static const char * const teamnames[2] = {"good", "evil"}; vector team[2]; float teamrank[2] = {0, 0}; - for(int round = 0, remaining = clients.length(); remaining>=0; round++) - { + for(int round = 0, remaining = clients.length(); remaining>=0; round++) { int first = round&1, second = (round+1)&1, selected = 0; - while(teamrank[first] <= teamrank[second]) - { + while(teamrank[first] <= teamrank[second]) { float rank; clientinfo *ci = choosebestclient(rank); if(!ci) break; @@ -940,15 +709,12 @@ namespace server if(!selected) break; remaining -= selected; } - loopi(sizeof(team)/sizeof(team[0])) - { + loopi(sizeof(team)/sizeof(team[0])) { addteaminfo(teamnames[i]); - loopvj(team[i]) - { + loopvj(team[i]) { clientinfo *ci = team[i][j]; if(!strcmp(ci->team, teamnames[i])) continue; - if(persistteams && ci->team[0]) - { + if(persistteams && ci->team[0]) { addteaminfo(ci->team); continue; } @@ -957,29 +723,21 @@ namespace server } } } - - struct teamrank - { + struct teamrank { const char *name; float rank; int clients; - teamrank(const char *name) : name(name), rank(0), clients(0) {} }; - - const char *chooseworstteam(const char *suggest = NULL, clientinfo *exclude = NULL) - { + const char *chooseworstteam(clientinfo *exclude = NULL) { teamrank teamranks[2] = { teamrank("good"), teamrank("evil") }; const int numteams = sizeof(teamranks)/sizeof(teamranks[0]); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci==exclude || ci->state.aitype!=AI_NONE || ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; ci->state.lasttimeplayed = lastmillis; - - loopj(numteams) if(!strcmp(ci->team, teamranks[j].name)) - { + loopj(numteams) if(!strcmp(ci->team, teamranks[j].name)) { teamrank &ts = teamranks[j]; ts.rank += ci->state.effectiveness/max(ci->state.timeplayed, 1); ts.clients++; @@ -987,24 +745,19 @@ namespace server } } teamrank *worst = &teamranks[numteams-1]; - loopi(numteams-1) - { + loopi(numteams-1) { teamrank &ts = teamranks[i]; if(ts.rank < worst->rank || (ts.rank == worst->rank && ts.clients < worst->clients)) worst = &ts; } return worst->name; } - - void prunedemos(int extra = 0) - { + void prunedemos(int extra = 0) { int n = clamp(demos.length() + extra - maxdemos, 0, demos.length()); if(n <= 0) return; loopi(n) delete[] demos[i].data; demos.remove(0, n); } - - void adddemo() - { + void adddemo() { if(!demotmp) return; int len = (int)min(demotmp->size(), stream::offset((maxdemosize<<20) + 0x10000)); demofile &d = demos.add(); @@ -1019,22 +772,15 @@ namespace server demotmp->read(d.data, len); DELETEP(demotmp); } - - void enddemorecord() - { + void enddemorecord() { if(!demorecord) return; - DELETEP(demorecord); - if(!demotmp) return; if(!maxdemos || !maxdemosize) { DELETEP(demotmp); return; } - prunedemos(1); adddemo(); } - - void writedemo(int chan, void *data, int len) - { + void writedemo(int chan, void *data, int len) { if(!demorecord) return; int stamp[3] = { gamemillis, chan, len }; lilswap(stamp, 3); @@ -1042,86 +788,61 @@ namespace server demorecord->write(data, len); if(demorecord->rawtell() >= (maxdemosize<<20)) enddemorecord(); } - - void recordpacket(int chan, void *data, int len) - { + void recordpacket(int chan, void *data, int len) { writedemo(chan, data, len); } - int welcomepacket(packetbuf &p, clientinfo *ci); void sendwelcome(clientinfo *ci); - - void setupdemorecord() - { + void setupdemorecord() { if(!m_mp(gamemode) || m_edit) return; - demotmp = opentempfile("demorecord", "w+b"); if(!demotmp) return; - stream *f = opengzfile(NULL, "wb", demotmp); if(!f) { DELETEP(demotmp); return; } - sendservmsg("recording demo"); - demorecord = f; - demoheader hdr; memcpy(hdr.magic, DEMO_MAGIC, sizeof(hdr.magic)); hdr.version = DEMO_VERSION; hdr.protocol = PROTOCOL_VERSION; lilswap(&hdr.version, 2); demorecord->write(&hdr, sizeof(demoheader)); - packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); welcomepacket(p, NULL); writedemo(1, p.buf, p.len); } - - void listdemos(int cn) - { + void listdemos(int cn) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putint(p, N_SENDDEMOLIST); putint(p, demos.length()); loopv(demos) sendstring(demos[i].info, p); sendpacket(cn, 1, p.finalize()); } - - void cleardemos(int n) - { - if(!n) - { + void cleardemos(int n) { + if(!n) { loopv(demos) delete[] demos[i].data; demos.shrink(0); sendservmsg("cleared all demos"); } - else if(demos.inrange(n-1)) - { + else if(demos.inrange(n-1)) { delete[] demos[n-1].data; demos.remove(n-1); sendservmsgf("cleared demo %d", n); } } - - static void freegetmap(ENetPacket *packet) - { - loopv(clients) - { + static void freegetmap(ENetPacket *packet) { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->getmap == packet) ci->getmap = NULL; } } - - static void freegetdemo(ENetPacket *packet) - { - loopv(clients) - { + static void freegetdemo(ENetPacket *packet) { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->getdemo == packet) ci->getdemo = NULL; } } - - void senddemo(clientinfo *ci, int num, int tag) - { + void senddemo(clientinfo *ci, int num, int tag) { if(ci->getdemo) return; if(!num) num = demos.length(); if(!demos.inrange(num-1)) return; @@ -1129,39 +850,28 @@ namespace server if((ci->getdemo = sendf(ci->clientnum, 2, "riim", N_SENDDEMO, tag, d.len, d.data))) ci->getdemo->freeCallback = freegetdemo; } - - void enddemoplayback() - { + void enddemoplayback() { if(!demoplayback) return; DELETEP(demoplayback); - loopv(clients) sendf(clients[i]->clientnum, 1, "ri3", N_DEMOPLAYBACK, 0, clients[i]->clientnum); - sendservmsg("demo playback finished"); - loopv(clients) sendwelcome(clients[i]); } - SVARP(demodir, "demo"); - - const char *getdemofile(const char *file, bool init) - { + const char *getdemofile(const char *file, bool init) { if(!demodir[0]) return NULL; static string buf; copystring(buf, demodir); int dirlen = strlen(buf); if(buf[dirlen] != '/' && buf[dirlen] != '\\' && dirlen+1 < (int)sizeof(buf)) { buf[dirlen++] = '/'; buf[dirlen] = '\0'; } - if(init) - { + if(init) { const char *dir = findfile(buf, "w"); if(!fileexists(dir, "w")) createdir(dir); } concatstring(buf, file); return buf; } - - void setupdemoplayback() - { + void setupdemoplayback() { if(demoplayback) return; demoheader hdr; string msg; @@ -1175,48 +885,37 @@ namespace server if(!demoplayback) formatstring(msg, "could not read demo \"%s\"", file); else if(demoplayback->read(&hdr, sizeof(demoheader))!=sizeof(demoheader) || memcmp(hdr.magic, DEMO_MAGIC, sizeof(hdr.magic))) formatstring(msg, "\"%s\" is not a demo file", file); - else - { + else { lilswap(&hdr.version, 2); if(hdr.version!=DEMO_VERSION) formatstring(msg, "demo \"%s\" requires an %s version of Cube 2: Sauerbraten", file, hdr.versionread(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) - { + if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { enddemoplayback(); return; } lilswap(&nextplayback, 1); } - - void readdemo() - { + void readdemo() { if(!demoplayback) return; - while(gamemillis>=nextplayback) - { + while(gamemillis>=nextplayback) { int chan, len; if(demoplayback->read(&chan, sizeof(chan))!=sizeof(chan) || - demoplayback->read(&len, sizeof(len))!=sizeof(len)) - { + demoplayback->read(&len, sizeof(len))!=sizeof(len)) { enddemoplayback(); return; } lilswap(&chan, 1); lilswap(&len, 1); ENetPacket *packet = enet_packet_create(NULL, len+1, 0); - if(!packet || demoplayback->read(packet->data+1, len)!=size_t(len)) - { + if(!packet || demoplayback->read(packet->data+1, len)!=size_t(len)) { if(packet) enet_packet_destroy(packet); enddemoplayback(); return; @@ -1225,24 +924,19 @@ namespace server sendpacket(-1, chan, packet); if(!packet->referenceCount) enet_packet_destroy(packet); if(!demoplayback) break; - if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) - { + if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { enddemoplayback(); return; } lilswap(&nextplayback, 1); } } - - void timeupdate(int secs) - { + void timeupdate(int secs) { if(!demoplayback) return; if(secs <= 0) interm = -1; else gamelimit = max(gamelimit, nextplayback + secs*1000); } - - void seekdemo(char *t) - { + void seekdemo(char *t) { if(!demoplayback) return; bool rev = *t == '-'; if(rev) t++; @@ -1251,170 +945,123 @@ namespace server else { secs = mins; mins = 0; } if(*t == '.') millis = strtoul(t+1, &t, 10); int offset = max(millis + (mins*60 + secs)*1000, 0), prevmillis = gamemillis; - if(rev) while(gamelimit - offset > gamemillis) - { + if(rev) while(gamelimit - offset > gamemillis) { gamemillis = gamelimit - offset; readdemo(); } - else if(offset > gamemillis) - { + else if(offset > gamemillis) { gamemillis = offset; readdemo(); } - if(gamemillis > prevmillis) - { + if(gamemillis > prevmillis) { if(!interm) sendf(-1, 1, "ri2", N_TIMEUP, max((gamelimit - gamemillis)/1000, 1)); } } - - ICOMMAND(seekdemo, "sN$", (char *t, int *numargs, ident *id), - { + ICOMMAND(seekdemo, "sN$", (char *t, int *numargs, ident *id), { if(*numargs > 0) seekdemo(t); - else - { + else { int secs = gamemillis/1000; defformatstring(str, "%d:%02d.%03d", secs/60, secs%60, gamemillis%1000); if(*numargs < 0) result(str); else printsvar(id, str); } }); - - void stopdemo() - { + void stopdemo() { if(m_demo) enddemoplayback(); else enddemorecord(); } - - void pausegame(bool val, clientinfo *ci = NULL) - { + void pausegame(bool val, clientinfo *ci = NULL) { if(gamepaused==val) return; gamepaused = val; sendf(-1, 1, "riii", N_PAUSEGAME, gamepaused ? 1 : 0, ci ? ci->clientnum : -1); } - - void checkpausegame() - { + void checkpausegame() { if(!gamepaused) return; int admins = 0; loopv(clients) if(clients[i]->privilege >= (restrictpausegame ? PRIV_ADMIN : PRIV_MASTER) || clients[i]->local) admins++; if(!admins) pausegame(false); } - - void forcepaused(bool paused) - { + void forcepaused(bool paused) { pausegame(paused); } - bool ispaused() { return gamepaused; } - - void changegamespeed(int val, clientinfo *ci = NULL) - { + void changegamespeed(int val, clientinfo *ci = NULL) { val = clamp(val, 10, 1000); if(gamespeed==val) return; gamespeed = val; sendf(-1, 1, "riii", N_GAMESPEED, gamespeed, ci ? ci->clientnum : -1); } - - void forcegamespeed(int speed) - { + void forcegamespeed(int speed) { changegamespeed(speed); } - int scaletime(int t) { return t*gamespeed; } - SVAR(serverauth, ""); - - struct userkey - { + struct userkey { char *name; char *desc; - userkey() : name(NULL), desc(NULL) {} userkey(char *name, char *desc) : name(name), desc(desc) {} }; - static inline uint hthash(const userkey &k) { return ::hthash(k.name); } static inline bool htcmp(const userkey &x, const userkey &y) { return !strcmp(x.name, y.name) && !strcmp(x.desc, y.desc); } - - struct userinfo : userkey - { + struct userinfo : userkey { void *pubkey; int privilege; - userinfo() : pubkey(NULL), privilege(PRIV_NONE) {} ~userinfo() { delete[] name; delete[] desc; if(pubkey) freepubkey(pubkey); } }; hashset users; - - void adduser(char *name, char *desc, char *pubkey, char *priv) - { + void adduser(char *name, char *desc, char *pubkey, char *priv) { userkey key(name, desc); userinfo &u = users[key]; if(u.pubkey) { freepubkey(u.pubkey); u.pubkey = NULL; } if(!u.name) u.name = newstring(name); if(!u.desc) u.desc = newstring(desc); u.pubkey = parsepubkey(pubkey); - switch(priv[0]) - { + switch(priv[0]) { case 'a': case 'A': u.privilege = PRIV_ADMIN; break; case 'm': case 'M': default: u.privilege = PRIV_AUTH; break; case 'n': case 'N': u.privilege = PRIV_NONE; break; } } COMMAND(adduser, "ssss"); - - void clearusers() - { + void clearusers() { users.clear(); } COMMAND(clearusers, ""); - - void hashpassword(int cn, int sessionid, const char *pwd, char *result, int maxlen) - { + void hashpassword(int cn, int sessionid, const char *pwd, char *result, int maxlen) { char buf[2*sizeof(string)]; formatstring(buf, "%d %d ", cn, sessionid); concatstring(buf, pwd, sizeof(buf)); if(!hashstring(buf, result, maxlen)) *result = '\0'; } - - bool checkpassword(clientinfo *ci, const char *wanted, const char *given) - { + bool checkpassword(clientinfo *ci, const char *wanted, const char *given) { string hash; hashpassword(ci->clientnum, ci->sessionid, wanted, hash, sizeof(hash)); return !strcmp(hash, given); } - - void revokemaster(clientinfo *ci) - { + void revokemaster(clientinfo *ci) { ci->privilege = PRIV_NONE; if(ci->state.state==CS_SPECTATOR && !ci->local) aiman::removeai(ci); } - extern void connected(clientinfo *ci); - - bool setmaster(clientinfo *ci, bool val, const char *pass = "", const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_MASTER, bool force = false, bool trial = false) - { + bool setmaster(clientinfo *ci, bool val, const char *pass = "", const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_MASTER, bool force = false, bool trial = false) { if(authname && !val) return false; const char *name = ""; - if(val) - { + if(val) { bool haspass = adminpass[0] && checkpassword(ci, adminpass, pass); int wantpriv = ci->local || haspass ? PRIV_ADMIN : authpriv; if(wantpriv <= ci->privilege) return true; - else if(wantpriv <= PRIV_MASTER && !force) - { - if(ci->state.state==CS_SPECTATOR) - { + else if(wantpriv <= PRIV_MASTER && !force) { + if(ci->state.state==CS_SPECTATOR) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "Spectators may not claim master."); return false; } - loopv(clients) if(ci!=clients[i] && clients[i]->privilege) - { + loopv(clients) if(ci!=clients[i] && clients[i]->privilege) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "Master is already claimed."); return false; } - if(!authname && !(mastermask&MM_AUTOAPPROVE) && !ci->privilege && !ci->local) - { + if(!authname && !(mastermask&MM_AUTOAPPROVE) && !ci->privilege && !ci->local) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "This server requires you to use the \"/auth\" command to claim master."); return false; } @@ -1423,8 +1070,7 @@ namespace server ci->privilege = wantpriv; name = privname(ci->privilege); } - else - { + else { if(!ci->privilege) return false; if(trial) return true; name = privname(ci->privilege); @@ -1432,14 +1078,12 @@ namespace server } bool hasmaster = false; loopv(clients) if(clients[i]->local || clients[i]->privilege >= PRIV_MASTER) hasmaster = true; - if(!hasmaster) - { + if(!hasmaster) { mastermode = MM_OPEN; allowedips.shrink(0); } string msg; - if(val && authname) - { + if(val && authname) { if(authdesc && authdesc[0]) formatstring(msg, "%s claimed %s as '\fs\f5%s\fr' [\fs\f0%s\fr]", colorname(ci), name, authname, authdesc); else formatstring(msg, "%s claimed %s as '\fs\f5%s\fr'", colorname(ci), name, authname); } @@ -1449,8 +1093,7 @@ namespace server sendstring(msg, p); putint(p, N_CURRENTMASTER); putint(p, mastermode); - loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) - { + loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) { putint(p, clients[i]->clientnum); putint(p, clients[i]->privilege); } @@ -1459,24 +1102,18 @@ namespace server checkpausegame(); return true; } - - bool trykick(clientinfo *ci, int victim, const char *reason = NULL, const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_NONE, bool trial = false) - { + bool trykick(clientinfo *ci, int victim, const char *reason = NULL, const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_NONE, bool trial = false) { int priv = ci->privilege; - if(authname) - { + if(authname) { if(priv >= authpriv || ci->local) authname = authdesc = NULL; else priv = authpriv; } - if((priv || ci->local) && ci->clientnum!=victim) - { + if((priv || ci->local) && ci->clientnum!=victim) { clientinfo *vinfo = (clientinfo *)getclientinfo(victim); - if(vinfo && vinfo->connected && (priv >= vinfo->privilege || ci->local) && vinfo->privilege < PRIV_ADMIN && !vinfo->local) - { + if(vinfo && vinfo->connected && (priv >= vinfo->privilege || ci->local) && vinfo->privilege < PRIV_ADMIN && !vinfo->local) { if(trial) return true; string kicker; - if(authname) - { + if(authname) { if(authdesc && authdesc[0]) formatstring(kicker, "%s as '\fs\f5%s\fr' [\fs\f0%s\fr]", colorname(ci), authname, authdesc); else formatstring(kicker, "%s as '\fs\f5%s\fr'", colorname(ci), authname); } @@ -1485,23 +1122,18 @@ namespace server else sendservmsgf("%s kicked %s", kicker, colorname(vinfo)); uint ip = getclientip(victim); addban(ip, 4*60*60000); - kickclients(ip, ci, priv); + kickclients(ci, priv); } } return false; } - - savedscore *findscore(clientinfo *ci, bool insert) - { + savedscore *findscore(clientinfo *ci, bool insert) { uint ip = getclientip(ci->clientnum); if(!ip && !ci->local) return 0; - if(!insert) - { - loopv(clients) - { + if(!insert) { + loopv(clients) { clientinfo *oi = clients[i]; - if(oi->clientnum != ci->clientnum && getclientip(oi->clientnum) == ip && !strcmp(oi->name, ci->name)) - { + if(oi->clientnum != ci->clientnum && getclientip(oi->clientnum) == ip && !strcmp(oi->name, ci->name)) { oi->state.timeplayed += lastmillis - oi->state.lasttimeplayed; oi->state.lasttimeplayed = lastmillis; static savedscore curscore; @@ -1510,8 +1142,7 @@ namespace server } } } - loopv(scores) - { + loopv(scores) { savedscore &sc = scores[i]; if(sc.ip == ip && !strcmp(sc.name, ci->name)) return ≻ } @@ -1521,30 +1152,22 @@ namespace server copystring(sc.name, ci->name); return ≻ } - - void savescore(clientinfo *ci) - { + void savescore(clientinfo *ci) { savedscore *sc = findscore(ci, true); if(sc) sc->save(ci->state); } - - static struct msgfilter - { + static struct msgfilter { uchar msgmask[NUMMSG]; - - msgfilter(int msg, ...) - { + msgfilter(int msg, ...) { memset(msgmask, 0, sizeof(msgmask)); va_list msgs; va_start(msgs, msg); - for(uchar val = 1; msg < NUMMSG; msg = va_arg(msgs, int)) - { + for(uchar val = 1; msg < NUMMSG; msg = va_arg(msgs, int)) { if(msg < 0) val = uchar(-msg); else msgmask[msg] = val; } va_end(msgs); } - uchar operator[](int msg) const { return msg >= 0 && msg < NUMMSG ? msgmask[msg] : 0; } } msgfilter(-1, N_CONNECT, N_SERVINFO, N_INITCLIENT, N_WELCOME, N_MAPCHANGE, N_SERVMSG, N_DAMAGE, N_HITPUSH, N_SHOTFX, N_EXPLODEFX, N_DIED, N_SPAWNSTATE, N_FORCEDEATH, N_TEAMINFO, N_ITEMACC, N_ITEMSPAWN, N_TIMEUP, N_CDIS, N_CURRENTMASTER, N_PONG, N_RESUME, @@ -1553,13 +1176,9 @@ namespace server N_NEWMAP, N_GETMAP, N_SENDMAP, N_CLIPBOARD, -3, N_EDITENT, N_EDITF, N_EDITT, N_EDITM, N_FLIP, N_COPY, N_PASTE, N_ROTATE, N_REPLACE, N_DELCUBE, N_EDITVAR, N_EDITVSLOT, N_UNDO, N_REDO, -4, N_POS, NUMMSG), connectfilter(-1, N_CONNECT, -2, N_AUTHANS, -3, N_PING, NUMMSG); - - int checktype(int type, clientinfo *ci) - { - if(ci) - { - if(!ci->connected) switch(connectfilter[type]) - { + int checktype(int type, clientinfo *ci) { + if(ci) { + if(!ci->connected) switch(connectfilter[type]) { // allow only before authconnect case 1: return !ci->connectauth ? type : -1; // allow only during authconnect @@ -1571,8 +1190,7 @@ namespace server } if(ci->local) return type; } - switch(msgfilter[type]) - { + switch(msgfilter[type]) { // server-only messages case 1: return ci ? -1 : type; // only allowed in coop-edit @@ -1585,54 +1203,41 @@ namespace server if(ci && ++ci->overflow >= 200) return -2; return type; } - - struct worldstate - { + struct worldstate { int uses, len; uchar *data; - worldstate() : uses(0), len(0), data(NULL) {} - void setup(int n) { len = n; data = new uchar[n]; } void cleanup() { DELETEA(data); len = 0; } bool contains(const uchar *p) const { return p >= data && p < &data[len]; } }; vector worldstates; bool reliablemessages = false; - - void cleanworldstate(ENetPacket *packet) - { - loopv(worldstates) - { + void cleanworldstate(ENetPacket *packet) { + loopv(worldstates) { worldstate &ws = worldstates[i]; if(!ws.contains(packet->data)) continue; ws.uses--; - if(ws.uses <= 0) - { + if(ws.uses <= 0) { ws.cleanup(); worldstates.removeunordered(i); } break; } } - - void flushclientposition(clientinfo &ci) - { + void flushclientposition(clientinfo &ci) { if(ci.position.empty() || (!hasnonlocalclients() && !demorecord)) return; packetbuf p(ci.position.length(), 0); p.put(ci.position.getbuf(), ci.position.length()); ci.position.setsize(0); sendpacket(-1, 0, p.finalize(), ci.ownernum); } - - static void sendpositions(worldstate &ws, ucharbuf &wsbuf) - { + static void sendpositions(worldstate &ws, ucharbuf &wsbuf) { if(wsbuf.empty()) return; int wslen = wsbuf.length(); recordpacket(0, wsbuf.buf, wslen); wsbuf.put(wsbuf.buf, wslen); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; uchar *data = wsbuf.buf; @@ -1646,9 +1251,7 @@ namespace server } wsbuf.offset(wsbuf.length()); } - - static inline void addposition(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) - { + static inline void addposition(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) { if(bi.position.empty()) return; if(wsbuf.length() + bi.position.length() > mtu) sendpositions(ws, wsbuf); int offset = wsbuf.length(); @@ -1658,15 +1261,12 @@ namespace server if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; } else ci.wslen += len; } - - static void sendmessages(worldstate &ws, ucharbuf &wsbuf) - { + static void sendmessages(worldstate &ws, ucharbuf &wsbuf) { if(wsbuf.empty()) return; int wslen = wsbuf.length(); recordpacket(1, wsbuf.buf, wslen); wsbuf.put(wsbuf.buf, wslen); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; uchar *data = wsbuf.buf; @@ -1680,9 +1280,7 @@ namespace server } wsbuf.offset(wsbuf.length()); } - - static inline void addmessages(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) - { + static inline void addmessages(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) { if(bi.messages.empty()) return; if(wsbuf.length() + 10 + bi.messages.length() > mtu) sendmessages(ws, wsbuf); int offset = wsbuf.length(); @@ -1695,20 +1293,16 @@ namespace server if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; } else ci.wslen += len; } - - bool buildworldstate() - { + bool buildworldstate() { int wsmax = 0; - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; ci.overflow = 0; ci.wsdata = NULL; wsmax += ci.position.length(); if(ci.messages.length()) wsmax += 10 + ci.messages.length(); } - if(wsmax <= 0) - { + if(wsmax <= 0) { reliablemessages = false; return false; } @@ -1717,16 +1311,14 @@ namespace server int mtu = getservermtu() - 100; if(mtu <= 0) mtu = ws.len; ucharbuf wsbuf(ws.data, ws.len); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; addposition(ws, wsbuf, mtu, ci, ci); loopvj(ci.bots) addposition(ws, wsbuf, mtu, *ci.bots[j], ci); } sendpositions(ws, wsbuf); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; addmessages(ws, wsbuf, mtu, ci, ci); @@ -1739,9 +1331,7 @@ namespace server worldstates.drop(); return false; } - - bool sendpackets(bool force) - { + bool sendpackets(bool force) { if(clients.empty() || (!hasnonlocalclients() && !demorecord)) return false; enet_uint32 curtime = enet_time_get()-lastsend; if(curtime<33 && !force) return false; @@ -1749,10 +1339,8 @@ namespace server lastsend += curtime - (curtime%33); return flush; } - template - void sendstate(gamestate &gs, T &p) - { + void sendstate(gamestate &gs, T &p) { putint(p, gs.lifesequence); putint(p, gs.health); putint(p, gs.maxhealth); @@ -1762,16 +1350,12 @@ namespace server putint(p, gs.gunselect); loopi(GUN_PISTOL-GUN_SG+1) putint(p, gs.ammo[GUN_SG+i]); } - - void spawnstate(clientinfo *ci) - { + void spawnstate(clientinfo *ci) { gamestate &gs = ci->state; gs.spawnstate(gamemode); gs.lifesequence = (gs.lifesequence + 1)&0x7F; } - - void sendspawn(clientinfo *ci) - { + void sendspawn(clientinfo *ci) { gamestate &gs = ci->state; spawnstate(ci); sendf(ci->ownernum, 1, "rii8v", N_SPAWNSTATE, ci->clientnum, gs.lifesequence, @@ -1780,18 +1364,13 @@ namespace server gs.gunselect, GUN_PISTOL-GUN_SG+1, &gs.ammo[GUN_SG]); gs.lastspawn = gamemillis; } - - void sendwelcome(clientinfo *ci) - { + void sendwelcome(clientinfo *ci) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); int chan = welcomepacket(p, ci); sendpacket(ci->clientnum, chan, p.finalize()); } - - void putinitclient(clientinfo *ci, packetbuf &p) - { - if(ci->state.aitype != AI_NONE) - { + void putinitclient(clientinfo *ci, packetbuf &p) { + if(ci->state.aitype != AI_NONE) { putint(p, N_INITAI); putint(p, ci->clientnum); putint(p, ci->ownernum); @@ -1801,8 +1380,7 @@ namespace server sendstring(ci->name, p); sendstring(ci->team, p); } - else - { + else { putint(p, N_INITCLIENT); putint(p, ci->clientnum); sendstring(ci->name, p); @@ -1810,57 +1388,43 @@ namespace server putint(p, ci->playermodel); } } - - void welcomeinitclient(packetbuf &p, int exclude = -1) - { - loopv(clients) - { + void welcomeinitclient(packetbuf &p, int exclude = -1) { + loopv(clients) { clientinfo *ci = clients[i]; if(!ci->connected || ci->clientnum == exclude) continue; - putinitclient(ci, p); } } - - bool hasmap(clientinfo *ci) - { + bool hasmap(clientinfo *ci) { return (m_edit && (clients.length() > 0 || ci->local)) || (smapname[0] && (!m_timed || gamemillis < gamelimit || (ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || numclients(ci->clientnum, true, true, true))); } - - int welcomepacket(packetbuf &p, clientinfo *ci) - { + int welcomepacket(packetbuf &p, clientinfo *ci) { putint(p, N_WELCOME); putint(p, N_MAPCHANGE); sendstring(smapname, p); putint(p, gamemode); putint(p, notgotitems ? 1 : 0); - if(!ci || (m_timed && smapname[0])) - { + if(!ci || (m_timed && smapname[0])) { putint(p, N_TIMEUP); putint(p, gamemillis < gamelimit && !interm ? max((gamelimit - gamemillis)/1000, 1) : 0); } - if(!notgotitems) - { + if(!notgotitems) { putint(p, N_ITEMLIST); - loopv(sents) if(sents[i].spawned) - { + loopv(sents) if(sents[i].spawned) { putint(p, i); putint(p, sents[i].type); } putint(p, -1); } bool hasmaster = false; - if(mastermode != MM_OPEN) - { + if(mastermode != MM_OPEN) { putint(p, N_CURRENTMASTER); putint(p, mastermode); hasmaster = true; } - loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) - { - if(!hasmaster) - { + loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) { + if(!hasmaster) { putint(p, N_CURRENTMASTER); putint(p, mastermode); hasmaster = true; @@ -1869,35 +1433,30 @@ namespace server putint(p, clients[i]->privilege); } if(hasmaster) putint(p, -1); - if(gamepaused) - { + if(gamepaused) { putint(p, N_PAUSEGAME); putint(p, 1); putint(p, -1); } - if(gamespeed != 100) - { + if(gamespeed != 100) { putint(p, N_GAMESPEED); putint(p, gamespeed); putint(p, -1); } - if(m_teammode) - { + if(m_teammode) { putint(p, N_TEAMINFO); enumerate(teaminfos, teaminfo, t, if(t.frags) { sendstring(t.team, p); putint(p, t.frags); } ); sendstring("", p); } - if(ci) - { + if(ci) { putint(p, N_SETTEAM); putint(p, ci->clientnum); sendstring(ci->team, p); putint(p, -1); } - if(ci && (m_demo || m_mp(gamemode)) && ci->state.state!=CS_SPECTATOR) - { + if(ci && (m_demo || m_mp(gamemode)) && ci->state.state!=CS_SPECTATOR) { gamestate &gs = ci->state; spawnstate(ci); putint(p, N_SPAWNSTATE); @@ -1905,18 +1464,15 @@ namespace server sendstate(gs, p); gs.lastspawn = gamemillis; } - if(ci && ci->state.state==CS_SPECTATOR) - { + if(ci && ci->state.state==CS_SPECTATOR) { putint(p, N_SPECTATOR); putint(p, ci->clientnum); putint(p, 1); sendf(-1, 1, "ri3x", N_SPECTATOR, ci->clientnum, 1, ci->clientnum); } - if(!ci || clients.length()>1) - { + if(!ci || clients.length()>1) { putint(p, N_RESUME); - loopv(clients) - { + loopv(clients) { clientinfo *oi = clients[i]; if(ci && oi->clientnum==ci->clientnum) continue; putint(p, oi->clientnum); @@ -1932,21 +1488,16 @@ namespace server } return 1; } - - bool restorescore(clientinfo *ci) - { + bool restorescore(clientinfo *ci) { //if(ci->local) return false; savedscore *sc = findscore(ci, false); - if(sc) - { + if(sc) { sc->restore(ci->state); return true; } return false; } - - void sendresume(clientinfo *ci) - { + void sendresume(clientinfo *ci) { gamestate &gs = ci->state; sendf(-1, 1, "ri3i5i6vi", N_RESUME, ci->clientnum, gs.state, gs.frags, gs.flags, gs.deaths, gs.quadmillis, @@ -1955,22 +1506,17 @@ namespace server gs.armour, gs.maxarmour, gs.armourtype, gs.gunselect, GUN_PISTOL-GUN_SG+1, &gs.ammo[GUN_SG], -1); } - - void sendinitclient(clientinfo *ci) - { + void sendinitclient(clientinfo *ci) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putinitclient(ci, p); sendpacket(-1, 1, p.finalize(), ci->clientnum); } - - void loaditems() - { + void loaditems() { resetitems(); notgotitems = true; if(m_edit || !loadents(smapname, ments, &mcrc)) return; - loopv(ments) if(canspawnitem(ments[i].type)) - { + loopv(ments) if(canspawnitem(ments[i].type)) { server_entity se = { NOTUSED, 0, false }; while(sents.length()<=i) sents.add(se); sents[i].type = ments[i].type; @@ -1979,14 +1525,11 @@ namespace server } notgotitems = false; } - - void changemap(const char *s, int mode) - { + void changemap(const char *s, int mode) { stopdemo(); pausegame(false); changegamespeed(100); aiman::clearai(); - gamemode = mode; gamemillis = 0; gamelimit = 10*60000; @@ -1997,50 +1540,36 @@ namespace server scores.shrink(0); shouldcheckteamkills = false; teamkills.shrink(0); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; } - if(!m_mp(gamemode)) kicknonlocalclients(DISC_LOCAL); - sendf(-1, 1, "risii", N_MAPCHANGE, smapname, gamemode, 1); - clearteaminfo(); if(m_teammode) autoteam(); - if(m_timed && smapname[0]) sendf(-1, 1, "ri2", N_TIMEUP, gamemillis < gamelimit && !interm ? max((gamelimit - gamemillis)/1000, 1) : 0); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; ci->mapchange(); ci->state.lasttimeplayed = lastmillis; if(m_mp(gamemode) && ci->state.state!=CS_SPECTATOR) sendspawn(ci); } - aiman::changemap(); - - if(m_demo) - { + if(m_demo) { if(clients.length()) setupdemoplayback(); } - else - { + else { if(demonextmatch) setupdemorecord(); demonextmatch = autorecorddemo!=0; } } - - void rotatemap(bool next) - { - if(!maprotations.inrange(curmaprotation)) - { + void rotatemap(bool next) { + if(!maprotations.inrange(curmaprotation)) { changemap("", 1); return; } - if(next) - { + if(next) { curmaprotation = findmaprotation(gamemode, smapname); if(curmaprotation >= 0) nextmaprotation(); else curmaprotation = smapname[0] ? max(findmaprotation(gamemode, ""), 0) : 0; @@ -2048,29 +1577,23 @@ namespace server maprotation &rot = maprotations[curmaprotation]; changemap(rot.map, rot.findmode(gamemode)); } - - struct votecount - { + struct votecount { char *map; int mode, count; votecount() {} votecount(char *s, int n) : map(s), mode(n), count(0) {} }; - - void checkvotes(bool force = false) - { + void checkvotes(bool force = false) { vector votes; int maxvotes = 0; - loopv(clients) - { + loopv(clients) { clientinfo *oi = clients[i]; if(oi->state.state==CS_SPECTATOR && !oi->privilege && !oi->local) continue; if(oi->state.aitype!=AI_NONE) continue; maxvotes++; if(!m_valid(oi->modevote)) continue; votecount *vc = NULL; - loopvj(votes) if(!strcmp(oi->mapvote, votes[j].map) && oi->modevote==votes[j].mode) - { + loopvj(votes) if(!strcmp(oi->mapvote, votes[j].map) && oi->modevote==votes[j].mode) { vc = &votes[j]; break; } @@ -2079,24 +1602,19 @@ namespace server } votecount *best = NULL; loopv(votes) if(!best || votes[i].count > best->count || (votes[i].count == best->count && rnd(2))) best = &votes[i]; - if(force || (best && best->count > maxvotes/2)) - { + if(force || (best && best->count > maxvotes/2)) { sendpackets(true); if(demorecord) enddemorecord(); - if(best && (best->count > (force ? 1 : maxvotes/2))) - { + if(best && (best->count > (force ? 1 : maxvotes/2))) { sendservmsg(force ? "vote passed by default" : "vote passed by majority"); changemap(best->map, best->mode); } else rotatemap(true); } } - - void forcemap(const char *map, int mode) - { + void forcemap(const char *map, int mode) { stopdemo(); - if(!map[0] && !m_check(mode, M_EDIT)) - { + if(!map[0] && !m_check(mode, M_EDIT)) { int idx = findmaprotation(mode, smapname); if(idx < 0 && smapname[0]) idx = findmaprotation(mode, ""); if(idx < 0) return; @@ -2105,54 +1623,43 @@ namespace server if(hasnonlocalclients()) sendservmsgf("local player forced %s on map %s", modename(mode), map[0] ? map : "[new map]"); changemap(map, mode); } - - void vote(const char *map, int reqmode, int sender) - { + void vote(const char *map, int reqmode, int sender) { clientinfo *ci = getinfo(sender); if(!ci || (ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || (!ci->local && !m_mp(reqmode))) return; if(!m_valid(reqmode)) return; - if(!map[0] && !m_check(reqmode, M_EDIT)) - { + if(!map[0] && !m_check(reqmode, M_EDIT)) { int idx = findmaprotation(reqmode, smapname); if(idx < 0 && smapname[0]) idx = findmaprotation(reqmode, ""); if(idx < 0) return; map = maprotations[idx].map; } - if(lockmaprotation && !ci->local && ci->privilege < (lockmaprotation > 1 ? PRIV_ADMIN : PRIV_MASTER) && findmaprotation(reqmode, map) < 0) - { + if(lockmaprotation && !ci->local && ci->privilege < (lockmaprotation > 1 ? PRIV_ADMIN : PRIV_MASTER) && findmaprotation(reqmode, map) < 0) { sendf(sender, 1, "ris", N_SERVMSG, "This server has locked the map rotation."); return; } copystring(ci->mapvote, map); ci->modevote = reqmode; - if(ci->local || (ci->privilege && mastermode>=MM_VETO)) - { + if(ci->local || (ci->privilege && mastermode>=MM_VETO)) { sendpackets(true); if(demorecord) enddemorecord(); if(!ci->local || hasnonlocalclients()) sendservmsgf("%s forced %s on map %s", colorname(ci), modename(ci->modevote), ci->mapvote[0] ? ci->mapvote : "[new map]"); changemap(ci->mapvote, ci->modevote); } - else - { + else { sendservmsgf("%s suggests %s on map %s (select map to vote)", colorname(ci), modename(reqmode), map[0] ? map : "[new map]"); checkvotes(); } } - VAR(overtime, 0, 0, 1); - - bool checkovertime() - { + bool checkovertime() { if(!m_timed || !overtime) return false; const char* topteam = NULL; int topscore = INT_MIN; bool tied = false; - if(m_teammode) - { + if(m_teammode) { vector scores; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; int score = 0; @@ -2161,10 +1668,8 @@ namespace server else if(score == topscore && strcmp(ci->team, topteam)) tied = true; } } - else - { - loopv(clients) - { + else { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR) continue; int score = ci->state.frags; @@ -2178,39 +1683,30 @@ namespace server sendf(-1, 1, "ri2", N_TIMEUP, max((gamelimit - gamemillis)/1000, 1)); return true; } - - void checkintermission(bool force = false) - { - if(gamemillis >= gamelimit && !interm && (force || !checkovertime())) - { + void checkintermission(bool force = false) { + if(gamemillis >= gamelimit && !interm && (force || !checkovertime())) { sendf(-1, 1, "ri2", N_TIMEUP, 0); changegamespeed(100); interm = gamemillis + 10000; } } - void startintermission() { gamelimit = min(gamelimit, gamemillis); checkintermission(true); } - - void dodamage(clientinfo *target, clientinfo *actor, int damage, int gun, const vec &hitpush = vec(0, 0, 0)) - { + void dodamage(clientinfo *target, clientinfo *actor, int damage, int gun, const vec &hitpush = vec(0, 0, 0)) { gamestate &ts = target->state; ts.dodamage(damage); if(target!=actor && !isteam(target->team, actor->team)) actor->state.damage += damage; sendf(-1, 1, "ri6", N_DAMAGE, target->clientnum, actor->clientnum, damage, ts.armour, ts.health); if(target==actor) target->setpushed(); - else if(!hitpush.iszero()) - { + else if(!hitpush.iszero()) { ivec v(vec(hitpush).rescale(DNF)); sendf(ts.health<=0 ? -1 : target->ownernum, 1, "ri7", N_HITPUSH, target->clientnum, gun, damage, v.x, v.y, v.z); target->setpushed(); } - if(ts.health<=0) - { + if(ts.health<=0) { target->state.deaths++; int fragvalue = (target==actor || isteam(target->team, actor->team) ? -1 : 1); actor->state.frags += fragvalue; - if(fragvalue>0) - { + if(fragvalue>0) { int friends = 0, enemies = 0; // note: friends also includes the fragger if(m_teammode) loopv(clients) if(strcmp(clients[i]->team, actor->team)) enemies++; else friends++; else { friends = 1; enemies = clients.length()-1; } @@ -2222,8 +1718,7 @@ namespace server target->position.setsize(0); ts.state = CS_DEAD; ts.lastdeath = gamemillis; - if(actor!=target && isteam(actor->team, target->team)) - { + if(actor!=target && isteam(actor->team, target->team)) { actor->state.teamkills++; addteamkill(actor, target, 1); } @@ -2232,9 +1727,7 @@ namespace server // ts.respawn(); } } - - void suicide(clientinfo *ci) - { + void suicide(clientinfo *ci) { gamestate &gs = ci->state; if(gs.state!=CS_ALIVE) return; int fragvalue = -1; @@ -2248,39 +1741,29 @@ namespace server gs.lastdeath = gamemillis; gs.respawn(); } - - void suicideevent::process(clientinfo *ci) - { + void suicideevent::process(clientinfo *ci) { suicide(ci); } - - void explodeevent::process(clientinfo *ci) - { + void explodeevent::process(clientinfo *ci) { gamestate &gs = ci->state; - switch(gun) - { + switch(gun) { case GUN_RL: if(!gs.rockets.remove(id)) return; break; - case GUN_GL: if(!gs.grenades.remove(id)) return; break; - default: return; } sendf(-1, 1, "ri4x", N_EXPLODEFX, ci->clientnum, gun, id, ci->ownernum); - loopv(hits) - { + loopv(hits) { hitinfo &h = hits[i]; clientinfo *target = getinfo(h.target); if(!target || target->state.state!=CS_ALIVE || h.lifesequence!=target->state.lifesequence || h.dist<0 || h.dist>guns[gun].exprad) continue; - bool dup = false; loopj(i) if(hits[j].target==h.target) { dup = true; break; } if(dup) continue; - int damage = guns[gun].damage; if(gs.quadmillis) damage *= 4; damage = int(damage*(1-h.dist/EXP_DISTSCALE/guns[gun].exprad)); @@ -2288,9 +1771,7 @@ namespace server dodamage(target, ci, damage, gun, h.dir); } } - - void shotevent::process(clientinfo *ci) - { + void shotevent::process(clientinfo *ci) { gamestate &gs = ci->state; int wait = millis - gs.lastshot; if(!gs.isalive(gamemillis) || @@ -2306,19 +1787,15 @@ namespace server int(to.x*DMF), int(to.y*DMF), int(to.z*DMF), ci->ownernum); gs.shotdamage += guns[gun].damage*(gs.quadmillis ? 4 : 1)*guns[gun].rays; - switch(gun) - { + switch(gun) { case GUN_RL: gs.rockets.add(id); break; case GUN_GL: gs.grenades.add(id); break; - default: - { + default: { int totalrays = 0, maxrays = guns[gun].rays; - loopv(hits) - { + loopv(hits) { hitinfo &h = hits[i]; clientinfo *target = getinfo(h.target); if(!target || target->state.state!=CS_ALIVE || h.lifesequence!=target->state.lifesequence || h.rays<1 || h.dist > guns[gun].range + 1) continue; - totalrays += h.rays; if(totalrays>maxrays) continue; int damage = h.rays*guns[gun].damage; @@ -2329,65 +1806,46 @@ namespace server } } } - - void pickupevent::process(clientinfo *ci) - { + void pickupevent::process(clientinfo *ci) { gamestate &gs = ci->state; if(m_mp(gamemode) && !gs.isalive(gamemillis)) return; pickup(ent, ci->clientnum); } - - bool gameevent::flush(clientinfo *ci, int fmillis) - { + bool gameevent::flush(clientinfo *ci, int fmillis) { + (void) fmillis; process(ci); return true; } - - bool timedevent::flush(clientinfo *ci, int fmillis) - { + bool timedevent::flush(clientinfo *ci, int fmillis) { if(millis > fmillis) return false; - else if(millis >= ci->lastevent) - { + else if(millis >= ci->lastevent) { ci->lastevent = millis; process(ci); } return true; } - - void clearevent(clientinfo *ci) - { + void clearevent(clientinfo *ci) { delete ci->events.remove(0); } - - void flushevents(clientinfo *ci, int millis) - { - while(ci->events.length()) - { + void flushevents(clientinfo *ci, int millis) { + while(ci->events.length()) { gameevent *ev = ci->events[0]; if(ev->flush(ci, millis)) clearevent(ci); else break; } } - - void processevents() - { - loopv(clients) - { + void processevents() { + loopv(clients) { clientinfo *ci = clients[i]; if(curtime>0 && ci->state.quadmillis) ci->state.quadmillis = max(ci->state.quadmillis-curtime, 0); flushevents(ci, gamemillis); } } - - void cleartimedevents(clientinfo *ci) - { + void cleartimedevents(clientinfo *ci) { int keep = 0; - loopv(ci->events) - { - if(ci->events[i]->keepable()) - { - if(keep < i) - { + loopv(ci->events) { + if(ci->events[i]->keepable()) { + if(keep < i) { for(int j = keep; j < i; j++) delete ci->events[j]; ci->events.remove(keep, i - keep); i = keep; @@ -2399,31 +1857,22 @@ namespace server while(ci->events.length() > keep) delete ci->events.pop(); ci->timesync = false; } - - void serverupdate() - { - if(shouldstep && !gamepaused) - { + void serverupdate() { + if(shouldstep && !gamepaused) { gamemillis += curtime; - if(m_demo) readdemo(); - else if(!m_timed || gamemillis < gamelimit) - { + else if(!m_timed || gamemillis < gamelimit) { processevents(); - if(curtime) - { - loopv(sents) if(sents[i].spawntime) // spawn entities when timer reached - { + if(curtime) { + loopv(sents) if(sents[i].spawntime) { // spawn entities when timer reached { int oldtime = sents[i].spawntime; sents[i].spawntime -= curtime; - if(sents[i].spawntime<=0) - { + if(sents[i].spawntime<=0) { sents[i].spawntime = 0; sents[i].spawned = true; sendf(-1, 1, "ri2", N_ITEMSPAWN, i); } - else if(sents[i].spawntime<=10000 && oldtime>10000 && (sents[i].type==I_QUAD || sents[i].type==I_BOOST)) - { + else if(sents[i].spawntime<=10000 && oldtime>10000 && (sents[i].type==I_QUAD || sents[i].type==I_BOOST)) { sendf(-1, 1, "ri2", N_ANNOUNCE, sents[i].type); } } @@ -2431,77 +1880,56 @@ namespace server aiman::checkai(); } } - while(bannedips.length() && bannedips[0].expire-totalmillis <= 0) bannedips.remove(0); //~loopv(connects) if(totalmillis-connects[i]->connectmillis>15000) disconnect_client(connects[i]->clientnum, DISC_TIMEOUT); - - if(nextexceeded && gamemillis > nextexceeded && (!m_timed || gamemillis < gamelimit)) - { + if(nextexceeded && gamemillis > nextexceeded && (!m_timed || gamemillis < gamelimit)) { nextexceeded = 0; - loopvrev(clients) - { + loopvrev(clients) { clientinfo &c = *clients[i]; if(c.state.aitype != AI_NONE) continue; //~if(c.checkexceeded()) disconnect_client(c.clientnum, DISC_MSGERR); else c.scheduleexceeded(); } } - if(shouldcheckteamkills) checkteamkills(); - - if(shouldstep && !gamepaused) - { + if(shouldstep && !gamepaused) { if(m_timed && smapname[0] && gamemillis-curtime>0) checkintermission(); - if(interm > 0 && gamemillis>interm) - { + if(interm > 0 && gamemillis>interm) { if(demorecord) enddemorecord(); interm = -1; checkvotes(true); } } - shouldstep = clients.length() > 0; } - - void forcespectator(clientinfo *ci) - { + void forcespectator(clientinfo *ci) { if(ci->state.state==CS_ALIVE) suicide(ci); ci->state.state = CS_SPECTATOR; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; if(!ci->local && (!ci->privilege || ci->warned)) aiman::removeai(ci); sendf(-1, 1, "ri3", N_SPECTATOR, ci->clientnum, 1); } - - struct crcinfo - { + struct crcinfo { int crc, matches; - crcinfo() {} 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) - { + void checkmaps(int req = -1) { if(m_edit || !smapname[0]) return; vector crcs; int total = 0, unsent = 0, invalid = 0; if(mcrc) crcs.add(crcinfo(mcrc, clients.length() + 1)); - loopv(clients) - { + 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->clientmap[0]) { if(ci->mapcrc < 0) invalid++; else if(!ci->mapcrc) unsent++; } - else - { + else { crcinfo *match = NULL; loopvj(crcs) if(crcs[j].crc == ci->mapcrc) { match = &crcs[j]; break; } if(!match) crcs.add(crcinfo(ci->mapcrc, 1)); @@ -2511,19 +1939,16 @@ namespace server if(!mcrc && total - unsent < min(total, 4)) return; crcs.sort(crcinfo::compare); string msg; - loopv(clients) - { + 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) - { + if(crcs.length() >= 2) loopv(crcs) { crcinfo &info = crcs[i]; - if(i || info.matches <= crcs[i+1].matches) loopvj(clients) - { + 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); @@ -2531,20 +1956,15 @@ namespace server if(req < 0) ci->warned = true; } } - if(req < 0 && modifiedmapspectator && (mcrc || modifiedmapspectator > 1)) loopv(clients) - { + 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) - { + bool shouldspectate(clientinfo *ci) { return !ci->local && ci->warned && modifiedmapspectator && (mcrc || modifiedmapspectator > 1); } - - void unspectate(clientinfo *ci) - { + void unspectate(clientinfo *ci) { if(shouldspectate(ci)) return; ci->state.state = CS_DEAD; ci->state.respawn(); @@ -2554,55 +1974,40 @@ namespace server if(ci->clientmap[0] || ci->mapcrc) checkmaps(); if(!hasmap(ci)) rotatemap(true); } - - void sendservinfo(clientinfo *ci) - { + void sendservinfo(clientinfo *ci) { sendf(ci->clientnum, 1, "ri5ss", N_SERVINFO, ci->clientnum, PROTOCOL_VERSION, ci->sessionid, serverpass[0] ? 1 : 0, serverdesc, serverauth); } - - void noclients() - { + void noclients() { bannedips.shrink(0); aiman::clearai(); } - - void localconnect(int n) - { + void localconnect(int n) { clientinfo *ci = getinfo(n); ci->clientnum = ci->ownernum = n; ci->connectmillis = totalmillis; ci->sessionid = (rnd(0x1000000)*((totalmillis%10000)+1))&0xFFFFFF; ci->local = true; - connects.add(ci); sendservinfo(ci); } - - void localdisconnect(int n) - { + void localdisconnect(int n) { if(m_demo) enddemoplayback(); clientdisconnect(n); } - - int clientconnect(int n) - { + int clientconnect(int n) { clientinfo *ci = getinfo(n); ci->clientnum = ci->ownernum = n; ci->connectmillis = totalmillis; ci->sessionid = (rnd(0x1000000)*((totalmillis%10000)+1))&0xFFFFFF; - connects.add(ci); if(!m_mp(gamemode)) return DISC_LOCAL; sendservinfo(ci); return DISC_NONE; } - - void clientdisconnect(int n) - { + void clientdisconnect(int n) { clientinfo *ci = getinfo(n); loopv(clients) if(clients[i]->authkickvictim == ci->clientnum) clients[i]->cleanauth(); - if(ci->connected) - { + if(ci->connected) { if(ci->privilege) setmaster(ci, false); ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; savescore(ci); @@ -2614,58 +2019,39 @@ namespace server } else connects.removeobj(ci); } - int reserveclients() { return 3; } - extern void verifybans(); - - struct banlist - { + struct banlist { vector bans; - void clear() { bans.shrink(0); } - - bool check(uint ip) - { + bool check(uint ip) { loopv(bans) if(bans[i].check(ip)) return true; return false; } - - void add(const char *ipname) - { + void add(const char *ipname) { ipmask ban; ban.parse(ipname); bans.add(ban); - verifybans(); } } ipbans, gbans; - - bool checkbans(uint ip) - { + bool checkbans(uint ip) { loopv(bannedips) if(bannedips[i].ip==ip) return true; return ipbans.check(ip) || gbans.check(ip); } - - void verifybans() - { - loopvrev(clients) - { + void verifybans() { + loopvrev(clients) { clientinfo *ci = clients[i]; if(ci->state.aitype != AI_NONE || ci->local || ci->privilege >= PRIV_ADMIN) continue; //~if(checkbans(getclientip(ci->clientnum))) disconnect_client(ci->clientnum, DISC_IPBAN); } } - ICOMMAND(clearipbans, "", (), ipbans.clear()); ICOMMAND(ipban, "s", (const char *ipname), ipbans.add(ipname)); - - int allowconnect(clientinfo *ci, const char *pwd = "") - { + int allowconnect(clientinfo *ci, const char *pwd = "") { if(ci->local) return DISC_NONE; if(!m_mp(gamemode)) return DISC_LOCAL; - if(serverpass[0]) - { + if(serverpass[0]) { if(!checkpassword(ci, serverpass, pwd)) return DISC_PASSWORD; return DISC_NONE; } @@ -2676,68 +2062,50 @@ namespace server if(mastermode>=MM_PRIVATE && allowedips.find(ip)<0) return DISC_PRIVATE; return DISC_NONE; } - - bool allowbroadcast(int n) - { + bool allowbroadcast(int n) { clientinfo *ci = getinfo(n); return ci && ci->connected; } - - clientinfo *findauth(uint id) - { + clientinfo *findauth(uint id) { loopv(clients) if(clients[i]->authreq == id) return clients[i]; return NULL; } - - void authfailed(clientinfo *ci) - { + void authfailed(clientinfo *ci) { if(!ci) return; ci->cleanauth(); //~if(ci->connectauth) disconnect_client(ci->clientnum, ci->connectauth); } - - void authfailed(uint id) - { + void authfailed(uint id) { authfailed(findauth(id)); } - - void authsucceeded(uint id) - { + void authsucceeded(uint id) { clientinfo *ci = findauth(id); if(!ci) return; ci->cleanauth(ci->connectauth!=0); if(ci->connectauth) connected(ci); - if(ci->authkickvictim >= 0) - { + if(ci->authkickvictim >= 0) { if(setmaster(ci, true, "", ci->authname, NULL, PRIV_AUTH, false, true)) trykick(ci, ci->authkickvictim, ci->authkickreason, ci->authname, NULL, PRIV_AUTH); ci->cleanauthkick(); } else setmaster(ci, true, "", ci->authname, NULL, PRIV_AUTH); } - - void authchallenged(uint id, const char *val, const char *desc = "") - { + void authchallenged(uint id, const char *val, const char *desc = "") { clientinfo *ci = findauth(id); if(!ci) return; sendf(ci->clientnum, 1, "risis", N_AUTHCHAL, desc, id, val); } - uint nextauthreq = 0; - - bool tryauth(clientinfo *ci, const char *user, const char *desc) - { + bool tryauth(clientinfo *ci, const char *user, const char *desc) { ci->cleanauth(); if(!nextauthreq) nextauthreq = 1; ci->authreq = nextauthreq++; filtertext(ci->authname, user, false, false, 100); copystring(ci->authdesc, desc); - if(ci->authdesc[0]) - { + if(ci->authdesc[0]) { userinfo *u = users.access(userkey(ci->authname, ci->authdesc)); - if(u) - { + if(u) { uint seed[3] = { ::hthash(serverauth) + detrnd(size_t(ci) + size_t(user) + size_t(desc), 0x10000), uint(totalmillis), randomMT() }; vector buf; ci->authchallenge = genchallenge(u->pubkey, seed, sizeof(seed), buf); @@ -2745,8 +2113,7 @@ namespace server } else ci->cleanauth(); } - else if(!requestmasterf("reqauth %u %s\n", ci->authreq, ci->authname)) - { + else if(!requestmasterf("reqauth %u %s\n", ci->authreq, ci->authname)) { ci->cleanauth(); sendf(ci->clientnum, 1, "ris", N_SERVMSG, "not connected to authentication server"); } @@ -2754,28 +2121,20 @@ namespace server //~if(ci->connectauth) disconnect_client(ci->clientnum, ci->connectauth); return false; } - - bool answerchallenge(clientinfo *ci, uint id, char *val, const char *desc) - { - if(ci->authreq != id || strcmp(ci->authdesc, desc)) - { + bool answerchallenge(clientinfo *ci, uint id, char *val, const char *desc) { + if(ci->authreq != id || strcmp(ci->authdesc, desc)) { ci->cleanauth(); return !ci->connectauth; } - for(char *s = val; *s; s++) - { + for(char *s = val; *s; s++) { if(!isxdigit(*s)) { *s = '\0'; break; } } - if(desc[0]) - { - if(ci->authchallenge && checkchallenge(val, ci->authchallenge)) - { + if(desc[0]) { + if(ci->authchallenge && checkchallenge(val, ci->authchallenge)) { userinfo *u = users.access(userkey(ci->authname, ci->authdesc)); - if(u) - { + if(u) { if(ci->connectauth) connected(ci); - if(ci->authkickvictim >= 0) - { + if(ci->authkickvictim >= 0) { if(setmaster(ci, true, "", ci->authname, ci->authdesc, u->privilege, false, true)) trykick(ci, ci->authkickvictim, ci->authkickreason, ci->authname, ci->authdesc, u->privilege); } @@ -2784,29 +2143,21 @@ namespace server } ci->cleanauth(); } - else if(!requestmasterf("confauth %u %s\n", id, val)) - { + else if(!requestmasterf("confauth %u %s\n", id, val)) { ci->cleanauth(); sendf(ci->clientnum, 1, "ris", N_SERVMSG, "not connected to authentication server"); } return ci->authreq || !ci->connectauth; } - - void masterconnected() - { + void masterconnected() { } - - void masterdisconnected() - { - loopvrev(clients) - { + void masterdisconnected() { + loopvrev(clients) { clientinfo *ci = clients[i]; if(ci->authreq) authfailed(ci); } } - - void processmasterinput(const char *cmd, int cmdlen, const char *args) - { + void processmasterinput(const char *cmd, int cmdlen) { uint id; string val; if(sscanf(cmd, "failauth %u", &id) == 1) @@ -2820,9 +2171,7 @@ namespace server else if(sscanf(cmd, "addgban %100s", val) == 1) gbans.add(val); } - - void receivefile(int sender, uchar *data, int len) - { + void receivefile(int sender, uchar *data, int len) { if(!m_edit || len <= 0 || len > 4*1024*1024) return; clientinfo *ci = getinfo(sender); if(ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) return; @@ -2832,82 +2181,59 @@ namespace server mapdata->write(data, len); sendservmsgf("[%s sent a map to server, \"/getmap\" to receive it]", colorname(ci)); } - - void sendclipboard(clientinfo *ci) - { + void sendclipboard(clientinfo *ci) { if(!ci->lastclipboard || !ci->clipboard) return; bool flushed = false; - loopv(clients) - { + loopv(clients) { clientinfo &e = *clients[i]; - if(e.clientnum != ci->clientnum && e.needclipboard - ci->lastclipboard >= 0) - { + if(e.clientnum != ci->clientnum && e.needclipboard - ci->lastclipboard >= 0) { if(!flushed) { flushserver(true); flushed = true; } sendpacket(e.clientnum, 1, ci->clipboard); } } } - - void connected(clientinfo *ci) - { + void connected(clientinfo *ci) { if(m_demo) enddemoplayback(); - if(!hasmap(ci)) rotatemap(false); - shouldstep = true; - connects.removeobj(ci); clients.add(ci); - ci->connectauth = 0; ci->connected = true; ci->needclipboard = totalmillis ? totalmillis : 1; if(mastermode>=MM_LOCKED) ci->state.state = CS_SPECTATOR; ci->state.lasttimeplayed = lastmillis; - - const char *worst = m_teammode ? chooseworstteam(NULL, ci) : NULL; + const char *worst = m_teammode ? chooseworstteam(ci) : NULL; copystring(ci->team, worst ? worst : "good", MAXTEAMLEN+1); - sendwelcome(ci); if(restorescore(ci)) sendresume(ci); sendinitclient(ci); - aiman::addclient(ci); - if(m_demo) setupdemoplayback(); - if(servermotd[0]) sendf(ci->clientnum, 1, "ris", N_SERVMSG, servermotd); } - - void parsepacket(int sender, int chan, packetbuf &p) // has to parse exactly each byte of the packet - { + void parsepacket(int sender, int chan, packetbuf &p) { // has to parse exactly each byte of the packet { if(sender<0 || p.packet->flags&ENET_PACKET_FLAG_UNSEQUENCED || chan > 2) return; char text[MAXTRANS]; int type; clientinfo *ci = sender>=0 ? getinfo(sender) : NULL, *cq = ci, *cm = ci; - if(ci && !ci->connected) - { + if(ci && !ci->connected) { if(chan==0) return; //~else if(chan!=1) { disconnect_client(sender, DISC_MSGERR); return; } - else while(p.length() < p.maxlen) switch(checktype(getint(p), ci)) - { - case N_CONNECT: - { + else while(p.length() < p.maxlen) switch(checktype(getint(p), ci)) { + case N_CONNECT: { getstring(text, p); filtertext(text, text, false, false, MAXNAMELEN); if(!text[0]) copystring(text, "Anonymous"); copystring(ci->name, text, MAXNAMELEN+1); ci->playermodel = 0; - string password, authdesc, authname; getstring(password, p, sizeof(password)); getstring(authdesc, p, sizeof(authdesc)); getstring(authname, p, sizeof(authname)); int disc = allowconnect(ci, password); - if(disc) - { - if(disc == DISC_LOCAL || !serverauth[0] || strcmp(serverauth, authdesc) || !tryauth(ci, authname, authdesc)) - { + if(disc) { + if(disc == DISC_LOCAL || !serverauth[0] || strcmp(serverauth, authdesc) || !tryauth(ci, authname, authdesc)) { //~disconnect_client(sender, disc); return; } @@ -2916,63 +2242,53 @@ namespace server else connected(ci); break; } - - case N_AUTHANS: - { + case N_AUTHANS: { string desc, ans; getstring(desc, p, sizeof(desc)); uint id = (uint)getint(p); getstring(ans, p, sizeof(ans)); - if(!answerchallenge(ci, id, ans, desc)) - { + if(!answerchallenge(ci, id, ans, desc)) { //~disconnect_client(sender, ci->connectauth); return; } break; } - case N_PING: getint(p); break; - default: //~disconnect_client(sender, DISC_MSGERR); return; } return; } - else if(chan==2) - { + else if(chan==2) { receivefile(sender, p.buf, p.maxlen); return; } - if(p.packet->flags&ENET_PACKET_FLAG_RELIABLE) reliablemessages = true; #define QUEUE_AI clientinfo *cm = cq; #define QUEUE_MSG { if(cm && (!cm->local || demorecord || hasnonlocalclients())) while(curmsgmessages.add(p.buf[curmsg++]); } #define QUEUE_BUF(body) { \ - if(cm && (!cm->local || demorecord || hasnonlocalclients())) \ - { \ - curmsg = p.length(); \ - { body; } \ + if(cm && (!cm->local || demorecord || hasnonlocalclients())) { \ + \ + curmsg = p.length(); { \ + body; } \ } \ } #define QUEUE_INT(n) QUEUE_BUF(putint(cm->messages, n)) #define QUEUE_UINT(n) QUEUE_BUF(putuint(cm->messages, n)) #define QUEUE_STR(text) QUEUE_BUF(sendstring(text, cm->messages)) int curmsg; - while((curmsg = p.length()) < p.maxlen) switch(type = checktype(getint(p), ci)) - { - case N_POS: - { + while((curmsg = p.length()) < p.maxlen) switch(type = checktype(getint(p), ci)) { + case N_POS: { int pcn = getuint(p); p.get(); uint flags = getuint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; vec pos; - loopk(3) - { + loopk(3) { int n = p.get(); n |= p.get()<<8; if(flags&(1<local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp) { + if((!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { if(!ci->local && !m_edit && max(vel.magnitude2(), (float)fabs(vel.z)) >= 180) cp->setexceeded(); cp->position.setsize(0); @@ -2999,53 +2312,41 @@ namespace server } break; } - - case N_TELEPORT: - { + case N_TELEPORT: { int pcn = getint(p), teleport = getint(p), teledest = getint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; - if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { flushclientposition(*cp); sendf(-1, 0, "ri4x", N_TELEPORT, pcn, teleport, teledest, cp->ownernum); } break; } - - case N_JUMPPAD: - { + case N_JUMPPAD: { int pcn = getint(p), jumppad = getint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; - if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { cp->setpushed(); flushclientposition(*cp); sendf(-1, 0, "ri3x", N_JUMPPAD, pcn, jumppad, cp->ownernum); } break; } - - case N_FROMAI: - { + case N_FROMAI: { int qcn = getint(p); if(qcn < 0) cq = ci; - else - { + else { cq = getinfo(qcn); if(cq && qcn != sender && cq->ownernum != sender) cq = NULL; } break; } - - case N_EDITMODE: - { + case N_EDITMODE: { int val = getint(p); if(!ci->local && !m_edit) break; if(val ? ci->state.state!=CS_ALIVE && ci->state.state!=CS_DEAD : ci->state.state!=CS_EDITING) break; - if(val) - { + if(val) { ci->state.editstate = ci->state.state; ci->state.state = CS_EDITING; ci->events.setsize(0); @@ -3056,16 +2357,12 @@ namespace server QUEUE_MSG; break; } - - case N_MAPCRC: - { + case N_MAPCRC: { getstring(text, p); int crc = getint(p); if(!ci) break; - if(strcmp(text, smapname)) - { - if(ci->clientmap[0]) - { + if(strcmp(text, smapname)) { + if(ci->clientmap[0]) { ci->clientmap[0] = '\0'; ci->mapcrc = 0; } @@ -3078,31 +2375,25 @@ namespace server 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) - { + 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; } } - if(cq->state.deadflush) - { + if(cq->state.deadflush) { flushevents(cq, cq->state.deadflush); cq->state.respawn(); } cleartimedevents(cq); sendspawn(cq); break; - - case N_GUNSELECT: - { + case N_GUNSELECT: { int gunselect = getint(p); if(!cq || cq->state.state!=CS_ALIVE) break; cq->state.gunselect = gunselect >= GUN_FIST && gunselect <= GUN_PISTOL ? gunselect : GUN_FIST; @@ -3110,9 +2401,7 @@ namespace server QUEUE_MSG; break; } - - case N_SPAWN: - { + case N_SPAWN: { int ls = getint(p), gunselect = getint(p); if(!cq || (cq->state.state!=CS_ALIVE && cq->state.state!=CS_DEAD && cq->state.state!=CS_EDITING) || ls!=cq->state.lifesequence || cq->state.lastspawn<0) break; cq->state.lastspawn = -1; @@ -3126,15 +2415,11 @@ namespace server }); break; } - - case N_SUICIDE: - { + case N_SUICIDE: { if(cq) cq->addevent(new suicideevent); break; } - - case N_SHOOT: - { + case N_SHOOT: { shotevent *shot = new shotevent; shot->id = getint(p); shot->millis = cq ? cq->geteventmillis(gamemillis, shot->id) : 0; @@ -3142,8 +2427,7 @@ namespace server loopk(3) shot->from[k] = getint(p)/DMF; loopk(3) shot->to[k] = getint(p)/DMF; int hits = getint(p); - loopk(hits) - { + loopk(hits) { if(p.overread()) break; hitinfo &hit = shot->hits.add(); hit.target = getint(p); @@ -3152,25 +2436,21 @@ namespace server hit.rays = getint(p); loopk(3) hit.dir[k] = getint(p)/DNF; } - if(cq) - { + if(cq) { cq->addevent(shot); cq->setpushed(); } else delete shot; break; } - - case N_EXPLODE: - { + case N_EXPLODE: { explodeevent *exp = new explodeevent; int cmillis = getint(p); exp->millis = cq ? cq->geteventmillis(gamemillis, cmillis) : 0; exp->gun = getint(p); exp->id = getint(p); int hits = getint(p); - loopk(hits) - { + loopk(hits) { if(p.overread()) break; hitinfo &hit = exp->hits.add(); hit.target = getint(p); @@ -3183,9 +2463,7 @@ namespace server else delete exp; break; } - - case N_ITEMPICKUP: - { + case N_ITEMPICKUP: { int n = getint(p); if(!cq) break; pickupevent *pickup = new pickupevent; @@ -3193,9 +2471,7 @@ namespace server cq->addevent(pickup); break; } - - case N_TEXT: - { + case N_TEXT: { QUEUE_AI; QUEUE_MSG; getstring(text, p); @@ -3204,14 +2480,11 @@ namespace server if(isdedicatedserver() && cq) logoutf("%s: %s", colorname(cq), text); break; } - - case N_SAYTEAM: - { + case N_SAYTEAM: { getstring(text, p); if(!ci || !cq || (ci->state.state==CS_SPECTATOR && !ci->local && !ci->privilege) || !m_teammode || !cq->team[0]) break; filtertext(text, text, true, true); - loopv(clients) - { + loopv(clients) { clientinfo *t = clients[i]; if(t==cq || t->state.state==CS_SPECTATOR || t->state.aitype != AI_NONE || strcmp(cq->team, t->team)) continue; sendf(t->clientnum, 1, "riis", N_SAYTEAM, cq->clientnum, text); @@ -3219,9 +2492,7 @@ namespace server if(isdedicatedserver() && cq) logoutf("%s <%s>: %s", colorname(cq), cq->team, text); break; } - - case N_SWITCHNAME: - { + case N_SWITCHNAME: { QUEUE_MSG; getstring(text, p); filtertext(ci->name, text, false, false, MAXNAMELEN); @@ -3229,20 +2500,15 @@ namespace server QUEUE_STR(ci->name); break; } - - case N_SWITCHMODEL: - { + case N_SWITCHMODEL: { ci->playermodel = 0; QUEUE_MSG; break; } - - case N_SWITCHTEAM: - { + case N_SWITCHTEAM: { getstring(text, p); filtertext(text, text, false, false, MAXTEAMLEN); - if(m_teammode && text[0] && strcmp(ci->team, text) && addteaminfo(text)) - { + if(m_teammode && text[0] && strcmp(ci->team, text) && addteaminfo(text)) { if(ci->state.state==CS_ALIVE) suicide(ci); copystring(ci->team, text); aiman::changeteam(ci); @@ -3250,9 +2516,7 @@ namespace server } break; } - - case N_MAPVOTE: - { + case N_MAPVOTE: { getstring(text, p); filtertext(text, text, false); fixmapname(text); @@ -3260,18 +2524,14 @@ namespace server vote(text, reqmode, sender); break; } - - case N_ITEMLIST: - { + case N_ITEMLIST: { if((ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || !notgotitems || strcmp(ci->clientmap, smapname)) { while(getint(p)>=0 && !p.overread()) getint(p); break; } int n; - while((n = getint(p))>=0 && n=0 && nstate.state==CS_SPECTATOR) break; QUEUE_MSG; bool canspawn = canspawnitem(type); - if(istate.state!=CS_SPECTATOR) QUEUE_MSG; break; } - case N_PING: sendf(sender, 1, "i2", N_PONG, getint(p)); break; - - case N_CLIENTPING: - { + case N_CLIENTPING: { int ping = getint(p); - if(ci) - { + if(ci) { ci->ping = ping; loopv(ci->bots) ci->bots[i]->ping = ping; } QUEUE_MSG; break; } - - case N_MASTERMODE: - { + case N_MASTERMODE: { int mm = getint(p); - if((ci->privilege || ci->local) && mm>=MM_OPEN && mm<=MM_PRIVATE) - { - if((ci->privilege>=PRIV_ADMIN || ci->local) || (mastermask&(1<privilege || ci->local) && mm>=MM_OPEN && mm<=MM_PRIVATE) { + if((ci->privilege>=PRIV_ADMIN || ci->local) || (mastermask&(1<=MM_PRIVATE) - { + if(mm>=MM_PRIVATE) { loopv(clients) allowedips.add(getclientip(clients[i]->clientnum)); } sendf(-1, 1, "rii", N_MASTERMODE, mastermode); //sendservmsgf("mastermode is now %s (%d)", mastermodename(mastermode), mastermode); } - else - { + else { defformatstring(s, "mastermode %d is disabled on this server", mm); sendf(sender, 1, "ris", N_SERVMSG, s); } } break; } - - case N_CLEARBANS: - { - if(ci->privilege || ci->local) - { + case N_CLEARBANS: { + if(ci->privilege || ci->local) { bannedips.shrink(0); sendservmsg("cleared all bans"); } break; } - - case N_KICK: - { + case N_KICK: { int victim = getint(p); getstring(text, p); filtertext(text, text); trykick(ci, victim, text); break; } - - case N_SPECTATOR: - { + case N_SPECTATOR: { int spectator = getint(p), val = getint(p); if(!ci->privilege && !ci->local && (spectator!=sender || (ci->state.state==CS_SPECTATOR && mastermode>=MM_LOCKED))) break; clientinfo *spinfo = (clientinfo *)getclientinfo(spectator); // no bots if(!spinfo || !spinfo->connected || (spinfo->state.state==CS_SPECTATOR ? val : !val)) break; - if(spinfo->state.state!=CS_SPECTATOR && val) forcespectator(spinfo); else if(spinfo->state.state==CS_SPECTATOR && !val) unspectate(spinfo); - if(cq && cq != ci && cq->ownernum != ci->clientnum) cq = NULL; break; } - - case N_SETTEAM: - { + case N_SETTEAM: { int who = getint(p); getstring(text, p); filtertext(text, text, false, false, MAXTEAMLEN); if(!ci->privilege && !ci->local) break; clientinfo *wi = getinfo(who); if(!m_teammode || !text[0] || !wi || !wi->connected || !strcmp(wi->team, text)) break; - if(addteaminfo(text)) - { + if(addteaminfo(text)) { if(wi->state.state==CS_ALIVE) suicide(wi); copystring(wi->team, text, MAXTEAMLEN+1); } @@ -3408,17 +2639,13 @@ namespace server sendf(-1, 1, "riisi", N_SETTEAM, who, wi->team, 1); break; } - case N_FORCEINTERMISSION: if(ci->local && !hasnonlocalclients()) startintermission(); break; - - case N_RECORDDEMO: - { + case N_RECORDDEMO: { int val = getint(p); if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; - if(!maxdemos || !maxdemosize) - { + if(!maxdemos || !maxdemosize) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "the server has disabled demo recording"); break; } @@ -3426,53 +2653,41 @@ namespace server sendservmsgf("demo recording is %s for next match", demonextmatch ? "enabled" : "disabled"); break; } - - case N_STOPDEMO: - { + case N_STOPDEMO: { if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; stopdemo(); break; } - - case N_CLEARDEMOS: - { + case N_CLEARDEMOS: { int demo = getint(p); if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; cleardemos(demo); break; } - case N_LISTDEMOS: if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; listdemos(sender); break; - - case N_GETDEMO: - { + case N_GETDEMO: { int n = getint(p), tag = getint(p); if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; senddemo(ci, n, tag); break; } - case N_GETMAP: if(!mapdata) sendf(sender, 1, "ris", N_SERVMSG, "no map to send"); else if(ci->getmap) sendf(sender, 1, "ris", N_SERVMSG, "already sending map"); - else - { + else { sendservmsgf("[%s is getting the map]", colorname(ci)); if((ci->getmap = sendfile(sender, 2, mapdata, "ri", N_SENDMAP))) ci->getmap->freeCallback = freegetmap; ci->needclipboard = totalmillis ? totalmillis : 1; } break; - - case N_NEWMAP: - { + case N_NEWMAP: { int size = getint(p); if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; - if(size>=0) - { + if(size>=0) { smapname[0] = '\0'; resetitems(); notgotitems = false; @@ -3480,13 +2695,10 @@ namespace server QUEUE_MSG; break; } - - case N_SETMASTER: - { + case N_SETMASTER: { int mn = getint(p), val = getint(p); getstring(text, p); - if(mn != ci->clientnum) - { + if(mn != ci->clientnum) { if(!ci->privilege && !ci->local) break; clientinfo *minfo = (clientinfo *)getclientinfo(mn); if(!minfo || !minfo->connected || (!ci->local && minfo->privilege >= ci->privilege) || (val && minfo->privilege)) break; @@ -3496,44 +2708,32 @@ namespace server // don't broadcast the master password break; } - - case N_ADDBOT: - { + case N_ADDBOT: { aiman::reqadd(ci, getint(p)); break; } - - case N_DELBOT: - { + case N_DELBOT: { aiman::reqdel(ci); break; } - - case N_BOTLIMIT: - { + case N_BOTLIMIT: { int limit = getint(p); if(ci) aiman::setbotlimit(ci, limit); break; } - - case N_BOTBALANCE: - { + case N_BOTBALANCE: { int balance = getint(p); if(ci) aiman::setbotbalance(ci, balance!=0); break; } - - case N_AUTHTRY: - { + case N_AUTHTRY: { string desc, name; getstring(desc, p, sizeof(desc)); getstring(name, p, sizeof(name)); tryauth(ci, name, desc); break; } - - case N_AUTHKICK: - { + case N_AUTHKICK: { string desc, name; getstring(desc, p, sizeof(desc)); getstring(name, p, sizeof(name)); @@ -3541,22 +2741,18 @@ namespace server getstring(text, p); filtertext(text, text); int authpriv = PRIV_AUTH; - if(desc[0]) - { + if(desc[0]) { userinfo *u = users.access(userkey(name, desc)); if(u) authpriv = u->privilege; else break; } if(ci->local || ci->privilege >= authpriv) trykick(ci, victim, text); - else if(trykick(ci, victim, text, name, desc, authpriv, true) && tryauth(ci, name, desc)) - { + else if(trykick(ci, victim, text, name, desc, authpriv, true) && tryauth(ci, name, desc)) { ci->authkickvictim = victim; ci->authkickreason = newstring(text); } break; } - - case N_AUTHANS: - { + case N_AUTHANS: { string desc, ans; getstring(desc, p, sizeof(desc)); uint id = (uint)getint(p); @@ -3564,43 +2760,33 @@ namespace server answerchallenge(ci, id, ans, desc); break; } - - case N_PAUSEGAME: - { + case N_PAUSEGAME: { int val = getint(p); if(ci->privilege < (restrictpausegame ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; pausegame(val > 0, ci); break; } - - case N_GAMESPEED: - { + case N_GAMESPEED: { int val = getint(p); if(ci->privilege < (restrictgamespeed ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; changegamespeed(val, ci); break; } - case N_COPY: ci->cleanclipboard(); ci->lastclipboard = totalmillis ? totalmillis : 1; goto genericmsg; - case N_PASTE: if(ci->state.state!=CS_SPECTATOR) sendclipboard(ci); goto genericmsg; - - case N_CLIPBOARD: - { + case N_CLIPBOARD: { int unpacklen = getint(p), packlen = getint(p); ci->cleanclipboard(false); - if(ci->state.state==CS_SPECTATOR) - { + if(ci->state.state==CS_SPECTATOR) { if(packlen > 0) p.subbuf(packlen); break; } - if(packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) - { + if(packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) { if(packlen > 0) p.subbuf(packlen); packlen = unpacklen = 0; } @@ -3614,11 +2800,9 @@ namespace server ci->clipboard->referenceCount++; break; } - case N_EDITT: case N_REPLACE: - case N_EDITVSLOT: - { + case N_EDITVSLOT: { int size = server::msgsizelookup(type); //~if(size<=0) { disconnect_client(sender, DISC_MSGERR); return; } loopi(size-1) getint(p); @@ -3629,13 +2813,10 @@ namespace server if(ci && ci->state.state!=CS_SPECTATOR) QUEUE_MSG; break; } - case N_UNDO: - case N_REDO: - { + case N_REDO: { int unpacklen = getint(p), packlen = getint(p); - if(!ci || ci->state.state==CS_SPECTATOR || packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) - { + if(!ci || ci->state.state==CS_SPECTATOR || packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) { if(packlen > 0) p.subbuf(packlen); break; } @@ -3649,27 +2830,21 @@ namespace server sendpacket(-1, 1, q.finalize(), ci->clientnum); break; } - case N_SERVCMD: getstring(text, p); break; - case -1: //~disconnect_client(sender, DISC_MSGERR); return; - case -2: //~disconnect_client(sender, DISC_OVERFLOW); return; - - default: genericmsg: - { + default: genericmsg: { int size = server::msgsizelookup(type); //~if(size<=0) { disconnect_client(sender, DISC_MSGERR); return; } loopi(size-1) getint(p); - if(ci) switch(msgfilter[type]) - { + if(ci) switch(msgfilter[type]) { case 2: case 3: if(ci->state.state != CS_SPECTATOR) QUEUE_MSG; break; default: if(cq && (ci != cq || ci->state.state!=CS_SPECTATOR)) { QUEUE_AI; QUEUE_MSG; } break; } @@ -3677,24 +2852,18 @@ namespace server } } } - int laninfoport() { return SAUERBRATEN_LANINFO_PORT; } int serverinfoport(int servport) { return servport < 0 ? SAUERBRATEN_SERVINFO_PORT : servport+1; } int serverport(int infoport) { return infoport < 0 ? SAUERBRATEN_SERVER_PORT : infoport-1; } const char *defaultmaster() { return "master.sauerbraten.org"; } int masterport() { return SAUERBRATEN_MASTER_PORT; } int numchannels() { return 3; } - #include "extinfo.h" - - void serverinforeply(ucharbuf &req, ucharbuf &p) - { - if(req.remaining() && !getint(req)) - { + void serverinforeply(ucharbuf &req, ucharbuf &p) { + if(req.remaining() && !getint(req)) { extserverinforeply(req, p); return; } - putint(p, numclients(-1, false, true)); putint(p, gamepaused || gamespeed != 100 ? 7 : 5); // number of attrs following putint(p, PROTOCOL_VERSION); // generic attributes, passed back below @@ -3702,8 +2871,7 @@ namespace server putint(p, m_timed ? max((gamelimit - gamemillis)/1000, 0) : 0); putint(p, maxclients); putint(p, serverpass[0] ? MM_PASSWORD : (!m_mp(gamemode) ? MM_PRIVATE : (mastermode || mastermask&MM_AUTOAPPROVE ? mastermode : MM_AUTH))); - if(gamepaused || gamespeed != 100) - { + if(gamepaused || gamespeed != 100) { putint(p, gamepaused ? 1 : 0); putint(p, gamespeed); } @@ -3711,7 +2879,6 @@ namespace server sendstring(serverdesc, p); sendserverinforeply(p); } - #include "aiman.h" } diff --git a/src/fpsgame/waypoint.cpp b/src/fpsgame/waypoint.cpp index 30a1403..05afb6c 100644 --- a/src/fpsgame/waypoint.cpp +++ b/src/fpsgame/waypoint.cpp @@ -2,26 +2,19 @@ extern selinfo sel; -namespace ai -{ +namespace ai { using namespace game; - vector waypoints; - - bool clipped(const vec &o) - { + bool clipped(const vec &o) { int material = lookupmaterial(o), clipmat = material&MATF_CLIP; return clipmat == MAT_CLIP || material&MAT_DEATH; } - - int getweight(const vec &o) - { + int getweight(const vec &o) { vec pos = o; pos.z += ai::JUMPMIN; if(!insideworld(vec(pos.x, pos.y, min(pos.z, getworldsize() - 1e-3f)))) return -2; float dist = raycube(pos, vec(0, 0, -1), 0, RAY_CLIPMAT); int weight = 1; - if(dist >= 0) - { + if(dist >= 0) { weight = int(dist/ai::JUMPMIN); pos.z -= clamp(dist-8.0f, 0.0f, pos.z); int trgmat = lookupmaterial(pos); @@ -29,46 +22,33 @@ namespace ai } return weight; } - - enum - { + enum { WPCACHE_STATIC = 0, WPCACHE_DYNAMIC, NUMWPCACHES }; - - struct wpcache - { - struct node - { + struct wpcache { + struct node { float split[2]; uint child[2]; - int axis() const { return child[0]>>30; } int childindex(int which) const { return child[which]&0x3FFFFFFF; } bool isleaf(int which) const { return (child[1]&(1<<(30+which)))!=0; } }; - vector nodes; int firstwp, lastwp; vec bbmin, bbmax; - wpcache() { clear(); } - - void clear() - { + void clear() { nodes.setsize(0); firstwp = lastwp = -1; bbmin = vec(1e16f, 1e16f, 1e16f); bbmax = vec(-1e16f, -1e16f, -1e16f); } - - void build(int first = 0, int last = -1) - { + void build(int first = 0, int last = -1) { if(last < 0) last = waypoints.length(); vector indices; - for(int i = first; i < last; i++) - { + for(int i = first; i < last; i++) { waypoint &w = waypoints[i]; indices.add(i); if(firstwp < 0) firstwp = i; @@ -77,34 +57,27 @@ namespace ai bbmax.max(vec(w.o).add(radius)); } if(first < last) lastwp = max(lastwp, last-1); - if(indices.length()) - { + if(indices.length()) { nodes.reserve(indices.length()); build(indices.getbuf(), indices.length(), bbmin, bbmax); } } - - void build(int *indices, int numindices, const vec &vmin, const vec &vmax) - { + void build(int *indices, int numindices, const vec &vmin, const vec &vmax) { int axis = 2; loopk(2) if(vmax[k] - vmin[k] > vmax[axis] - vmin[axis]) axis = k; - vec leftmin(1e16f, 1e16f, 1e16f), leftmax(-1e16f, -1e16f, -1e16f), rightmin(1e16f, 1e16f, 1e16f), rightmax(-1e16f, -1e16f, -1e16f); float split = 0.5f*(vmax[axis] + vmin[axis]), splitleft = -1e16f, splitright = 1e16f; int left, right; - for(left = 0, right = numindices; left < right;) - { + for(left = 0, right = numindices; left < right;) { waypoint &w = waypoints[indices[left]]; float radius = WAYPOINTRADIUS; - if(max(split - (w.o[axis]-radius), 0.0f) > max((w.o[axis]+radius) - split, 0.0f)) - { + if(max(split - (w.o[axis]-radius), 0.0f) > max((w.o[axis]+radius) - split, 0.0f)) { ++left; splitleft = max(splitleft, w.o[axis]+radius); leftmin.min(vec(w.o).sub(radius)); leftmax.max(vec(w.o).add(radius)); } - else - { + else { --right; swap(indices[left], indices[right]); splitright = min(splitright, w.o[axis]-radius); @@ -112,111 +85,84 @@ namespace ai rightmax.max(vec(w.o).add(radius)); } } - - if(!left || right==numindices) - { + if(!left || right==numindices) { leftmin = rightmin = vec(1e16f, 1e16f, 1e16f); leftmax = rightmax = vec(-1e16f, -1e16f, -1e16f); left = right = numindices/2; splitleft = -1e16f; splitright = 1e16f; - loopi(numindices) - { + loopi(numindices) { waypoint &w = waypoints[indices[i]]; float radius = WAYPOINTRADIUS; - if(i < left) - { + if(i < left) { splitleft = max(splitleft, w.o[axis]+radius); leftmin.min(vec(w.o).sub(radius)); leftmax.max(vec(w.o).add(radius)); } - else - { + else { splitright = min(splitright, w.o[axis]-radius); rightmin.min(vec(w.o).sub(radius)); rightmax.max(vec(w.o).add(radius)); } } } - int offset = nodes.length(); node &curnode = nodes.add(); curnode.split[0] = splitleft; curnode.split[1] = splitright; - if(left<=1) curnode.child[0] = (axis<<30) | (left>0 ? indices[0] : 0x3FFFFFFF); - else - { + else { curnode.child[0] = (axis<<30) | (nodes.length()-offset); if(left) build(indices, left, leftmin, leftmax); } - if(numindices-right<=1) curnode.child[1] = (1<<31) | (left<=1 ? 1<<30 : 0) | (numindices-right>0 ? indices[right] : 0x3FFFFFFF); - else - { + else { curnode.child[1] = (left<=1 ? 1<<30 : 0) | (nodes.length()-offset); if(numindices-right) build(&indices[right], numindices-right, rightmin, rightmax); } } } wpcaches[NUMWPCACHES]; - static int invalidatedwpcaches = 0, clearedwpcaches = (1<= 1000) { numinvalidatewpcaches = 0; invalidatedwpcaches = (1<= wpcaches[i].firstwp && wp <= wpcaches[i].lastwp) { invalidatedwpcaches |= 1< 0 ? wpcaches[i-1].lastwp+1 : 1, i+1 >= NUMWPCACHES || wpcaches[i+1].firstwp < 0 ? -1 : wpcaches[i+1].firstwp); clearedwpcaches = 0; lastwpcache = waypoints.length(); - wpavoid.clear(); loopv(waypoints) if(waypoints[i].weight < 0) wpavoid.avoidnear(NULL, waypoints[i].o.z + WAYPOINTRADIUS, waypoints[i].o, WAYPOINTRADIUS); } - - struct wpcachestack - { + struct wpcachestack { wpcache::node *node; float tmin, tmax; }; - vector wpcachestack; - - int closestwaypoint(const vec &pos, float mindist, bool links, fpsent *d) - { + int closestwaypoint(const vec &pos, float mindist, bool links) { if(waypoints.empty()) return -1; if(clearedwpcaches) buildwpcache(); - #define CHECKCLOSEST(index) do { \ int n = (index); \ - if(n < waypoints.length()) \ - { \ + if(n < waypoints.length()) { \ + \ const waypoint &w = waypoints[n]; \ - if(!links || w.links[0]) \ - { \ + if(!links || w.links[0]) { \ + \ float dist = w.o.squaredist(pos); \ if(dist < mindist*mindist) { closest = n; mindist = sqrtf(dist); } \ } \ @@ -224,31 +170,24 @@ namespace ai } while(0) int closest = -1; wpcache::node *curnode; - loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) - { + loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) { int axis = curnode->axis(); float dist1 = pos[axis] - curnode->split[0], dist2 = curnode->split[1] - pos[axis]; - if(dist1 >= mindist) - { - if(dist2 < mindist) - { + if(dist1 >= mindist) { + if(dist2 < mindist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKCLOSEST(curnode->childindex(1)); } } - else if(curnode->isleaf(0)) - { + else if(curnode->isleaf(0)) { CHECKCLOSEST(curnode->childindex(0)); - if(dist2 < mindist) - { + if(dist2 < mindist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKCLOSEST(curnode->childindex(1)); } } - else - { - if(dist2 < mindist) - { + else { + if(dist2 < mindist) { if(!curnode->isleaf(1)) wpcachestack.add(curnode + curnode->childindex(1)); else CHECKCLOSEST(curnode->childindex(1)); } @@ -261,48 +200,38 @@ namespace ai for(int i = lastwpcache; i < waypoints.length(); i++) { CHECKCLOSEST(i); } return closest; } - - void findwaypointswithin(const vec &pos, float mindist, float maxdist, vector &results) - { + void findwaypointswithin(const vec &pos, float mindist, float maxdist, vector &results) { if(waypoints.empty()) return; if(clearedwpcaches) buildwpcache(); - float mindist2 = mindist*mindist, maxdist2 = maxdist*maxdist; #define CHECKWITHIN(index) do { \ int n = (index); \ - if(n < waypoints.length()) \ - { \ + if(n < waypoints.length()) { \ + \ const waypoint &w = waypoints[n]; \ float dist = w.o.squaredist(pos); \ if(dist > mindist2 && dist < maxdist2) results.add(n); \ } \ } while(0) wpcache::node *curnode; - loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) - { + loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) { int axis = curnode->axis(); float dist1 = pos[axis] - curnode->split[0], dist2 = curnode->split[1] - pos[axis]; - if(dist1 >= maxdist) - { - if(dist2 < maxdist) - { + if(dist1 >= maxdist) { + if(dist2 < maxdist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKWITHIN(curnode->childindex(1)); } } - else if(curnode->isleaf(0)) - { + else if(curnode->isleaf(0)) { CHECKWITHIN(curnode->childindex(0)); - if(dist2 < maxdist) - { + if(dist2 < maxdist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKWITHIN(curnode->childindex(1)); } } - else - { - if(dist2 < maxdist) - { + else { + if(dist2 < maxdist) { if(!curnode->isleaf(1)) wpcachestack.add(curnode + curnode->childindex(1)); else CHECKWITHIN(curnode->childindex(1)); } @@ -314,47 +243,37 @@ namespace ai } for(int i = lastwpcache; i < waypoints.length(); i++) { CHECKWITHIN(i); } } - - void avoidset::avoidnear(void *owner, float above, const vec &pos, float limit) - { + void avoidset::avoidnear(void *owner, float above, const vec &pos, float limit) { if(ai::waypoints.empty()) return; if(clearedwpcaches) buildwpcache(); - float limit2 = limit*limit; #define CHECKNEAR(index) do { \ int n = (index); \ - if(n < ai::waypoints.length()) \ - { \ + if(n < ai::waypoints.length()) { \ + \ const waypoint &w = ai::waypoints[n]; \ if(w.o.squaredist(pos) < limit2) add(owner, above, n); \ } \ } while(0) wpcache::node *curnode; - loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) - { + loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) { int axis = curnode->axis(); float dist1 = pos[axis] - curnode->split[0], dist2 = curnode->split[1] - pos[axis]; - if(dist1 >= limit) - { - if(dist2 < limit) - { + if(dist1 >= limit) { + if(dist2 < limit) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKNEAR(curnode->childindex(1)); } } - else if(curnode->isleaf(0)) - { + else if(curnode->isleaf(0)) { CHECKNEAR(curnode->childindex(0)); - if(dist2 < limit) - { + if(dist2 < limit) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKNEAR(curnode->childindex(1)); } } - else - { - if(dist2 < limit) - { + else { + if(dist2 < limit) { if(!curnode->isleaf(1)) wpcachestack.add(curnode + curnode->childindex(1)); else CHECKNEAR(curnode->childindex(1)); } @@ -366,27 +285,21 @@ namespace ai } for(int i = lastwpcache; i < waypoints.length(); i++) { CHECKNEAR(i); } } - - int avoidset::remap(fpsent *d, int n, vec &pos, bool retry) - { - if(!obstacles.empty()) - { + int avoidset::remap(fpsent *d, int n, vec &pos, bool retry) { + if(!obstacles.empty()) { int cur = 0; - loopv(obstacles) - { + loopv(obstacles) { obstacle &ob = obstacles[i]; int next = cur + ob.numwaypoints; - if(ob.owner != d) - { - for(; cur < next; cur++) if(waypoints[cur] == n) - { + if(ob.owner != d) { + for(; cur < next; cur++) if(waypoints[cur] == n) { if(ob.above < 0) return retry ? n : -1; vec above(pos.x, pos.y, ob.above); if(above.z-d->o.z >= ai::JUMPMAX) return retry ? n : -1; // too much scotty - int node = closestwaypoint(above, ai::SIGHTMIN, true, d); - if(ai::iswaypoint(node) && node != n) - { // try to reroute above their head? + int node = closestwaypoint(above, ai::SIGHTMIN, true); + if(ai::iswaypoint(node) && node != n) { + // try to reroute above their head? if(!find(node, d)) { pos = ai::waypoints[node].o; @@ -394,8 +307,7 @@ namespace ai } else return retry ? n : -1; } - else - { + else { vec old = d->o; d->o = vec(above).add(vec(0, 0, d->eyeheight)); bool col = collide(d, vec(0, 0, 1)); @@ -414,37 +326,25 @@ namespace ai } return n; } - static inline float heapscore(waypoint *q) { return q->score(); } - - bool route(fpsent *d, int node, int goal, vector &route, const avoidset &obstacles, int retries) - { + bool route(fpsent *d, int node, int goal, vector &route, const avoidset &obstacles, int retries) { if(waypoints.empty() || !iswaypoint(node) || !iswaypoint(goal) || goal == node || !waypoints[node].links[0]) return false; - static ushort routeid = 1; static vector queue; - - if(!routeid) - { + if(!routeid) { loopv(waypoints) waypoints[i].route = 0; routeid = 1; } - - if(d) - { - if(retries <= 1 && d->ai) loopi(ai::NUMPREVNODES) if(d->ai->prevnodes[i] != node && iswaypoint(d->ai->prevnodes[i])) - { + if(d) { + if(retries <= 1 && d->ai) loopi(ai::NUMPREVNODES) if(d->ai->prevnodes[i] != node && iswaypoint(d->ai->prevnodes[i])) { waypoints[d->ai->prevnodes[i]].route = routeid; waypoints[d->ai->prevnodes[i]].curscore = -1; waypoints[d->ai->prevnodes[i]].estscore = 0; } - if(retries <= 0) - { - loopavoid(obstacles, d, - { - if(iswaypoint(wp) && wp != node && wp != goal && waypoints[node].find(wp) < 0 && waypoints[goal].find(wp) < 0) - { + if(retries <= 0) { + loopavoid(obstacles, d, { + if(iswaypoint(wp) && wp != node && wp != goal && waypoints[node].find(wp) < 0 && waypoints[goal].find(wp) < 0) { waypoints[wp].route = routeid; waypoints[wp].curscore = -1; waypoints[wp].estscore = 0; @@ -452,34 +352,28 @@ namespace ai }); } } - waypoints[node].route = routeid; waypoints[node].curscore = waypoints[node].estscore = 0; waypoints[node].prev = 0; queue.setsize(0); queue.add(&waypoints[node]); route.setsize(0); - int lowest = -1; - while(!queue.empty()) - { + while(!queue.empty()) { waypoint &m = *queue.removeheap(); float prevscore = m.curscore; m.curscore = -1; - loopi(MAXWAYPOINTLINKS) - { + loopi(MAXWAYPOINTLINKS) { int link = m.links[i]; if(!link) break; - if(iswaypoint(link) && (link == node || link == goal || waypoints[link].links[0])) - { + if(iswaypoint(link) && (link == node || link == goal || waypoints[link].links[0])) { waypoint &n = waypoints[link]; int weight = max(n.weight, 1); float curscore = prevscore + n.o.dist(m.o)*weight; if(n.route == routeid && curscore >= n.curscore) continue; n.curscore = curscore; n.prev = ushort(&m - &waypoints[0]); - if(n.route != routeid) - { + if(n.route != routeid) { n.estscore = n.o.dist(waypoints[goal].o)*weight; if(n.estscore <= WAYPOINTRADIUS*4 && (lowest < 0 || n.estscore <= waypoints[lowest].estscore)) lowest = link; @@ -492,92 +386,68 @@ namespace ai } } foundgoal: - routeid++; - - if(lowest >= 0) // otherwise nothing got there - { + if(lowest >= 0) { // otherwise nothing got there { for(waypoint *m = &waypoints[lowest]; m > &waypoints[0]; m = &waypoints[m->prev]) route.add(m - &waypoints[0]); // just keep it stored backward } - return !route.empty(); } - VARF(dropwaypoints, 0, 0, 1, { player1->lastnode = -1; }); - - int addwaypoint(const vec &o, int weight = -1) - { + int addwaypoint(const vec &o, int weight = -1) { if(waypoints.length() > MAXWAYPOINTS) return -1; int n = waypoints.length(); waypoints.add(waypoint(o, weight >= 0 ? weight : getweight(o))); invalidatewpcache(n); return n; } - - void linkwaypoint(waypoint &a, int n) - { - loopi(MAXWAYPOINTLINKS) - { + void linkwaypoint(waypoint &a, int n) { + loopi(MAXWAYPOINTLINKS) { if(a.links[i] == n) return; if(!a.links[i]) { a.links[i] = n; return; } } a.links[rnd(MAXWAYPOINTLINKS)] = n; } - string loadedwaypoints = ""; - - static inline bool shouldnavigate() - { + static inline bool shouldnavigate() { if(dropwaypoints) return true; loopvrev(players) if(players[i]->aitype != AI_NONE) return true; return false; } - - static inline bool shoulddrop(fpsent *d) - { + static inline bool shoulddrop(fpsent *d) { return !d->ai && (dropwaypoints || !loadedwaypoints[0]); } - - void inferwaypoints(fpsent *d, const vec &o, const vec &v, float mindist) - { + void inferwaypoints(fpsent *d, const vec &o, const vec &v, float mindist) { if(!shouldnavigate()) return; - if(shoulddrop(d)) - { + if(shoulddrop(d)) { if(waypoints.empty()) seedwaypoints(); int from = closestwaypoint(o, mindist, false), to = closestwaypoint(v, mindist, false); if(!iswaypoint(from)) from = addwaypoint(o); if(!iswaypoint(to)) to = addwaypoint(v); if(d->lastnode != from && iswaypoint(d->lastnode) && iswaypoint(from)) linkwaypoint(waypoints[d->lastnode], from); - if(iswaypoint(to)) - { + if(iswaypoint(to)) { if(from != to && iswaypoint(from) && iswaypoint(to)) linkwaypoint(waypoints[from], to); d->lastnode = to; } } - else d->lastnode = closestwaypoint(v, WAYPOINTRADIUS*2, false, d); + else d->lastnode = closestwaypoint(v, WAYPOINTRADIUS*2, false); } - - void navigate(fpsent *d) - { + void navigate(fpsent *d) { vec v(d->feetpos()); if(d->state != CS_ALIVE) { d->lastnode = -1; return; } bool dropping = shoulddrop(d); int mat = lookupmaterial(v); if((mat&MATF_CLIP) == MAT_CLIP || mat&MAT_DEATH) dropping = false; float dist = dropping ? WAYPOINTRADIUS : (d->ai ? WAYPOINTRADIUS : SIGHTMIN); - int curnode = closestwaypoint(v, dist, false, d), prevnode = d->lastnode; - if(!iswaypoint(curnode) && dropping) - { + int curnode = closestwaypoint(v, dist, false), prevnode = d->lastnode; + if(!iswaypoint(curnode) && dropping) { if(waypoints.empty()) seedwaypoints(); curnode = addwaypoint(v); } - if(iswaypoint(curnode)) - { - if(dropping && d->lastnode != curnode && iswaypoint(d->lastnode)) - { + if(iswaypoint(curnode)) { + if(dropping && d->lastnode != curnode && iswaypoint(d->lastnode)) { linkwaypoint(waypoints[d->lastnode], curnode); if(!d->timeinair) linkwaypoint(waypoints[curnode], d->lastnode); } @@ -585,35 +455,26 @@ namespace ai if(d->ai && iswaypoint(prevnode) && d->lastnode != prevnode) d->ai->addprevnode(prevnode); } else if(!iswaypoint(d->lastnode) || waypoints[d->lastnode].o.squaredist(v) > SIGHTMIN*SIGHTMIN) - d->lastnode = closestwaypoint(v, SIGHTMAX, false, d); + d->lastnode = closestwaypoint(v, SIGHTMAX, false); } - - void navigate() - { + void navigate() { if(shouldnavigate()) loopv(players) ai::navigate(players[i]); if(invalidatedwpcaches) clearwpcache(false); } - - void clearwaypoints(bool full) - { + void clearwaypoints(bool full) { waypoints.setsize(0); clearwpcache(); - if(full) - { + if(full) { loadedwaypoints[0] = '\0'; dropwaypoints = 0; } } ICOMMAND(clearwaypoints, "", (), clearwaypoints()); - - void seedwaypoints() - { + void seedwaypoints() { if(waypoints.empty()) addwaypoint(vec(0, 0, 0)); - loopv(entities::ents) - { + loopv(entities::ents) { extentity &e = *entities::ents[i]; - switch(e.type) - { + switch(e.type) { case PLAYERSTART: case TELEPORT: case JUMPPAD: addwaypoint(e.o); break; @@ -623,21 +484,17 @@ namespace ai } } } - - void remapwaypoints() - { + void remapwaypoints() { vector remap; int total = 0; loopv(waypoints) remap.add(waypoints[i].links[1] == 0xFFFF ? 0 : total++); total = 0; - loopvj(waypoints) - { + loopvj(waypoints) { if(waypoints[j].links[1] == 0xFFFF) continue; waypoint &w = waypoints[total]; if(j != total) w = waypoints[j]; int k = 0; - loopi(MAXWAYPOINTLINKS) - { + loopi(MAXWAYPOINTLINKS) { int link = w.links[i]; if(!link) break; if((w.links[k] = remap[link])) k++; @@ -647,22 +504,17 @@ namespace ai } waypoints.setsize(total); } - - bool cleanwaypoints() - { + bool cleanwaypoints() { int cleared = 0; - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; - if(clipped(w.o)) - { + if(clipped(w.o)) { w.links[0] = 0; w.links[1] = 0xFFFF; cleared++; } } - if(cleared) - { + if(cleared) { player1->lastnode = -1; loopv(players) if(players[i]) players[i]->lastnode = -1; remapwaypoints(); @@ -671,37 +523,28 @@ namespace ai } return false; } - - bool getwaypointfile(const char *mname, char *wptname) - { + bool getwaypointfile(const char *mname, char *wptname) { if(!mname || !*mname) mname = getclientmap(); if(!*mname) return false; - string pakname, mapname, cfgname; getmapfilenames(mname, NULL, pakname, mapname, cfgname); nformatstring(wptname, MAXSTRLEN, "packages/%s.wpt", mapname); path(wptname); return true; } - - void loadwaypoints(bool force, const char *mname) - { + void loadwaypoints(bool force, const char *mname) { string wptname; if(!getwaypointfile(mname, wptname)) return; if(!force && (waypoints.length() || !strcmp(loadedwaypoints, wptname))) return; - stream *f = opengzfile(wptname, "rb"); if(!f) return; char magic[4]; if(f->read(magic, 4) < 4 || memcmp(magic, "OWPT", 4)) { delete f; return; } - copystring(loadedwaypoints, wptname); - waypoints.setsize(0); waypoints.add(vec(0, 0, 0)); ushort numwp = f->getlil(); - loopi(numwp) - { + loopi(numwp) { if(f->end()) break; vec o; o.x = f->getlil(); @@ -709,35 +552,26 @@ namespace ai o.z = f->getlil(); waypoint &w = waypoints.add(waypoint(o, getweight(o))); int numlinks = f->getchar(), k = 0; - loopi(numlinks) - { - if((w.links[k] = f->getlil())) - { + loopi(numlinks) { + if((w.links[k] = f->getlil())) { if(++k >= MAXWAYPOINTLINKS) break; } } } - delete f; conoutf("loaded %d waypoints from %s", numwp, wptname); - if(!cleanwaypoints()) clearwpcache(); } ICOMMAND(loadwaypoints, "s", (char *mname), loadwaypoints(true, mname)); - - void savewaypoints(bool force, const char *mname) - { + void savewaypoints(bool force, const char *mname) { if((!dropwaypoints && !force) || waypoints.empty()) return; - string wptname; if(!getwaypointfile(mname, wptname)) return; - stream *f = opengzfile(wptname, "wb"); if(!f) return; f->write("OWPT", 4); f->putlil(waypoints.length()-1); - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; f->putlil(w.o.x); f->putlil(w.o.y); @@ -747,55 +581,43 @@ namespace ai f->putchar(numlinks); loopj(numlinks) f->putlil(w.links[j]); } - delete f; conoutf("saved %d waypoints to %s", waypoints.length()-1, wptname); } - ICOMMAND(savewaypoints, "s", (char *mname), savewaypoints(true, mname)); - - void delselwaypoints() - { + void delselwaypoints() { if(noedit(true)) return; vec o = vec(sel.o).sub(0.1f), s = vec(sel.s).mul(sel.grid).add(o).add(0.1f); int cleared = 0; - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; - if(w.o.x >= o.x && w.o.x <= s.x && w.o.y >= o.y && w.o.y <= s.y && w.o.z >= o.z && w.o.z <= s.z) - { + if(w.o.x >= o.x && w.o.x <= s.x && w.o.y >= o.y && w.o.y <= s.y && w.o.z >= o.z && w.o.z <= s.z) { w.links[0] = 0; w.links[1] = 0xFFFF; cleared++; } } - if(cleared) - { + if(cleared) { player1->lastnode = -1; remapwaypoints(); clearwpcache(); } } COMMAND(delselwaypoints, ""); - - void movewaypoints(const vec &d) - { + void movewaypoints(const vec &d) { if(noedit(true)) return; int worldsize = getworldsize(); - if(d.x < -worldsize || d.x > worldsize || d.y < -worldsize || d.y > worldsize || d.z < -worldsize || d.z > worldsize) - { + if(d.x < -worldsize || d.x > worldsize || d.y < -worldsize || d.y > worldsize || d.z < -worldsize || d.z > worldsize) { clearwaypoints(); return; } int cleared = 0; - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; w.o.add(d); if(!insideworld(w.o)) { w.links[0] = 0; w.links[1] = 0xFFFF; cleared++; } } - if(cleared) - { + if(cleared) { player1->lastnode = -1; remapwaypoints(); } diff --git a/src/fpsgame/weapon.cpp b/src/fpsgame/weapon.cpp index 1bdb302..c486110 100644 --- a/src/fpsgame/weapon.cpp +++ b/src/fpsgame/weapon.cpp @@ -1,37 +1,27 @@ // weapon.cpp: all shooting and effects code, projectile management #include "game.h" -namespace game -{ +namespace game { static const int OFFSETMILLIS = 500; vec rays[MAXRAYS]; - - struct hitmsg - { + struct hitmsg { int target, lifesequence, info1, info2; ivec dir; }; vector hits; - ICOMMAND(getweapon, "", (), intret(player1->gunselect)); - - void gunselect(int gun, fpsent *d) - { - if(gun!=d->gunselect) - { + void gunselect(int gun, fpsent *d) { + if(gun!=d->gunselect) { addmsg(N_GUNSELECT, "rci", d, gun); playsound(S_WEAPLOAD, d == player1 ? NULL : &d->o); } d->gunselect = gun; } - - void nextweapon(int dir, bool force = false) - { + void nextweapon(int dir, bool force = false) { if(player1->state!=CS_ALIVE) return; dir = (dir < 0 ? NUMGUNS-1 : 1); int gun = player1->gunselect; - loopi(NUMGUNS) - { + loopi(NUMGUNS) { gun = (gun + dir)%NUMGUNS; if(force || player1->ammo[gun]) break; } @@ -39,50 +29,39 @@ namespace game else playsound(S_NOAMMO); } ICOMMAND(nextweapon, "ii", (int *dir, int *force), nextweapon(*dir, *force!=0)); - - int getweapon(const char *name) - { + int getweapon(const char *name) { const char *abbrevs[] = { "FI", "SG", "CG", "RL", "RI", "GL", "PI" }; if(isdigit(name[0])) return parseint(name); else loopi(sizeof(abbrevs)/sizeof(abbrevs[0])) if(!strcasecmp(abbrevs[i], name)) return i; return -1; } - - void setweapon(const char *name, bool force = false) - { + void setweapon(const char *name, bool force = false) { int gun = getweapon(name); if(player1->state!=CS_ALIVE || gunGUN_PISTOL) return; if(force || player1->ammo[gun]) gunselect(gun, player1); else playsound(S_NOAMMO); } ICOMMAND(setweapon, "si", (char *name, int *force), setweapon(name, *force!=0)); - - void cycleweapon(int numguns, int *guns, bool force = false) - { + void cycleweapon(int numguns, int *guns, bool force = false) { if(numguns<=0 || player1->state!=CS_ALIVE) return; int offset = 0; loopi(numguns) if(guns[i] == player1->gunselect) { offset = i+1; break; } - loopi(numguns) - { + loopi(numguns) { int gun = guns[(i+offset)%numguns]; - if(gun>=0 && gunammo[gun])) - { + if(gun>=0 && gunammo[gun])) { gunselect(gun, player1); return; } } playsound(S_NOAMMO); } - ICOMMAND(cycleweapon, "V", (tagval *args, int numargs), - { + ICOMMAND(cycleweapon, "V", (tagval *args, int numargs), { int numguns = min(numargs, 7); int guns[7]; loopi(numguns) guns[i] = getweapon(args[i].getstr()); cycleweapon(numguns, guns); }); - - void weaponswitch(fpsent *d) - { + void weaponswitch(fpsent *d) { if(d->state!=CS_ALIVE) return; int s = d->gunselect; if (s!=GUN_CG && d->ammo[GUN_CG]) s = GUN_CG; @@ -92,49 +71,36 @@ namespace game else if(s!=GUN_GL && d->ammo[GUN_GL]) s = GUN_GL; else if(s!=GUN_PISTOL && d->ammo[GUN_PISTOL]) s = GUN_PISTOL; else s = GUN_FIST; - gunselect(s, d); } - - ICOMMAND(weapon, "V", (tagval *args, int numargs), - { + ICOMMAND(weapon, "V", (tagval *args, int numargs), { if(player1->state!=CS_ALIVE) return; - loopi(7) - { + loopi(7) { const char *name = i < numargs ? args[i].getstr() : ""; - if(name[0]) - { + if(name[0]) { int gun = getweapon(name); if(gun >= GUN_FIST && gun <= GUN_PISTOL && gun != player1->gunselect && player1->ammo[gun]) { gunselect(gun, player1); return; } } else { weaponswitch(player1); return; } } playsound(S_NOAMMO); }); - - void offsetray(const vec &from, const vec &to, int spread, float range, vec &dest) - { + void offsetray(const vec &from, const vec &to, int spread, float range, vec &dest) { vec offset; do offset = vec(rndscale(1), rndscale(1), rndscale(1)).sub(0.5f); while(offset.squaredlen() > 0.5f*0.5f); offset.mul((to.dist(from)/1024)*spread); offset.z /= 2; dest = vec(offset).add(to); - if(dest != from) - { + if(dest != from) { vec dir = vec(dest).sub(from).normalize(); raycubepos(from, dir, dest, range, RAY_CLIPMAT|RAY_ALPHAPOLY); } } - - void createrays(int gun, const vec &from, const vec &to) // create random spread of rays - { + void createrays(int gun, const vec &from, const vec &to) { // create random spread of rays { loopi(guns[gun].rays) offsetray(from, to, guns[gun].spread, guns[gun].range, rays[i]); } - enum { BNC_GRENADE }; - - struct bouncer : physent - { + struct bouncer : physent { int lifetime, bounces; float lastyaw, roll; bool local; @@ -145,37 +111,26 @@ namespace game float offsetheight; int id; entitylight light; - - bouncer() : bounces(0), roll(0), variant(0) - { + bouncer() : bounces(0), roll(0), variant(0) { type = ENT_BOUNCE; } - - vec offsetpos() - { + vec offsetpos() { vec pos(o); - if(offsetmillis > 0) - { + if(offsetmillis > 0) { pos.add(vec(offset).mul(offsetmillis/float(OFFSETMILLIS))); if(offsetheight >= 0) pos.z = max(pos.z, o.z - max(offsetheight - eyeheight, 0.0f)); } return pos; } - - void limitoffset() - { + void limitoffset() { if(bouncetype == BNC_GRENADE && offsetmillis > 0 && offset.z < 0) offsetheight = raycube(vec(o.x + offset.x, o.y + offset.y, o.z), vec(0, 0, -1), -offset.z); else offsetheight = -1; } }; - vector bouncers; - vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d); - - void newbouncer(const vec &from, const vec &to, bool local, int id, fpsent *owner, int type, int lifetime, int speed, entitylight *light = NULL) - { + void newbouncer(const vec &from, const vec &to, bool local, int id, fpsent *owner, int type, int lifetime, int speed, entitylight *light = NULL) { bouncer &bnc = *bouncers.add(new bouncer); bnc.o = from; bnc.radius = bnc.xradius = bnc.yradius = 1.5f; @@ -187,18 +142,13 @@ namespace game bnc.bouncetype = type; bnc.id = local ? lastmillis : id; if(light) bnc.light = *light; - bnc.collidetype = COLLIDE_ELLIPSE_PRECISE; - vec dir(to); dir.sub(from).safenormalize(); bnc.vel = dir; bnc.vel.mul(speed); - avoidcollision(&bnc, dir, owner, 0.1f); - - if(type==BNC_GRENADE) - { + if(type==BNC_GRENADE) { bnc.offset = hudgunorigin(GUN_GL, from, to, owner); if(owner==followingplayer(player1) && !isthirdperson()) bnc.offset.sub(owner->o).rescale(16).add(owner->o); } @@ -206,37 +156,27 @@ namespace game bnc.offset.sub(bnc.o); bnc.offsetmillis = OFFSETMILLIS; bnc.limitoffset(); - bnc.resetinterp(); } - - void bounced(physent *d, const vec &surface) - { + void bounced(physent *d, const vec &surface) { if(d->type != ENT_BOUNCE) return; bouncer *b = (bouncer *)d; if(b->bounces >= 2) return; b->bounces++; adddecal(DECAL_BLOOD, vec(b->o).sub(vec(surface).mul(b->radius)), surface, 2.96f/b->bounces, bvec(0x60, 0xFF, 0xFF), rnd(4)); } - - void updatebouncers(int time) - { - loopv(bouncers) - { + void updatebouncers(int time) { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; - if(bnc.bouncetype==BNC_GRENADE && bnc.vel.magnitude() > 50.0f) - { + if(bnc.bouncetype==BNC_GRENADE && bnc.vel.magnitude() > 50.0f) { vec pos = bnc.offsetpos(); regular_particle_splash(PART_SMOKE, 1, 150, pos, 0x404040, 2.4f, 50, -20); } vec old(bnc.o); bool stopped = false; if(bnc.bouncetype==BNC_GRENADE) stopped = bounce(&bnc, 0.6f, 0.5f, 0.8f) || (bnc.lifetime -= time)<0; - - if(stopped) - { - if(bnc.bouncetype==BNC_GRENADE) - { + if(stopped) { + if(bnc.bouncetype==BNC_GRENADE) { int qdam = guns[GUN_GL].damage*(bnc.owner->quadmillis ? 4 : 1); hits.setsize(0); explode(bnc.local, bnc.owner, bnc.o, NULL, qdam, GUN_GL); @@ -247,24 +187,18 @@ namespace game } delete bouncers.remove(i--); } - else - { + else { bnc.roll += old.sub(bnc.o).magnitude()/(4*RAD); bnc.offsetmillis = max(bnc.offsetmillis-time, 0); bnc.limitoffset(); } } } - - void removebouncers(fpsent *owner) - { + void removebouncers(fpsent *owner) { loopv(bouncers) if(bouncers[i]->owner==owner) { delete bouncers[i]; bouncers.remove(i--); } } - void clearbouncers() { bouncers.deletecontents(); } - - struct projectile - { + struct projectile { vec dir, o, to, offset; float speed; fpsent *owner; @@ -275,11 +209,8 @@ namespace game entitylight light; }; vector projs; - void clearprojectiles() { projs.shrink(0); } - - void newprojectile(const vec &from, const vec &to, float speed, bool local, int id, fpsent *owner, int gun) - { + void newprojectile(const vec &from, const vec &to, float speed, bool local, int id, fpsent *owner, int gun) { projectile &p = projs.add(); p.dir = vec(to).sub(from).safenormalize(); p.o = from; @@ -293,69 +224,51 @@ namespace game p.offsetmillis = OFFSETMILLIS; p.id = local ? lastmillis : id; } - - void removeprojectiles(fpsent *owner) - { + void removeprojectiles(fpsent *owner) { // can't use loopv here due to strange GCC optimizer bug int len = projs.length(); loopi(len) if(projs[i].owner==owner) { projs.remove(i--); len--; } } - VARP(blood, 0, 1, 1); - - void damageeffect(int damage, fpsent *d, bool thirdperson) - { + void damageeffect(int damage, fpsent *d, bool thirdperson) { vec p = d->o; p.z += 0.6f*(d->eyeheight + d->aboveeye) - d->eyeheight; if(blood) particle_splash(PART_BLOOD, damage/10, 1000, p, 0x60FFFF, 2.96f); - if(thirdperson) - { + if(thirdperson) { defformatstring(ds, "%d", damage); particle_textcopy(d->abovehead(), ds, PART_TEXT, 2000, 0xFF4B19, 4.0f, -8); } } - - void spawnbouncer(const vec &p, const vec &vel, fpsent *d, int type, entitylight *light = NULL) - { - vec to(rnd(100)-50, rnd(100)-50, rnd(100)-50); - if(to.iszero()) to.z += 1; - to.normalize(); - to.add(p); - newbouncer(p, to, true, 0, d, type, rnd(1000)+1000, rnd(100)+20, light); - } - - void hit(int damage, dynent *d, fpsent *at, const vec &vel, int gun, float info1, int info2 = 1) - { - if(at==player1 && d!=at) - { + //~void spawnbouncer(const vec &p, const vec &vel, fpsent *d, int type, entitylight *light = NULL) + //~{ + //~vec to(rnd(100)-50, rnd(100)-50, rnd(100)-50); + //~if(to.iszero()) to.z += 1; + //~to.normalize(); + //~to.add(p); + //~newbouncer(p, to, true, 0, d, type, rnd(1000)+1000, rnd(100)+20, light); + //~} + void hit(int damage, dynent *d, fpsent *at, const vec &vel, int gun, float info1, int info2 = 1) { + if(at==player1 && d!=at) { extern int hitsound; if(hitsound && lasthit != lastmillis) playsound(S_HIT); lasthit = lastmillis; } - fpsent *f = (fpsent *)d; - f->lastpain = lastmillis; if(at->type==ENT_PLAYER && !isteam(at->team, f->team)) at->totaldamage += damage; - if(f->type==ENT_AI || !m_mp(gamemode) || f==at) f->hitpush(damage, vel, at, gun); - pwhit(gun, damage); - if(!m_mp(gamemode)) damaged(damage, f, at); - else - { + else { hitmsg &h = hits.add(); h.target = f->clientnum; h.lifesequence = f->lifesequence; h.info1 = int(info1*DMF); h.info2 = info2; h.dir = f==at ? ivec(0, 0, 0) : ivec(vec(vel).mul(DNF)); - if(at==player1) - { + if(at==player1) { damageeffect(damage, f); - if(f==player1) - { + if(f==player1) { damagecompass(damage, at ? at->o : f->o); playsound(S_PAIN6); } @@ -363,14 +276,10 @@ namespace game } } } - - void hitpush(int damage, dynent *d, fpsent *at, vec &from, vec &to, int gun, int rays) - { + void hitpush(int damage, dynent *d, fpsent *at, vec &from, vec &to, int gun, int rays) { hit(damage, d, at, vec(to).sub(from).safenormalize(), gun, from.dist(to), rays); } - - float projdist(dynent *o, vec &dir, const vec &v) - { + float projdist(dynent *o, vec &dir, const vec &v) { vec middle = o->o; middle.z += (o->aboveeye-o->eyeheight)/2; float dist = middle.dist(v, dir); @@ -378,68 +287,53 @@ namespace game if(dist<0) dist = 0; return dist; } - - void radialeffect(dynent *o, const vec &v, int qdam, fpsent *at, int gun) - { + void radialeffect(dynent *o, const vec &v, int qdam, fpsent *at, int gun) { if(o->state!=CS_ALIVE) return; vec dir; float dist = projdist(o, dir, v); - if(disto.reject(v, o->radius + guns[gun].exprad) || o==safe) continue; radialeffect(o, v, damage, owner, gun); } } - - void projsplash(projectile &p, vec &v, dynent *safe, int damage) - { - if(guns[p.gun].part) - { + void projsplash(projectile &p, vec &v, dynent *safe, int damage) { + if(guns[p.gun].part) { particle_splash(PART_SPARK, 100, 200, v, 0xB49B4B, 0.24f); playsound(S_FEXPLODE, &v); // no push? } - else - { + else { explode(p.local, p.owner, v, safe, damage, GUN_RL); adddecal(DECAL_SCORCH, v, vec(p.dir).neg(), guns[p.gun].exprad/2); } } - - void explodeeffects(int gun, fpsent *d, bool local, int id) - { + void explodeeffects(int gun, fpsent *d, bool local, int id) { if(local) return; - switch(gun) - { + switch(gun) { case GUN_RL: - loopv(projs) - { + loopv(projs) { projectile &p = projs[i]; - if(p.gun == gun && p.owner == d && p.id == id && !p.local) - { + if(p.gun == gun && p.owner == d && p.id == id && !p.local) { vec pos(p.o); pos.add(vec(p.offset).mul(p.offsetmillis/float(OFFSETMILLIS))); explode(p.local, p.owner, pos, NULL, 0, GUN_RL); @@ -450,11 +344,9 @@ namespace game } break; case GUN_GL: - loopv(bouncers) - { + loopv(bouncers) { bouncer &b = *bouncers[i]; - if(b.bouncetype == BNC_GRENADE && b.owner == d && b.id == id && !b.local) - { + if(b.bouncetype == BNC_GRENADE && b.owner == d && b.id == id && !b.local) { vec pos = b.offsetpos(); explode(b.local, b.owner, pos, NULL, 0, GUN_GL); adddecal(DECAL_SCORCH, pos, vec(0, 0, 1), guns[gun].exprad/2); @@ -467,9 +359,7 @@ namespace game break; } } - - bool projdamage(dynent *o, projectile &p, vec &v, int qdam) - { + bool projdamage(dynent *o, projectile &p, vec &v, int qdam) { if(o->state!=CS_ALIVE) return false; if(!intersect(o, p.o, v)) return false; projsplash(p, v, o, qdam); @@ -478,11 +368,8 @@ namespace game hit(qdam, o, p.owner, dir, p.gun, 0); return true; } - - void updateprojectiles(int time) - { - loopv(projs) - { + void updateprojectiles(int time) { + loopv(projs) { projectile &p = projs[i]; p.offsetmillis = max(p.offsetmillis-time, 0); int qdam = guns[p.gun].damage*(p.owner->quadmillis ? 4 : 1); @@ -492,37 +379,30 @@ namespace game vec v = vec(p.o).add(dv); bool exploded = false; hits.setsize(0); - if(p.local) - { + if(p.local) { vec halfdv = vec(dv).mul(0.5f), bo = vec(p.o).add(halfdv); float br = max(fabs(halfdv.x), fabs(halfdv.y)) + 1; - loopj(numdynents()) - { + loopj(numdynents()) { dynent *o = iterdynents(j); if(p.owner==o || o->o.reject(bo, o->radius + br)) continue; if(projdamage(o, p, v, qdam)) { exploded = true; break; } } } - if(!exploded) - { - if(dist<4) - { - if(p.o!=p.to) // if original target was moving, reevaluate endpoint - { + if(!exploded) { + if(dist<4) { + if(p.o!=p.to) { // if original target was moving, reevaluate endpoint { if(raycubepos(p.o, p.dir, p.to, 0, RAY_CLIPMAT|RAY_ALPHAPOLY)>=4) continue; } projsplash(p, v, NULL, qdam); exploded = true; } - else - { + else { vec pos(v); pos.add(vec(p.offset).mul(p.offsetmillis/float(OFFSETMILLIS))); regular_particle_splash(PART_SMOKE, 2, 300, pos, 0x404040, 2.4f, 50, -20); } } - if(exploded) - { + if(exploded) { if(p.local) addmsg(N_EXPLODE, "rci3iv", p.owner, lastmillis-maptime, p.gun, p.id-maptime, hits.length(), hits.length()*sizeof(hitmsg)/sizeof(int), hits.getbuf()); @@ -531,28 +411,20 @@ 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 - { + 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) - { + switch(gun) { case GUN_FIST: if(d->type==ENT_PLAYER && chainsawhudgun) sound = S_CHAINSAW_ATTACK; break; - - case GUN_SG: - { + case GUN_SG: { if(!local) createrays(gun, from, to); if(muzzleflash && d->muzzle.x >= 0) particle_flare(d->muzzle, d->muzzle, 200, PART_MUZZLE_FLASH3, 0xFFFFFF, 2.75f, d); - loopi(guns[gun].rays) - { + loopi(guns[gun].rays) { if(d->quadmillis) particle_trail(PART_FLAME, 400, hudgunorigin(gun, from, rays[i], d), rays[i], 0x802010, 0.6f, 36); particle_splash(PART_SPARK, 20, 250, rays[i], 0xB49B4B, 0.24f); @@ -562,10 +434,8 @@ namespace game if(muzzlelight) adddynlight(hudgunorigin(gun, d->o, to, d), 30, vec(0.5f, 0.375f, 0.25f), 100, 100, DL_FLASH, 0, vec(0, 0, 0), d); break; } - case GUN_CG: - case GUN_PISTOL: - { + case GUN_PISTOL: { particle_splash(PART_SPARK, 200, 250, to, 0xB49B4B, 0.24f); if(d->quadmillis) particle_trail(PART_FLAME, 400, hudgunorigin(gun, from, to, d), to, 0x802010, 0.6f, 36); @@ -576,7 +446,6 @@ namespace game if(muzzlelight) adddynlight(hudgunorigin(gun, d->o, to, d), gun==GUN_CG ? 30 : 15, vec(0.5f, 0.375f, 0.25f), gun==GUN_CG ? 50 : 100, gun==GUN_CG ? 50 : 100, DL_FLASH, 0, vec(0, 0, 0), d); break; } - case GUN_RL: if(d->quadmillis) particle_trail(PART_FLAME, 400, hudgunorigin(gun, from, to, d), to, 0x802010, 0.6f, 36); @@ -585,9 +454,7 @@ namespace game pspeed = guns[gun].projspeed; newprojectile(from, to, (float)pspeed, local, id, d, gun); break; - - case GUN_GL: - { + case GUN_GL: { float dist = from.dist(to); vec up = to; up.z += dist/8; @@ -597,7 +464,6 @@ namespace game newbouncer(from, up, local, id, d, BNC_GRENADE, guns[gun].ttl, guns[gun].projspeed); break; } - case GUN_RIFLE: particle_splash(PART_SPARK, 200, 250, to, 0xB49B4B, 0.24f); if(d->quadmillis) @@ -609,13 +475,11 @@ namespace game if(muzzlelight) adddynlight(hudgunorigin(gun, d->o, to, d), 25, vec(0.5f, 0.375f, 0.25f), 75, 75, DL_FLASH, 0, vec(0, 0, 0), d); break; } - bool looped = false; if(d->attacksound >= 0 && d->attacksound != sound) d->stopattacksound(); if(d->idlesound >= 0) d->stopidlesound(); fpsent *h = followingplayer(player1); - switch(sound) - { + switch(sound) { case S_CHAINSAW_ATTACK: if(d->attacksound >= 0) looped = true; d->attacksound = sound; @@ -627,114 +491,89 @@ namespace game } if(d->quadmillis && lastmillis-prevaction>200 && !looped) playsound(S_ITEMPUP, d==h ? NULL : &d->o); } - - void particletrack(physent *owner, vec &o, vec &d) - { + void particletrack(physent *owner, vec &o, vec &d) { if(owner->type!=ENT_PLAYER && owner->type!=ENT_AI) return; fpsent *pl = (fpsent *)owner; if(pl->muzzle.x < 0 || pl->lastattackgun != pl->gunselect) return; float dist = o.dist(d); o = pl->muzzle; if(dist <= 0) d = o; - else - { + else { vecfromyawpitch(owner->yaw, owner->pitch, 1, 0, d); float newdist = raycube(owner->o, d, dist, RAY_CLIPMAT|RAY_ALPHAPOLY); d.mul(min(newdist, dist)).add(owner->o); } } - - void dynlighttrack(physent *owner, vec &o, vec &hud) - { + void dynlighttrack(physent *owner, vec &o, vec &hud) { if(owner->type!=ENT_PLAYER && owner->type!=ENT_AI) return; fpsent *pl = (fpsent *)owner; if(pl->muzzle.x < 0 || pl->lastattackgun != pl->gunselect) return; o = pl->muzzle; hud = owner == followingplayer(player1) ? vec(pl->o).add(vec(0, 0, 2)) : pl->muzzle; } - float intersectdist = 1e16f; - - bool intersect(dynent *d, const vec &from, const vec &to, float &dist) // if lineseg hits entity bounding box - { + bool intersect(dynent *d, const vec &from, const vec &to, float &dist) { // if lineseg hits entity bounding box { vec bottom(d->o), top(d->o); bottom.z -= d->eyeheight; top.z += d->aboveeye; return linecylinderintersect(from, to, bottom, top, d->radius, dist); } - - dynent *intersectclosest(const vec &from, const vec &to, fpsent *at, float &bestdist) - { + dynent *intersectclosest(const vec &from, const vec &to, fpsent *at, float &bestdist) { dynent *best = NULL; bestdist = 1e16f; - loopi(numdynents()) - { + loopi(numdynents()) { dynent *o = iterdynents(i); if(o==at || o->state!=CS_ALIVE) continue; float dist; if(!intersect(o, from, to, dist)) continue; - if(distgunselect].damage; if(d->quadmillis) qdam *= 4; dynent *o; float dist; - if(guns[d->gunselect].rays > 1) - { + if(guns[d->gunselect].rays > 1) { dynent *hits[MAXRAYS]; int maxrays = guns[d->gunselect].rays; - loopi(maxrays) - { + loopi(maxrays) { if((hits[i] = intersectclosest(from, rays[i], d, dist))) shorten(from, rays[i], dist); else adddecal(DECAL_BULLET, rays[i], vec(from).sub(rays[i]).safenormalize(), 2.0f); } - loopi(maxrays) if(hits[i]) - { + loopi(maxrays) if(hits[i]) { o = hits[i]; hits[i] = NULL; int numhits = 1; - for(int j = i+1; j < maxrays; j++) if(hits[j] == o) - { + for(int j = i+1; j < maxrays; j++) if(hits[j] == o) { hits[j] = NULL; numhits++; } hitpush(numhits*qdam, o, d, from, to, d->gunselect, numhits); } } - else if((o = intersectclosest(from, to, d, dist))) - { + else if((o = intersectclosest(from, to, d, dist))) { shorten(from, to, dist); hitpush(qdam, o, d, from, to, d->gunselect, 1); } else if(d->gunselect!=GUN_FIST) adddecal(DECAL_BULLET, to, vec(from).sub(to).safenormalize(), d->gunselect==GUN_RIFLE ? 3.0f : 2.0f); } - - void shoot(fpsent *d, const vec &targ) - { + void shoot(fpsent *d, const vec &targ) { int prevaction = d->lastaction, attacktime = lastmillis-prevaction; if(attacktimegunwait) return; d->gunwait = 0; if((d==player1 || d->ai) && !d->attacking) return; d->lastaction = lastmillis; d->lastattackgun = d->gunselect; - if(!d->ammo[d->gunselect]) - { - if(d==player1) - { + if(!d->ammo[d->gunselect]) { + if(d==player1) { msgsound(S_NOAMMO, d); d->gunwait = 600; d->lastattackgun = -1; @@ -743,9 +582,7 @@ namespace game return; } if(d->gunselect) d->ammo[d->gunselect]--; - pwshot(d->gunselect); /// PW - vec from = d->o, to = targ, dir = vec(to).sub(from).safenormalize(); float dist = to.dist(from); vec kickback = vec(dir).mul(guns[d->gunselect].kickamount*-2.5f); @@ -757,65 +594,48 @@ namespace game if(barrier > 0 && barrier < dist && (!shorten || barrier < shorten)) shorten = barrier; if(shorten) to = vec(dir).mul(shorten).add(from); - if(guns[d->gunselect].rays > 1) createrays(d->gunselect, from, to); else if(guns[d->gunselect].spread) offsetray(from, to, guns[d->gunselect].spread, guns[d->gunselect].range, to); - hits.setsize(0); - if(!guns[d->gunselect].projspeed) raydamage(from, to, d); - shoteffects(d->gunselect, from, to, d, true, 0, prevaction); - - if(d==player1 || d->ai) - { + if(d==player1 || d->ai) { addmsg(N_SHOOT, "rci2i6iv", d, lastmillis-maptime, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF), hits.length(), hits.length()*sizeof(hitmsg)/sizeof(int), hits.getbuf()); } - d->gunwait = guns[d->gunselect].attackdelay; if(d->gunselect == GUN_PISTOL && d->ai) d->gunwait += int(d->gunwait*(((101-d->skill)+rnd(111-d->skill))/100.f)); d->totalshots += guns[d->gunselect].damage*(d->quadmillis ? 4 : 1)*guns[d->gunselect].rays; } - - void adddynlights() - { - loopv(projs) - { + void adddynlights() { + loopv(projs) { projectile &p = projs[i]; if(p.gun!=GUN_RL) continue; vec pos(p.o); pos.add(vec(p.offset).mul(p.offsetmillis/float(OFFSETMILLIS))); adddynlight(pos, 20, vec(1, 0.75f, 0.5f)); } - loopv(bouncers) - { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; if(bnc.bouncetype!=BNC_GRENADE) continue; vec pos = bnc.offsetpos(); adddynlight(pos, 8, vec(0.25f, 1, 1)); } } - static const char * const projnames[2] = { "projectiles/grenade", "projectiles/rocket" }; - void preloadbouncers() { loopi(sizeof(projnames)/sizeof(projnames[0])) preloadmodel(projnames[i]); } - - void renderbouncers() - { + void renderbouncers() { float yaw, pitch; - loopv(bouncers) - { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; vec pos = bnc.offsetpos(); vec vel(bnc.vel); if(vel.magnitude() <= 25.0f) yaw = bnc.lastyaw; - else - { + else { vectoyawpitch(vel, yaw, pitch); yaw += 90; bnc.lastyaw = yaw; @@ -823,8 +643,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); - else - { + else { const char *mdl = NULL; int cull = MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED; float fade = 1; @@ -833,12 +652,9 @@ namespace game } } } - - void renderprojectiles() - { + void renderprojectiles() { float yaw, pitch; - loopv(projs) - { + loopv(projs) { projectile &p = projs[i]; if(p.gun!=GUN_RL) continue; float dist = min(p.o.dist(p.to)/32.0f, 1.0f); @@ -852,12 +668,9 @@ namespace game rendermodel(&p.light, "projectiles/rocket", ANIM_MAPMODEL|ANIM_LOOP, v, yaw, pitch, MDL_CULL_VFC|MDL_CULL_OCCLUDED|MDL_LIGHT|MDL_LIGHT_FAST); } } - - void checkattacksound(fpsent *d, bool local) - { + void checkattacksound(fpsent *d, bool local) { int gun = -1; - switch(d->attacksound) - { + switch(d->attacksound) { case S_CHAINSAW_ATTACK: if(chainsawhudgun) gun = GUN_FIST; break; @@ -866,74 +679,57 @@ namespace game } if(gun >= 0 && gun < NUMGUNS && d->clientnum >= 0 && d->state == CS_ALIVE && - d->lastattackgun == gun && lastmillis - d->lastaction < guns[gun].attackdelay + 50) - { + d->lastattackgun == gun && lastmillis - d->lastaction < guns[gun].attackdelay + 50) { d->attackchan = playsound(d->attacksound, local ? NULL : &d->o, NULL, 0, -1, -1, d->attackchan); if(d->attackchan < 0) d->attacksound = -1; } else d->stopattacksound(); } - - void checkidlesound(fpsent *d, bool local) - { + void checkidlesound(fpsent *d, bool local) { int sound = -1, radius = 0; - if(d->clientnum >= 0 && d->state == CS_ALIVE) switch(d->gunselect) - { + if(d->clientnum >= 0 && d->state == CS_ALIVE) switch(d->gunselect) { case GUN_FIST: - if(chainsawhudgun && d->attacksound < 0) - { + if(chainsawhudgun && d->attacksound < 0) { sound = S_CHAINSAW_IDLE; radius = 50; } break; } - if(d->idlesound != sound) - { + if(d->idlesound != sound) { if(d->idlesound >= 0) d->stopidlesound(); - if(sound >= 0) - { + if(sound >= 0) { d->idlechan = playsound(sound, local ? NULL : &d->o, NULL, 0, -1, 100, d->idlechan, radius); if(d->idlechan >= 0) d->idlesound = sound; } } - else if(sound >= 0) - { + else if(sound >= 0) { d->idlechan = playsound(sound, local ? NULL : &d->o, NULL, 0, -1, -1, d->idlechan, radius); if(d->idlechan < 0) d->idlesound = -1; } } - - void removeweapons(fpsent *d) - { + void removeweapons(fpsent *d) { removebouncers(d); removeprojectiles(d); } - - void updateweapons(int curtime) - { + void updateweapons(int curtime) { updateprojectiles(curtime); pwcalcaccuracy(); if(player1->clientnum>=0 && player1->state==CS_ALIVE) shoot(player1, worldpos); // only shoot when connected to server updatebouncers(curtime); // need to do this after the player shoots so grenades don't end up inside player's BB next frame fpsent *following = followingplayer(); if(!following) following = player1; - loopv(players) - { + loopv(players) { fpsent *d = players[i]; checkattacksound(d, d==following); checkidlesound(d, d==following); } } - - void avoidweapons(ai::avoidset &obstacles, float radius) - { - loopv(projs) - { + void avoidweapons(ai::avoidset &obstacles, float radius) { + loopv(projs) { projectile &p = projs[i]; obstacles.avoidnear(NULL, p.o.z + guns[p.gun].exprad + 1, p.o, radius + guns[p.gun].exprad); } - loopv(bouncers) - { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; if(bnc.bouncetype != BNC_GRENADE) continue; obstacles.avoidnear(NULL, bnc.o.z + guns[GUN_GL].exprad + 1, bnc.o, radius + guns[GUN_GL].exprad); -- cgit v1.2.3