gamemodes 'hunt the flag' & 'keep the flag' added

git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@2485 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
ac_stef
2008-09-06 02:57:11 +00:00
parent 4e531f19f0
commit 4ee2dbaddf
37 changed files with 400 additions and 192 deletions
+2
View File
@@ -71,6 +71,8 @@ alias pf [ votemap 6 $arg1 ]
alias lss [ votemap 9 $arg1 ]
alias osok [ votemap 10 $arg1 ]
alias tosok [ votemap 11 $arg1 ]
alias htf [ votemap 13 $arg1 ]
alias ktf [ votemap 14 $arg1 ]
//--------------------- editing -------------------------------
+13 -1
View File
@@ -37,7 +37,19 @@ menudirlist "packages/maps" "cgz" "map $arg1"
newmenu maps_ctf
// Add maps to the below list to include them in the CTF map menu.
// Add maps to the below list to include them in the CTF map menu. Maps should contain flags here.
genmapitems "ac_depot ac_desert3 ac_elevation ac_keller ac_mines ac_power ac_shine ac_sunset ac_urban"
menuitem """"
menuitem "Show all maps.." [showmenu "all maps"]
newmenu maps_htf
// Add maps to the below list to include them in the HTF map menu.
genmapitems "ac_arctic ac_complex ac_depot ac_desert ac_desert2 ac_desert3 ac_elevation ac_keller ac_mines ac_power ac_scaffold ac_shine ac_snow ac_sunset ac_toxic ac_urban"
menuitem """"
menuitem "Show all maps..." [ showmenu "all maps" ]
newmenu maps_ktf
// Add maps to the below list to include them in the KTF map menu. Maps should contain flags here.
genmapitems "ac_depot ac_desert3 ac_elevation ac_keller ac_mines ac_power ac_shine ac_sunset ac_urban"
menuitem """"
menuitem "Show all maps.." [showmenu "all maps"]
+2
View File
@@ -26,6 +26,8 @@ menuitem "Deathmatch" "mode 2; showmenu maps"
menuitem "Team Survivor" "mode 4; showmenu maps"
menuitem "Survivor" "mode 3; showmenu maps"
menuitem "Capture the Flag" "mode 5; showmenu maps_ctf"
menuitem "Hunt the Flag" "mode 13; showmenu maps_htf"
menuitem "Keep the Flag" "mode 14; showmenu maps_ktf"
menuitem "Pistol Frenzy" "mode 6; showmenu maps"
menuitem "Last Swiss Standing" "mode 9; showmenu maps"
menuitem "One Shot, One Kill" "mode 10; showmenu maps"
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,3 @@
md3load tris.md3
md3skin mesh skin.jpg
md3anim flag 0 7
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.
@@ -0,0 +1,3 @@
md3load tris.md3
md3skin mesh skin.jpg
md3anim flag 0 7
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.
@@ -0,0 +1,3 @@
md3load tris.md3
md3skin mesh skin.jpg
md3anim flag 0 7
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.
@@ -0,0 +1,2 @@
mdlscale 60
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.
@@ -0,0 +1 @@
mdlscale 60
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

@@ -0,0 +1 @@
mdlscale 60
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.
+61 -38
View File
@@ -93,7 +93,7 @@ int smallerteam()
void changeteam(int team, bool respawn) // force team and respawn
{
c2sinit = false;
if(m_ctf) tryflagdrop(NULL);
if(m_flags) tryflagdrop(false);
filtertext(player1->team, team_string(team), false, MAXTEAMLEN);
if(respawn) addmsg(SV_CHANGETEAM, "r");
}
@@ -281,8 +281,8 @@ void addsleep(char *msec, char *cmd)
s.cmd = newstring(cmd);
}
void resetsleep()
{
void resetsleep()
{
loopv(sleeps) DELETEA(sleeps[i].cmd);
sleeps.setsize(0);
}
@@ -351,7 +351,7 @@ void findplayerstart(playerent *d, bool mapcenter, int arenaspawn)
loopi(arenaspawn) x = findentity(PLAYERSTART, x+1, type);
if(x >= 0) e = &ents[x];
}
else if(m_teammode || m_arena)
else if((m_teammode || m_arena) && !m_ktf) // ktf uses ffa spawns
{
loopi(r) spawncycle = findentity(PLAYERSTART, spawncycle+1, type);
if(spawncycle >= 0) e = &ents[spawncycle];
@@ -362,7 +362,7 @@ void findplayerstart(playerent *d, bool mapcenter, int arenaspawn)
loopi(r)
{
spawncycle = findentity(PLAYERSTART, spawncycle+1);
spawncycle = m_ktf && numspawn[2] > 5 ? findentity(PLAYERSTART, spawncycle+1, 100) : findentity(PLAYERSTART, spawncycle+1);
if(spawncycle < 0) continue;
float dist = nearestenemy(vec(ents[spawncycle].x, ents[spawncycle].y, ents[spawncycle].z), d->team);
if(!e || dist < 0 || (bestdist >= 0 && dist > bestdist)) { e = &ents[spawncycle]; bestdist = dist; }
@@ -419,7 +419,7 @@ bool tryrespawn()
player1->respawnoffset = lastmillis; // count again
}
int respawnmillis = player1->respawnoffset+(m_arena ? 0 : (m_ctf ? 5000 : 2000));
int respawnmillis = player1->respawnoffset+(m_arena ? 0 : (m_flags ? 5000 : 2000));
if(lastmillis>respawnmillis)
{
@@ -480,8 +480,6 @@ void dokill(playerent *pl, playerent *act, bool gib)
else outf("\f2%s %s %s", aname, death, pname);
}
if(m_ctf && pl==player1) tryflagdrop(pl!=act && isteam(act->team, pl->team));
if(gib)
{
if(pl!=act && act->weaponsel->type == GUN_SNIPER) playsound(S_HEADSHOT, SP_LOW);
@@ -556,9 +554,18 @@ entity flagdummies[2]; // in case the map does not provide flags
void preparectf(bool cleanonly=false)
{
loopi(2) flaginfos[i].flag = &flagdummies[i];
loopi(2) flaginfos[i].flagent = &flagdummies[i];
if(!cleanonly)
{
loopi(2)
{
flaginfo &f = flaginfos[i];
f.ack = false;
f.actor = NULL;
f.actor_cn = -1;
f.team = i;
f.state = m_ktf ? CTFF_IDLE : CTFF_INBASE;
}
loopv(ents)
{
entity &e = ents[i];
@@ -567,12 +574,7 @@ void preparectf(bool cleanonly=false)
e.spawned = true;
if(e.attr2>2) { conoutf("\f3invalid ctf-flag entity (%i)", i); e.attr2 = 0; }
flaginfo &f = flaginfos[e.attr2];
f.ack = false;
f.actor = NULL;
f.actor_cn = -1;
f.team = e.attr2;
f.flag = &e;
f.state = CTFF_INBASE;
f.flagent = &e;
f.originalpos.x = (float) e.x;
f.originalpos.y = (float) e.y;
f.originalpos.z = (float) e.z;
@@ -594,7 +596,7 @@ void startmap(const char *name) // called just after a map load
// End add by Rick
clearbounceents();
resetspawns();
if(m_ctf) preparectf();
if(m_flags) preparectf();
particlereset();
suicided = -1;
spawncycle = -1;
@@ -625,11 +627,8 @@ void startmap(const char *name) // called just after a map load
void suicide()
{
if(player1->state!=CS_ALIVE) return;
if(!m_mp(gamemode)) dokill(player1, player1);
else if(suicided!=player1->lifesequence)
if(player1->state == CS_ALIVE && suicided!=player1->lifesequence)
{
tryflagdrop(false);
addmsg(SV_SUICIDE, "r");
suicided = player1->lifesequence;
}
@@ -644,7 +643,7 @@ void flagmsg(int flag, int action)
flaginfo &f = flaginfos[flag];
if(!f.actor || !f.ack) return;
bool own = flag == team_int(player1->team), firstperson = f.actor == player1;
const char *teamstr = flag == team_int(player1->team) ? "your" : "the enemy";
const char *teamstr = m_ktf ? "the" : own ? "your" : "the enemy";
switch(action)
{
@@ -653,53 +652,77 @@ void flagmsg(int flag, int action)
playsound(S_FLAGPICKUP, SP_HIGH);
if(firstperson)
{
conoutf("\f2you got the enemy flag");
musicsuggest(M_FLAGGRAB, 90*1000, true);
conoutf("\f2you got the %sflag", m_ctf ? "enemy " : "");
musicsuggest(M_FLAGGRAB, m_ctf ? 90*1000 : 900*1000, true);
}
else conoutf("\f2%s got %s flag", colorname(f.actor), teamstr);
break;
}
case SV_FLAGDROP:
case SV_FLAGLOST:
{
const char *droplost = action == SV_FLAGLOST ? "lost" : "dropped";
playsound(S_FLAGDROP, SP_HIGH);
if(firstperson)
{
conoutf("\f2you lost the flag");
conoutf("\f2you %s the flag", droplost);
musicfadeout(M_FLAGGRAB);
}
else conoutf("\f2%s lost %s flag", colorname(f.actor), teamstr);
else conoutf("\f2%s %s %s flag", colorname(f.actor), droplost, teamstr);
break;
}
case SV_FLAGRETURN:
{
playsound(S_FLAGRETURN, SP_HIGH);
if(firstperson) conoutf("\f2you returned your flag");
else conoutf("\f2%s returned %s flag", colorname(f.actor), teamstr);
if(m_ctf)
{
if(firstperson) conoutf("\f2you returned your flag");
else conoutf("\f2%s returned %s flag", colorname(f.actor), teamstr);
}
else if(m_htf)
{
conoutf("\f2%s failed to score (own team flag not taken)", firstperson ? "you" : colorname(f.actor));
}
else
{ //ktf
conoutf("\f2%s lost the flag", firstperson ? "you" : colorname(f.actor));
if(firstperson) musicfadeout(M_FLAGGRAB);
}
break;
}
case SV_FLAGSCORE:
{
playsound(S_FLAGSCORE, SP_HIGH);
if(firstperson)
playsound(m_ktf ? S_VOTEPASS : S_FLAGSCORE, SP_HIGH); // need better ktf sound here
if(m_ktf)
{
const char *ta = firstperson ? "you have" : colorname(f.actor);
const char *tb = firstperson ? "" : " has";
int m = f.stolentime / 60;
if(m)
conoutf("%s%s been keeping the flag for %d minute%s %d seconds now", ta, tb, m, m == 1 ? "" : "s", f.stolentime % 60);
else
conoutf("%s%s been keeping the flag for %d seconds now", ta, tb, f.stolentime);
}
else if(firstperson)
{
conoutf("\f2you scored");
addmsg(SV_FLAGS, "ri", ++player1->flagscore);
musicfadeout(M_FLAGGRAB);
if(m_ctf) musicfadeout(M_FLAGGRAB);
}
else conoutf("\f2%s scored for %s team", colorname(f.actor), (own ? "the enemy" : "your"));
break;
}
case SV_FLAGRESET:
{
playsound(S_FLAGRETURN, SP_HIGH);
conoutf("the server reset the flag");
break;
}
case SV_FLAGRESET:
{
playsound(S_FLAGRETURN, SP_HIGH);
conoutf("the server reset the flag");
if(firstperson) musicfadeout(M_FLAGGRAB);
break;
}
default: break;
}
}
void dropflag() { tryflagdrop(false); }
void dropflag() { tryflagdrop(true); }
COMMAND(dropflag, ARG_NONE);
char *votestring(int type, char *arg1, char *arg2)
+18 -12
View File
@@ -268,7 +268,7 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
getstring(text, p);
filtertext(d->team, text, false, MAXTEAMLEN);
setskin(d, getint(p));
if(m_ctf) loopi(2)
if(m_flags) loopi(2)
{
flaginfo &f = flaginfos[i];
if(!f.actor) f.actor = getclient(f.actor_cn);
@@ -539,37 +539,43 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
flaginfo &f = flaginfos[flag];
f.state = getint(p);
int action = getint(p);
int actor = f.state==CTFF_STOLEN || action==SV_FLAGRETURN ? getint(p) : -1;
switch(f.state)
{
case CTFF_STOLEN:
{
flagstolen(flag, action, getint(p));
if(action==SV_FLAGSCORE) f.stolentime = getint(p);
flagstolen(flag, action, actor);
break;
}
case CTFF_DROPPED:
{
short x = (ushort) (getint(p)/DMF);
short y = (ushort) (getint(p)/DMF);
short z = ((ushort) (getint(p)/DMF))-((short)player1->eyeheight); // correct z offset, assumes all players do have the same eyeheight
flagdropped(flag, action, x, y, z);
if(action != SV_FLAGRETURN)
{
short x = (ushort) (getint(p)/DMF);
short y = (ushort) (getint(p)/DMF);
short z = ((ushort) (getint(p)/DMF))-((short)player1->eyeheight); // correct z offset, assumes all players do have the same eyeheight
flagdropped(flag, action, x, y, z);
}
break;
}
case CTFF_INBASE:
{
int actor = -1;
if(action == SV_FLAGRETURN) actor = getint(p);
flaginbase(flag, action, actor);
break;
}
case CTFF_IDLE:
f.flagent->spawned = false;
f.ack = true;
break;
}
break;
}
case SV_FLAGS:
{
if(!d) return;
d->flagscore = getint(p);
int fcn = getint(p), flags = getint(p);
playerent *p = (fcn == getclientnum() ? player1 : getclient(fcn));
if(p) p->flagscore = flags;
break;
}
+2 -2
View File
@@ -424,7 +424,7 @@ bool nickcomplete(char *s)
char *cp = s;
for(int i = strlen(s) - 2; i > 0; i--)
if (s[i] == ' ') { cp = s + i + 1; break; }
if(s[i] == ' ') { cp = s + i + 1; break; }
if(!completesize) { completesize = (int)strlen(cp); completeidx = 0; }
int idx = 0;
@@ -460,7 +460,7 @@ void commandcomplete(char *s)
if(!s[1]) return;
char *cp = s;
for(int i = strlen(s) - 2; i > 0; i--)
if (s[i] == ';' || s[i] == ' ') { cp = s + i; break; }
if(s[i] == ';' || s[i] == ' ') { cp = s + i; break; }
if(!completesize)
{
completesize = (int)strlen(cp)-1;
+89 -57
View File
@@ -8,15 +8,15 @@ const int physent::crouchtime = 200;
vector<entity> ents;
const char *entnames[] =
{
{
"none?", "light", "playerstart",
"clips", "ammobox","grenades",
"health", "armour", "akimbo",
"mapmodel", "trigger",
"mapmodel", "trigger",
"ladder", "ctf-flag", "sound", "?", "?",
};
const char *entmdlnames[] =
const char *entmdlnames[] =
{
"pickups/pistolclips", "pickups/ammobox", "pickups/nades", "pickups/health", "pickups/kevlar", "pickups/akimbo",
};
@@ -28,13 +28,13 @@ void renderent(entity &e, const char *mdlname, float z, float yaw, int anim = AN
void renderentities()
{
if(editmode)
if(editmode)
{
loopv(ents)
{
entity &e = ents[i];
if(e.type==NOTUSED) continue;
vec v(e.x, e.y, e.z);
vec v(e.x, e.y, e.z);
particle_splash(2, 2, 40, v);
}
}
@@ -47,21 +47,6 @@ void renderentities()
if(!&mmi) continue;
rendermodel(mmi.name, ANIM_MAPMODEL|ANIM_LOOP, e.attr4, mmi.rad ? (float)mmi.rad : 1.1f, vec(e.x, e.y, (float)S(e.x, e.y)->floor+mmi.zoff+e.attr3), (float)((e.attr1+7)-(e.attr1+7)%15), 0, 10.0f);
}
else if(e.type==CTF_FLAG && (m_ctf || editmode))
{
flaginfo &f = flaginfos[e.attr2];
if(f.state==CTFF_STOLEN)
{
if(!f.actor || f.actor == player1) continue;
s_sprintfd(path)("pickups/flags/small_%s", team_string(e.attr2));
rendermodel(path, ANIM_FLAG|ANIM_START, 0, 1.1f, vec(f.actor->o).add(vec(0, 0, 0.3f+(sinf(lastmillis/100.0f)+1)/10)), lastmillis/2.5f, 0, 120.0f);
}
else
{
s_sprintfd(path)("pickups/flags/%s", team_string(e.attr2));
rendermodel(path, ANIM_FLAG|ANIM_LOOP, 0, 4, vec(e.x, e.y, f.state==CTFF_INBASE ? (float)S(e.x, e.y)->floor : e.z), (float)((e.attr1+7)-(e.attr1+7)%15), 0, 120.0f);
}
}
else if(isitem(e.type))
{
if((!OUTBORD(e.x, e.y) && e.spawned) | editmode)
@@ -70,6 +55,30 @@ void renderentities()
}
}
}
if(m_flags || editmode) loopi(2)
{
flaginfo &f = flaginfos[i];
switch(f.state)
{
case CTFF_STOLEN:
if(f.actor && f.actor != player1)
{
s_sprintfd(path)("pickups/flags/small_%s%s", m_ktf ? "" : team_string(i), m_htf ? "_htf" : m_ktf ? "ktf" : "");
rendermodel(path, ANIM_FLAG|ANIM_START, 0, 1.1f, vec(f.actor->o).add(vec(0, 0, 0.3f+(sinf(lastmillis/100.0f)+1)/10)), lastmillis/2.5f, 0, 120.0f);
}
break;
case CTFF_INBASE:
case CTFF_DROPPED:
{
entity &e = *f.flagent;
s_sprintfd(path)("pickups/flags/%s%s", m_ktf ? "" : team_string(i), m_htf ? "_htf" : m_ktf ? "ktf" : "");
rendermodel(path, ANIM_FLAG|ANIM_LOOP, 0, 4, vec(e.x, e.y, f.state==CTFF_INBASE ? (float)S(e.x, e.y)->floor : e.z), (float)((e.attr1+7)-(e.attr1+7)%15), 0, 120.0f);
break;
}
case CTFF_IDLE:
break;
}
}
}
// these two functions are called when the server acknowledges that you really
@@ -129,13 +138,33 @@ void trypickup(int n, playerent *d)
flaginfo &f = flaginfos[flag];
flaginfo &of = flaginfos[team_opposite(flag)];
if(f.state == CTFF_STOLEN) break;
bool own = flag == team_int(d->team);
if(flag == team_int(d->team)) // it's the own flag
if(m_ctf)
{
if(f.state == CTFF_DROPPED) flagreturn();
else if(f.state == CTFF_INBASE && of.state == CTFF_STOLEN && of.actor == d && of.ack) flagscore();
if(own) // it's the own flag
{
if(f.state == CTFF_DROPPED) flagreturn(flag);
else if(f.state == CTFF_INBASE && of.state == CTFF_STOLEN && of.actor == d && of.ack) flagscore(of.team);
}
else flagpickup(flag);
}
else if(m_htf)
{
if(own)
{
flagpickup(flag);
}
else
{
if(f.state == CTFF_DROPPED) flagscore(f.team); // may not count!
}
}
else if(m_ktf)
{
if(f.state == CTFF_IDLE) break;
flagpickup(flag);
}
else flagpickup();
}
break;
}
@@ -160,7 +189,7 @@ void checkitems(playerent *d)
if(dist1<1.5f && dist2<e.attr1) trypickup(i, d);
continue;
}
if(!e.spawned) continue;
if(OUTBORD(e.x, e.y)) continue;
@@ -189,7 +218,7 @@ void putitems(ucharbuf &p) // puts items in network stream and also s
}
}
void resetspawns()
void resetspawns()
{
loopv(ents) ents[i].spawned = false;
if(m_noitemsnade || m_pistol)
@@ -229,10 +258,10 @@ bool intersect(entity *e, vec &from, vec &to, vec *end) // if lineseg hits entit
{
mapmodelinfo &mmi = getmminfo(e->attr2);
if(!&mmi || !mmi.h) return false;
float lo = (float)(S(e->x, e->y)->floor+mmi.zoff+e->attr3);
float hi = lo+mmi.h;
vec v = to, w(e->x, e->y, lo + (fabs(hi-lo)/2.0f)), *p;
vec v = to, w(e->x, e->y, lo + (fabs(hi-lo)/2.0f)), *p;
v.sub(from);
w.sub(from);
float c1 = w.dot(v);
@@ -250,7 +279,7 @@ bool intersect(entity *e, vec &from, vec &to, vec *end) // if lineseg hits entit
p = &v;
}
}
if (p->x <= e->x+mmi.rad
&& p->x >= e->x-mmi.rad
&& p->y <= e->y+mmi.rad
@@ -269,11 +298,11 @@ bool intersect(entity *e, vec &from, vec &to, vec *end) // if lineseg hits entit
int flagdropmillis = 0;
void flagpickup()
void flagpickup(int fln)
{
if(flagdropmillis && flagdropmillis>lastmillis) return;
flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
f.flag->spawned = false;
flaginfo &f = flaginfos[fln];
f.flagent->spawned = false;
f.state = CTFF_STOLEN;
f.actor = player1; // do this although we don't know if we picked the flag to avoid getting it after a possible respawn
f.actor_cn = getclientnum();
@@ -281,32 +310,35 @@ void flagpickup()
addmsg(SV_FLAGPICKUP, "ri", f.team);
}
void tryflagdrop(bool reset)
void tryflagdrop(bool manual)
{
flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
if(f.state==CTFF_STOLEN && f.actor==player1)
loopi(2)
{
f.flag->spawned = false;
f.state = CTFF_DROPPED;
f.ack = false;
flagdropmillis = lastmillis+3000;
addmsg(reset ? SV_FLAGRESET : SV_FLAGDROP, "ri", f.team);
flaginfo &f = flaginfos[i];
if(f.state==CTFF_STOLEN && f.actor==player1)
{
f.flagent->spawned = false;
f.state = CTFF_DROPPED;
f.ack = false;
flagdropmillis = lastmillis+3000;
addmsg(manual ? SV_FLAGDROP : SV_FLAGLOST, "ri", f.team);
}
}
}
void flagreturn()
void flagreturn(int fln)
{
flaginfo &f = flaginfos[team_int(player1->team)];
f.flag->spawned = false;
flaginfo &f = flaginfos[fln];
f.flagent->spawned = false;
f.ack = false;
addmsg(SV_FLAGRETURN, "ri", f.team);
}
void flagscore()
void flagscore(int fln)
{
flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
flaginfo &f = flaginfos[fln];
f.ack = false;
addmsg(SV_FLAGSCORE, "ri", f.team);
addmsg(SV_FLAGSCORE, "ri", fln);
}
// flag ent actions from the net
@@ -318,7 +350,7 @@ void flagstolen(int flag, int action, int act)
flaginfo &f = flaginfos[flag];
f.actor = actor;
f.actor_cn = act;
f.flag->spawned = false;
f.flagent->spawned = false;
f.ack = true;
flagmsg(flag, action);
}
@@ -334,7 +366,7 @@ void flagdropped(int flag, int action, short x, short y, short z)
p.o.z = z;
p.vel.z = -0.8f;
p.aboveeye = p.eyeheight = p.radius = 0.0f;
bool oldcancollide = false;
if(f.actor)
{
@@ -348,11 +380,11 @@ void flagdropped(int flag, int action, short x, short y, short z)
}
if(f.actor) f.actor->cancollide = oldcancollide; // restore settings
f.flag->x = (short)round(p.o.x);
f.flag->y = (short)round(p.o.y);
f.flag->z = (short)round(p.o.z);
if(f.flag->z < hdr.waterlevel) f.flag->z = (short) hdr.waterlevel;
f.flag->spawned = true;
f.flagent->x = (short)round(p.o.x);
f.flagent->y = (short)round(p.o.y);
f.flagent->z = (short)round(p.o.z);
if(f.flagent->z < hdr.waterlevel) f.flagent->z = (short) hdr.waterlevel;
f.flagent->spawned = true;
f.ack = true;
flagmsg(flag, action);
}
@@ -362,10 +394,10 @@ void flaginbase(int flag, int action, int act)
flaginfo &f = flaginfos[flag];
playerent *actor = act == getclientnum() ? player1 : getclient(act);
if(actor) { f.actor = actor; f.actor_cn = act; }
f.flag->x = (ushort) f.originalpos.x;
f.flag->y = (ushort) f.originalpos.y;
f.flag->z = (ushort) f.originalpos.z;
f.flag->spawned = true;
f.flagent->x = (ushort) f.originalpos.x;
f.flagent->y = (ushort) f.originalpos.y;
f.flagent->z = (ushort) f.originalpos.z;
f.flagent->spawned = true;
f.ack = true;
flagmsg(flag, action);
}
+4 -3
View File
@@ -465,18 +465,19 @@ struct botent : playerent
int deaths() { return lifesequence; }
};
enum { CTFF_INBASE = 0, CTFF_STOLEN, CTFF_DROPPED };
enum { CTFF_INBASE = 0, CTFF_STOLEN, CTFF_DROPPED, CTFF_IDLE };
struct flaginfo
{
int team;
entity *flag;
entity *flagent;
int actor_cn;
playerent *actor;
vec originalpos;
int state; // one of CTFF_*
bool ack;
flaginfo() : flag(0), actor(0), state(CTFF_INBASE), ack(false) {}
int stolentime;
flaginfo() : flagent(0), actor(0), state(CTFF_INBASE), ack(false) {}
};
enum { BT_NONE, BT_NADE, BT_GIB };
+3 -3
View File
@@ -97,13 +97,13 @@ const char *modefullnames[] =
{
"team deathmatch", "coopedit", "deathmatch", "survivor",
"team survivor", "ctf", "pistol frenzy", "bot team deathmatch", "bot deathmatch", "last swiss standing",
"one shot, one kill", "team one shot, one kill", "bot one shot, one kill"
"one shot, one kill", "team one shot, one kill", "bot one shot, one kill", "hunt the flag", "keep the flag"
};
const char *modeacronymnames[] =
{
"TDM", "coop", "DM", "SURV", "TSURV", "CTF", "PF", "BTDM", "BDM", "LSS",
"OSOK", "TOSOK", "BOSOK"
"OSOK", "TOSOK", "BOSOK", "HTF", "CTF"
};
const char *voteerrors[] = { "voting is currently disabled", "there is already a vote pending", "already voted", "can't vote that often", "this vote is not allowed in the current environment (singleplayer/multiplayer)", "no permission", "invalid vote" };
@@ -125,7 +125,7 @@ char msgsizesl[] = // size inclusive message token, 0 for variable
SV_EDITMODE, 2, SV_EDITH, 7, SV_EDITT, 7, SV_EDITS, 6, SV_EDITD, 6, SV_EDITE, 6,
SV_SENDMAP, 0, SV_RECVMAP, 1, SV_SERVMSG, 0, SV_ITEMLIST, 0, SV_WEAPCHANGE, 2, SV_PRIMARYWEAP, 2,
SV_MODELSKIN, 2,
SV_FLAGPICKUP, 2, SV_FLAGDROP, 2, SV_FLAGRETURN, 2, SV_FLAGSCORE, 2, SV_FLAGRESET, 2, SV_FLAGINFO, 0, SV_FLAGS, 2,
SV_FLAGPICKUP, 2, SV_FLAGDROP, 2, SV_FLAGLOST, 2, SV_FLAGRETURN, 2, SV_FLAGSCORE, 2, SV_FLAGRESET, 2, SV_FLAGINFO, 0, SV_FLAGS, 3,
SV_ARENAWIN, 2,
SV_SETADMIN, 0, SV_SERVOPINFO, 3,
SV_CALLVOTE, 0, SV_CALLVOTESUC, 1, SV_CALLVOTEERR, 2, SV_VOTE, 2, SV_VOTERESULT, 2,
+10 -5
View File
@@ -23,7 +23,7 @@ enum
SV_EDITMODE, SV_EDITH, SV_EDITT, SV_EDITS, SV_EDITD, SV_EDITE,
SV_SENDMAP, SV_RECVMAP, SV_SERVMSG, SV_ITEMLIST, SV_WEAPCHANGE, SV_PRIMARYWEAP,
SV_MODELSKIN,
SV_FLAGPICKUP, SV_FLAGDROP, SV_FLAGRETURN, SV_FLAGSCORE, SV_FLAGRESET, SV_FLAGINFO, SV_FLAGS,
SV_FLAGPICKUP, SV_FLAGDROP, SV_FLAGLOST, SV_FLAGRETURN, SV_FLAGSCORE, SV_FLAGRESET, SV_FLAGINFO, SV_FLAGS,
SV_ARENAWIN,
SV_SETADMIN, SV_SERVOPINFO,
SV_CALLVOTE, SV_CALLVOTESUC, SV_CALLVOTEERR, SV_VOTE, SV_VOTERESULT,
@@ -69,11 +69,13 @@ enum
GMODE_CTF,
GMODE_PISTOLFRENZY,
GMODE_BOTTEAMDEATHMATCH,
GMODE_GOTDEATHMATCH,
GMODE_BOTDEATHMATCH,
GMODE_LASTSWISSSTANDING,
GMODE_ONESHOTONEKILL,
GMODE_TEAMONESHOTONEKILL,
GMODE_BOTONESHOTONEKILL
GMODE_BOTONESHOTONEKILL,
GMODE_HUNTTHEFLAG, // 13
GMODE_KEEPTHEFLAG
};
#define m_lms (gamemode==3 || gamemode==4)
@@ -81,6 +83,8 @@ enum
#define m_pistol (gamemode==6)
#define m_lss (gamemode==9)
#define m_osok (gamemode>=10 && gamemode<=12)
#define m_htf (gamemode==13)
#define m_ktf (gamemode==14)
#define m_noitems (m_lms || m_osok)
#define m_noitemsnade (m_lss)
@@ -88,9 +92,10 @@ enum
#define m_noprimary (m_pistol || m_lss)
#define m_noguns (m_nopistol && m_noprimary)
#define m_arena (m_lms || m_lss || m_osok)
#define m_teammode (gamemode==0 || gamemode==4 || gamemode==5 || gamemode==7 || gamemode==11)
#define m_teammode (gamemode==0 || gamemode==4 || gamemode==5 || gamemode==7 || gamemode==11 || gamemode==13 || gamemode==14)
#define m_tarena (m_arena && m_teammode)
#define m_botmode (gamemode==7 || gamemode == 8 || gamemode==12)
#define m_valid(mode) (((mode)>=0 && (mode)<=12) || (mode) == -3)
#define m_valid(mode) (((mode)>=0 && (mode)<=14) || (mode) == -3)
#define m_mp(mode) (m_valid(mode) && (mode)!=7 && (mode)!=8 && (mode)!=12)
#define m_demo (gamemode==-3)
#define m_flags (m_ctf || m_htf || m_ktf)
+4 -4
View File
@@ -302,10 +302,10 @@ extern void setskin(playerent *pl, uint skin);
extern void callvote(int type, char *arg1 = NULL, char *arg2 = NULL);
extern void resetsleep();
//game mode extras
extern void flagpickup();
extern void tryflagdrop(bool reset = false);
extern void flagreturn();
extern void flagscore();
extern void flagpickup(int fln);
extern void tryflagdrop(bool manual = false);
extern void flagreturn(int fln);
extern void flagscore(int fln);
extern void flagstolen(int flag, int action, int act);
extern void flagdropped(int flag, int action, short x, short y, short z);
extern void flaginbase(int flag, int action, int act);
+30 -12
View File
@@ -34,9 +34,22 @@ void drawradaricon(float x, float y, float s, int col, int row)
void drawctficon(float x, float y, float s, int col, int row, float ts)
{
static Texture *tex = NULL;
if(!tex) tex = textureload("packages/misc/ctficons.png");
if(tex) drawicon(tex, x, y, s, col, row, ts);
static Texture *ctftex = NULL, *htftex = NULL, *ktftex = NULL;
if(!ctftex) ctftex = textureload("packages/misc/ctficons.png");
if(!htftex) htftex = textureload("packages/misc/htficons.png");
if(!ktftex) ktftex = textureload("packages/misc/ktficons.png");
if(m_htf)
{
if(htftex) drawicon(htftex, x, y, s, col, row, ts);
}
else if(m_ktf)
{
if(ktftex) drawicon(ktftex, x, y, s, col, row, ts);
}
else
{
if(ctftex) drawicon(ctftex, x, y, s, col, row, ts);
}
}
void drawvoteicon(float x, float y, int col, int row, bool noblend)
@@ -332,22 +345,26 @@ void drawradar(playerent *p, int w, int h)
if(!pl || pl==p || !isteam(p->team, pl->team) || !insideradar(centerpos, res/2, pl->o)) continue;
drawradarent(pl->o.x*coordtrans, pl->o.y*coordtrans, pl->yaw, pl->state==CS_ALIVE ? (isattacking(pl) ? 2 : 0) : 1, team_int(pl->team), iconsize, isattacking(pl), colorname(pl));
}
if(m_ctf)
if(m_flags)
{
glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis / 100.0f) + 1.0f) / 2.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
loopi(2) // flag items
{
flaginfo &f = flaginfos[i];
entity *e = f.flag;
entity *e = f.flagent;
if(!e) continue;
float yaw = showmap ? 0 : p->yaw;
if(m_ktf && f.state == CTFF_IDLE) continue;
if(f.state==CTFF_STOLEN)
{
if(f.actor && i != team_int(p->team) && insideradar(centerpos, res/2, f.actor->o))
drawradarent(f.actor->o.x*coordtrans+iconsize/2, f.actor->o.y*coordtrans+iconsize/2, yaw, 3, f.team, iconsize, true); // draw near flag thief
bool tm = i != team_int(p->team);
if(m_htf) tm = !tm;
else if(m_ktf) tm = true;
if(f.actor && tm && insideradar(centerpos, res/2, f.actor->o))
drawradarent(f.actor->o.x*coordtrans+iconsize/2, f.actor->o.y*coordtrans+iconsize/2, yaw, 3, m_ktf ? 2 : f.team, iconsize, true); // draw near flag thief
}
else if(insideradar(centerpos, res/2, vec(e->x, e->y, centerpos.z))) drawradarent(e->x*coordtrans, e->y*coordtrans, yaw, 3, f.team, iconsize, false); // draw on entitiy pos
else if(insideradar(centerpos, res/2, vec(e->x, e->y, centerpos.z))) drawradarent(e->x*coordtrans, e->y*coordtrans, yaw, 3, m_ktf ? 2 : f.team, iconsize, false); // draw on entitiy pos
}
}
@@ -512,7 +529,7 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
if(p->weaponsel && p->weaponsel->type>=GUN_KNIFE && p->weaponsel->type<NUMGUNS) p->weaponsel->renderstats(); // flowtron
}
if(m_ctf && !hidectfhud)
if(m_flags && !hidectfhud)
{
glLoadIdentity();
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
@@ -526,12 +543,13 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
}
// big flag-stolen icon
flaginfo &f = flaginfos[team_opposite(team_int(p->team))];
if(f.state==CTFF_STOLEN && f.actor == p && f.ack)
int ft = 0;
if((flaginfos[0].state==CTFF_STOLEN && flaginfos[0].actor == p && flaginfos[0].ack) ||
(flaginfos[1].state==CTFF_STOLEN && flaginfos[1].actor == p && flaginfos[1].ack && ++ft))
{
glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis/100.0f)+1.0f) / 2.0f);
glEnable(GL_BLEND);
drawctficon(VIRTW-225-10, VIRTH*5/8, 225, team_opposite(team_int(p->team)), 1, 1/2.0f);
drawctficon(VIRTW-225-10, VIRTH*5/8, 225, m_ktf ? team_int(p->team) : ft, 1, 1/2.0f);
glDisable(GL_BLEND);
}
}
+4 -4
View File
@@ -7,7 +7,7 @@ void *scoremenu = NULL, *teammenu = NULL, *ctfmenu = NULL;
void showscores(bool on)
{
menuset(on ? (m_ctf ? ctfmenu : (m_teammode ? teammenu : scoremenu)) : NULL);
menuset(on ? (m_flags ? ctfmenu : (m_teammode ? teammenu : scoremenu)) : NULL);
}
COMMAND(showscores, ARG_DOWN);
@@ -33,7 +33,7 @@ struct teamscore
teammembers.add(d);
frags += d->frags;
deaths += d->deaths;
if(m_ctf) flagscore += d->flagscore;
if(m_flags) flagscore += d->flagscore;
}
};
@@ -92,7 +92,7 @@ void renderscore(void *menu, playerent *d)
string &s = line.s;
scoreratio sr;
sr.calc(d->frags, d->deaths);
if(m_ctf) s_sprintf(s)("%d\t%d\t%d\t%.*f\t%s\t%s\t%d\t%s%s", d->flagscore, d->frags, d->deaths, sr.precision, sr.ratio, d->state==CS_LAGGED ? "LAG" : lag, colorping(d->ping), d->clientnum, status, colorname(d));
if(m_flags) s_sprintf(s)("%d\t%d\t%d\t%.*f\t%s\t%s\t%d\t%s%s", d->flagscore, d->frags, d->deaths, sr.precision, sr.ratio, d->state==CS_LAGGED ? "LAG" : lag, colorping(d->ping), d->clientnum, status, colorname(d));
else if(m_teammode) s_sprintf(s)("%d\t%d\t%.*f\t%s\t%s\t%d\t%s%s", d->frags, d->deaths, sr.precision, sr.ratio, d->state==CS_LAGGED ? "LAG" : lag, colorping(d->ping), d->clientnum, status, colorname(d));
else s_sprintf(s)("%d\t%d\t%.*f\t%s\t%s\t%d\t%s%s", d->frags, d->deaths, sr.precision, sr.ratio, d->state==CS_LAGGED ? "LAG" : lag, colorping(d->ping), d->clientnum, status, colorname(d));
}
@@ -108,7 +108,7 @@ void renderteamscore(void *menu, teamscore *t)
s_sprintfd(plrs)("(%d %s)", t->teammembers.length(), t->teammembers.length() == 1 ? "player" : "players");
scoreratio sr;
sr.calc(t->frags, t->deaths);
if(m_ctf) s_sprintf(line.s)("%d\t%d\t%d\t%.*f\t\t\t\t%s\t\t%s", t->flagscore, t->frags, t->deaths, sr.precision, sr.ratio, team_string(t->team), plrs);
if(m_flags) s_sprintf(line.s)("%d\t%d\t%d\t%.*f\t\t\t\t%s\t\t%s", t->flagscore, t->frags, t->deaths, sr.precision, sr.ratio, team_string(t->team), plrs);
else if(m_teammode) s_sprintf(line.s)("%d\t%d\t%.*f\t\t\t\t%s\t\t%s", t->frags, t->deaths, sr.precision, sr.ratio, team_string(t->team), plrs);
static color teamcolors[2] = { color(1.0f, 0, 0, 0.2f), color(0, 0, 1.0f, 0.2f) };
line.bgcolor = &teamcolors[t->team];
+140 -39
View File
@@ -820,6 +820,7 @@ struct sflaginfo
int actor_cn;
float pos[3];
int lastupdate;
int stolentime;
} sflaginfos[2];
void sendflaginfo(int flag, int action, int cn = -1)
@@ -833,6 +834,7 @@ void sendflaginfo(int flag, int action, int cn = -1)
putint(p, action);
if(f.state==CTFF_STOLEN || action==SV_FLAGRETURN) putint(p, f.actor_cn);
else if(f.state==CTFF_DROPPED) loopi(3) putint(p, int(f.pos[i]*DMF));
if(f.state==CTFF_STOLEN && action==SV_FLAGSCORE) putint(p, (gamemillis - f.stolentime) / 1000);
enet_packet_resize(packet, p.length());
sendpacket(cn, 1, packet);
if(packet->referenceCount==0) enet_packet_destroy(packet);
@@ -842,7 +844,8 @@ void flagaction(int flag, int action, int sender)
{
if(!valid_flag(flag)) return;
sflaginfo &f = sflaginfos[flag];
sflaginfo &of = sflaginfos[team_opposite(flag)];
bool ktf_switch = false;
switch(action)
{
case SV_FLAGPICKUP:
@@ -850,15 +853,18 @@ void flagaction(int flag, int action, int sender)
if(f.state == CTFF_STOLEN) return;
f.state = CTFF_STOLEN;
f.actor_cn = sender;
f.stolentime = gamemillis;
logger->writeline(log::info,"[%s] %s stole the flag", clients[sender]->hostname, clients[sender]->name);
break;
}
case SV_FLAGDROP:
case SV_FLAGLOST:
{
if(f.state!=CTFF_STOLEN || (sender != -1 && f.actor_cn != sender)) return;
ktf_switch = true;
f.state = CTFF_DROPPED;
loopi(3) f.pos[i] = clients[sender]->state.o[i];
logger->writeline(log::info,"[%s] %s dropped the flag", clients[sender]->hostname, clients[sender]->name);
loopi(3) f.pos[i] = clients[f.actor_cn]->state.o[i];
logger->writeline(log::info,"[%s] %s %s the flag", clients[f.actor_cn]->hostname, clients[f.actor_cn]->name, action == SV_FLAGLOST ? "lost" : "dropped");
break;
}
case SV_FLAGRETURN:
@@ -872,19 +878,50 @@ void flagaction(int flag, int action, int sender)
case SV_FLAGRESET:
{
if(sender != -1 && f.actor_cn != sender) return;
ktf_switch = true;
f.state = CTFF_INBASE;
logger->writeline(log::info,"The server reset the flag");
break;
}
case SV_FLAGSCORE:
{
if(f.state != CTFF_STOLEN) return;
f.state = CTFF_INBASE;
logger->writeline(log::info, "[%s] %s scored with the flag for %s", clients[sender]->hostname, clients[sender]->name, clients[sender]->team);
bool score = true;
if(m_ctf)
{ //ctf f: actor carrying, of: unstolen own
if(f.state != CTFF_STOLEN || f.actor_cn != sender || of.state != CTFF_INBASE) return;
f.state = CTFF_INBASE;
}
else if(m_htf)
{ //htf of: own team carrying, f: other team dropped
if(f.state != CTFF_DROPPED) return;
f.state = CTFF_INBASE;
if(of.state != CTFF_STOLEN)
{
action = SV_FLAGRETURN;
score = false; // sry, fail
}
}
if(score)
{
clients[sender]->state.flagscore += 1;
sendf(-1, 1, "riii", SV_FLAGS, sender, clients[sender]->state.flagscore);
logger->writeline(log::info, "[%s] %s scored with the flag for %s, new score %d", clients[sender]->hostname, clients[sender]->name, clients[sender]->team, clients[sender]->state.flagscore);
}
else
{
logger->writeline(log::info, "[%s] %s failed to score", clients[sender]->hostname, clients[sender]->name);
}
break;
}
default: return;
}
if(m_ktf && ktf_switch)
{
f.state = CTFF_IDLE;
of.state = CTFF_INBASE;
sendflaginfo(team_opposite(flag), SV_FLAGRETURN);
action = 0;
}
f.lastupdate = gamemillis;
sendflaginfo(flag, action);
@@ -892,14 +929,54 @@ void flagaction(int flag, int action, int sender)
void ctfreset()
{
int idleflag = m_ktf ? rnd(2) : -1;
loopi(2)
{
sflaginfos[i].actor_cn = 0;
sflaginfos[i].state = CTFF_INBASE;
sflaginfos[i].state = i == idleflag ? CTFF_IDLE : CTFF_INBASE;
sflaginfos[i].lastupdate = -1;
}
}
void htf_forceflag(int flag)
{
sflaginfo &f = sflaginfos[flag];
int besthealth = 0, numbesthealth = 0;
loopv(clients) if(clients[i]->type!=ST_EMPTY)
{
if(clients[i]->state.state == CS_ALIVE && team_int(clients[i]->team) == flag)
{
if(clients[i]->state.health == besthealth)
numbesthealth++;
else
{
if(clients[i]->state.health > besthealth)
{
besthealth = clients[i]->state.health;
numbesthealth = 1;
}
}
}
}
if(numbesthealth)
{
int pick = rnd(numbesthealth);
loopv(clients) if(clients[i]->type!=ST_EMPTY)
{
if(clients[i]->state.state == CS_ALIVE && team_int(clients[i]->team) == flag && --pick < 0)
{
f.state = CTFF_STOLEN;
f.actor_cn = i;
sendflaginfo(flag, SV_FLAGPICKUP);
logger->writeline(log::info,"[%s] %s got forced to pickup the flag", clients[i]->hostname, clients[i]->name);
break;
}
}
}
f.lastupdate = gamemillis;
}
bool canspawn(client *c, bool connecting = false)
{
if(m_arena)
@@ -1015,7 +1092,7 @@ void arenacheck()
if(!dead) return;
sendf(-1, 1, "ri2", SV_ARENAWIN, !alive ? -1 : alive->clientnum);
arenaround = gamemillis+5000;
if (autoteam && m_teammode) refillteams(true);
if(autoteam && m_teammode) refillteams(true);
}
#define SPAMREPEATINTERVAL 15 // detect doubled lines only if interval < 15 seconds
@@ -1141,7 +1218,7 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib,
{
clientstate &ts = target->state;
ts.dodamage(damage);
actor->state.damage += damage;
actor->state.damage += damage != 1000 ? damage : 0;
sendf(-1, 1, "ri6", gib ? SV_GIBDAMAGE : SV_DAMAGE, target->clientnum, actor->clientnum, damage, ts.armour, ts.health);
if(target!=actor && !hitpush.iszero())
{
@@ -1152,6 +1229,9 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib,
}
if(ts.health<=0)
{
int targethasflag = -1;
bool flagtk = false, suic = false;
loopi(2) { if(sflaginfos[i].state == CTFF_STOLEN && sflaginfos[i].actor_cn == target->clientnum) targethasflag = i; }
target->state.deaths++;
if(target!=actor)
{
@@ -1160,14 +1240,29 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib,
{
actor->state.frags--;
actor->state.teamkills++;
flagtk = true;
}
}
else actor->state.frags--;
else
{ // suicide
actor->state.frags--;
flagtk = true;
suic = true;
}
sendf(-1, 1, "ri4", gib ? SV_GIBDIED : SV_DIED, target->clientnum, actor->clientnum, actor->state.frags);
if(flagtk && (m_htf || m_ktf) && targethasflag >= 0)
{
actor->state.flagscore--;
sendf(-1, 1, "riii", SV_FLAGS, actor->clientnum, actor->state.flagscore);
}
target->position.setsizenodelete(0);
ts.state = CS_DEAD;
ts.lastdeath = gamemillis;
logger->writeline(log::info, "[%s] %s %s %s", actor->hostname, actor->name, gib ? "gibbed" : "fragged", target->name);
if(m_flags && targethasflag >= 0)
{
flagaction(targethasflag, suic ? SV_FLAGLOST : SV_FLAGRESET, -1);
}
// don't issue respawn yet until DEATHMILLIS has elapsed
// ts.respawn();
@@ -1237,7 +1332,7 @@ void readscfg(const char *name)
par[3] = par[4] = 0; // default values
for(i = 0; i < CONFIG_MAXPAR; i++)
{
if ((l = strtok(NULL, sep)) != NULL)
if((l = strtok(NULL, sep)) != NULL)
par[i] = atoi(l);
else
break;
@@ -1264,7 +1359,7 @@ int cmpipmatch(const void *a, const void * b) { return - (((struct iprange *)a)-
enet_uint32 atoip(const char *s)
{
unsigned int d[3], res;
if (sscanf(s, "%u.%u.%u.%u", &res, d, d + 1, d + 2) != 4) return 0;
if(sscanf(s, "%u.%u.%u.%u", &res, d, d + 1, d + 2) != 4) return 0;
loopi(3)
{
if(d[i] > 255) return 0;
@@ -1445,7 +1540,7 @@ void forceteam(int client, int team, bool respawn, bool notify = false)
void calcscores()
{
loopv(clients) if (clients[i]->type!=ST_EMPTY)
loopv(clients) if(clients[i]->type!=ST_EMPTY)
{
clients[i]->at3_score = clients[i]->state.frags * 100 / (clients[i]->state.deaths ? clients[i]->state.deaths : 1)
+ clients[i]->state.flagscore < 3 ? 66 * clients[i]->state.flagscore : 66 + 33 * clients[i]->state.flagscore;
@@ -1490,7 +1585,7 @@ bool refillteams(bool now, bool notify) // force only minimal amounts of player
bool switched = false;
calcscores();
loopv(clients) if (clients[i]->type!=ST_EMPTY) // playerlist stocktaking
loopv(clients) if(clients[i]->type!=ST_EMPTY) // playerlist stocktaking
{
clients[i]->at3_dontmove = true;
if(!clients[i]->awaitdisc)
@@ -1500,8 +1595,8 @@ bool refillteams(bool now, bool notify) // force only minimal amounts of player
{
teamsize[t]++;
teamscore[t] += clients[i]->at3_score;
if(!m_ctf || !((sflaginfos[0].state==CTFF_STOLEN && sflaginfos[0].actor_cn==i) ||
(sflaginfos[1].state==CTFF_STOLEN && sflaginfos[1].actor_cn==i) ))
if(!m_flags || !((sflaginfos[0].state==CTFF_STOLEN && sflaginfos[0].actor_cn==i) ||
(sflaginfos[1].state==CTFF_STOLEN && sflaginfos[1].actor_cn==i) ))
{
clients[i]->at3_dontmove = false;
moveable[t]++;
@@ -1519,7 +1614,7 @@ bool refillteams(bool now, bool notify) // force only minimal amounts of player
if(now || gamemillis - lasttime_eventeams > 8000 + allplayers * 1000 || diffnum > 2 + allplayers / 10)
{
// time to even out teams
loopv(clients) if (clients[i]->type!=ST_EMPTY && team_int(clients[i]->team) != bigteam) clients[i]->at3_dontmove = true; // dont move small team players
loopv(clients) if(clients[i]->type!=ST_EMPTY && team_int(clients[i]->team) != bigteam) clients[i]->at3_dontmove = true; // dont move small team players
while(diffnum > 1 && moveable[bigteam] > 0)
{
// pick best fitting cn
@@ -1528,7 +1623,7 @@ bool refillteams(bool now, bool notify) // force only minimal amounts of player
int bestfit = 1000000000;
int targetscore = diffscore / (diffnum & ~1);
s_sprintf(atlog)("at-target: %d, ", targetscore);
loopv(clients) if (clients[i]->type!=ST_EMPTY && !clients[i]->at3_dontmove) // try all still movable players
loopv(clients) if(clients[i]->type!=ST_EMPTY && !clients[i]->at3_dontmove) // try all still movable players
{
int fit = targetscore - clients[i]->at3_score;
if(fit < 0 ) fit = -(fit * 15) / 10; // avoid too good players
@@ -1607,7 +1702,7 @@ void resetmap(const char *newname, int newmode, int newtime, bool notify)
{
if(!lastteammode)
shuffleteams(false);
else if (autoteam)
else if(autoteam)
refillteams(true, false);
}
// send spawns
@@ -1624,6 +1719,7 @@ void resetmap(const char *newname, int newmode, int newtime, bool notify)
demonextmatch = false;
setupdemorecord();
}
if(m_ktf) { sendflaginfo(0, 0); sendflaginfo(1, 0); }
}
void nextcfgset(bool notify = true) // load next maprotation set
@@ -1813,7 +1909,7 @@ const char *disc_reason(int reason)
void disconnect_client(int n, int reason)
{
if(!clients.inrange(n) || clients[n]->type!=ST_TCPIP) return;
if(m_ctf) loopi(2) if(sflaginfos[i].state==CTFF_STOLEN && sflaginfos[i].actor_cn==n) flagaction(i, SV_FLAGDROP, n);
if(m_flags) loopi(2) if(sflaginfos[i].state==CTFF_STOLEN && sflaginfos[i].actor_cn==n) flagaction(i, SV_FLAGLOST, n);
client &c = *clients[n];
savedscore *sc = findscore(c, true);
if(sc) sc->save(c.state);
@@ -2069,7 +2165,7 @@ int checktype(int type, client *cl)
static int edittypes[] = { SV_EDITENT, SV_EDITH, SV_EDITT, SV_EDITS, SV_EDITD, SV_EDITE };
if(cl && smode!=1) loopi(sizeof(edittypes)/sizeof(int)) if(type == edittypes[i]) return -1;
// server only messages
static int servtypes[] = { SV_INITS2C, SV_MAPRELOAD, SV_SERVMSG, SV_GIBDAMAGE, SV_DAMAGE, SV_HITPUSH, SV_SHOTFX, SV_DIED, SV_SPAWNSTATE, SV_FORCEDEATH, SV_ITEMACC, SV_ITEMSPAWN, SV_TIMEUP, SV_CDIS, SV_PONG, SV_RESUME, SV_FLAGINFO, SV_ARENAWIN, SV_SENDDEMOLIST, SV_SENDDEMO, SV_DEMOPLAYBACK, SV_CLIENT, SV_CALLVOTESUC, SV_CALLVOTEERR, SV_VOTERESULT, SV_WHOISINFO };
static int servtypes[] = { SV_INITS2C, SV_MAPRELOAD, SV_SERVMSG, SV_GIBDAMAGE, SV_DAMAGE, SV_HITPUSH, SV_SHOTFX, SV_DIED, SV_SPAWNSTATE, SV_FORCEDEATH, SV_ITEMACC, SV_ITEMSPAWN, SV_TIMEUP, SV_CDIS, SV_PONG, SV_RESUME, SV_FLAGINFO, SV_ARENAWIN, SV_SENDDEMOLIST, SV_SENDDEMO, SV_DEMOPLAYBACK, SV_CLIENT, SV_CALLVOTESUC, SV_CALLVOTEERR, SV_VOTERESULT, SV_WHOISINFO, SV_FLAGS, SV_FLAGRESET };
if(cl) loopi(sizeof(servtypes)/sizeof(int)) if(type == servtypes[i]) return -1;
return type;
}
@@ -2142,7 +2238,7 @@ void process(ENetPacket *packet, int sender, int chan) // sender may be -1
welcomepacket(p, sender);
enet_packet_resize(packet, p.length());
sendpacket(sender, 1, packet);
if(smapname[0] && m_ctf) loopi(2) sendflaginfo(i, -1, sender);
if(smapname[0] && m_flags) loopi(2) sendflaginfo(i, -1, sender);
if(clientrole != CR_DEFAULT) changeclientrole(sender, clientrole, NULL, true);
}
@@ -2443,19 +2539,16 @@ void process(ENetPacket *packet, int sender, int chan) // sender may be -1
case SV_FLAGPICKUP:
case SV_FLAGDROP:
case SV_FLAGLOST:
case SV_FLAGRETURN:
case SV_FLAGSCORE:
case SV_FLAGRESET:
{
if(!m_flags) { disconnect_client(sender, DISC_TAGT); return; }
flagaction(getint(p), type, sender);
break;
}
case SV_FLAGS:
cl->state.flagscore = getint(p);
QUEUE_MSG;
break;
case SV_SETADMIN:
{
bool claim = getint(p) != 0;
@@ -2681,10 +2774,18 @@ void serverslice(uint timeout) // main server update, called from cube main lo
{
processevents();
checkitemspawns(diff);
if(m_ctf) loopi(2)
if(m_flags) loopi(2)
{
sflaginfo &f = sflaginfos[i];
if(f.state==CTFF_DROPPED && gamemillis-f.lastupdate>30000) flagaction(i, SV_FLAGRESET, -1);
if(f.state == CTFF_DROPPED && gamemillis-f.lastupdate > (m_ctf ? 30000 : 10000)) flagaction(i, SV_FLAGRESET, -1);
if(m_htf && f.state == CTFF_INBASE && gamemillis-f.lastupdate > 10000)
{
htf_forceflag(i);
}
if(m_ktf && f.state == CTFF_STOLEN && gamemillis-f.lastupdate > 15000)
{
flagaction(i, SV_FLAGSCORE, f.actor_cn);
}
}
if(m_arena) arenacheck();
}
@@ -2750,20 +2851,20 @@ void serverslice(uint timeout) // main server update, called from cube main lo
{
cvector teams;
bool flag;
bool addteam;
loopv(clients)
{
if(clients[i]->type == ST_EMPTY || !clients[i]->name[0]) continue;
flag = true;
addteam = true;
loopvj(teams)
{
if(strcmp(clients[i]->team,teams[j])==0 || !clients[i]->team[0])
{
flag = false;
addteam = false;
break;
}
}
if(flag) teams.add(clients[i]->team);
if(addteam) teams.add(clients[i]->team);
}
loopv(teams)
@@ -2778,7 +2879,7 @@ void serverslice(uint timeout) // main server update, called from cube main lo
flagscore += clients[j]->state.flagscore;
}
logger->writeline(log::info, "Team %5s: %3d frags", teams[i], fragscore);
if(m_ctf) logger->writeline(log::info, "Team %5s: %3d flags", teams[i], flagscore); // ctf only
if(m_flags) logger->writeline(log::info, "Team %5s: %3d flags", teams[i], flagscore); // ctf only
}
}
@@ -2910,19 +3011,19 @@ void extinfo_teamscorebuf(ucharbuf &p)
if(!m_teammode) return;
cvector teams;
bool flag;
bool addteam;
loopv(clients) if(clients[i]->type!=ST_EMPTY)
{
flag = true;
addteam = true;
loopvj(teams)
{
if(strcmp(clients[i]->team,teams[j])==0 || !clients[i]->team[0])
{
flag = false;
addteam = false;
break;
}
}
if(flag) teams.add(clients[i]->team);
if(addteam) teams.add(clients[i]->team);
}
loopv(teams)
@@ -2937,7 +3038,7 @@ void extinfo_teamscorebuf(ucharbuf &p)
flagscore += clients[j]->state.flagscore;
}
putint(p,fragscore); //add fragscore per team
if(m_ctf) //when capture mode
if(m_flags) //when capture mode
{
putint(p,flagscore); //add flagscore per team
}
+4 -11
View File
@@ -3,7 +3,7 @@
void processevent(client *c, explodeevent &e)
{
clientstate &gs = c->state;
switch(e.gun)
switch(e.gun)
{
case GUN_GRENADE:
if(!gs.grenades.remove(e.id)) return;
@@ -79,14 +79,7 @@ void processevent(client *c, shotevent &e)
void processevent(client *c, suicideevent &e)
{
clientstate &gs = c->state;
if(gs.state!=CS_ALIVE) return;
gs.frags--;
gs.deaths++;
sendf(-1, 1, "ri4", SV_DIED, c->clientnum, c->clientnum, gs.frags);
c->position.setsizenodelete(0);
gs.state = CS_DEAD;
gs.respawn();
serverdamage(c, c, 1000, GUN_KNIFE, false);
logger->writeline(log::info, "[%s] %s suicided", c->hostname, c->name);
}
@@ -102,7 +95,7 @@ void processevent(client *c, reloadevent &e)
clientstate &gs = c->state;
if(!gs.isalive(gamemillis) ||
e.gun<GUN_KNIFE || e.gun>=NUMGUNS ||
!reloadable_gun(e.gun) ||
!reloadable_gun(e.gun) ||
gs.ammo[e.gun]<=0)
return;
@@ -148,7 +141,7 @@ void processevents()
while(c->events.length())
{
gameevent &e = c->events[0];
if(e.type<GE_SUICIDE)
if(e.type<GE_SUICIDE)
{
if(e.shot.millis>gamemillis) break;
if(e.shot.millis<c->lastevent) { clearevent(c); continue; }
+1 -1
View File
@@ -299,7 +299,7 @@ bool load_world(char *mname) // still supports all map formats that have
if(e.attr1>32) e.attr1 = 32; // 12_03 and below
}
if (hdr.version<MAPVERSION && strncmp(hdr.head,"CUBE",4)==0) //only render lights, pl starts and map models on old maps
if(hdr.version<MAPVERSION && strncmp(hdr.head,"CUBE",4)==0) //only render lights, pl starts and map models on old maps
{
switch(e.type)
{