From d4e40cb5217e787af5c088e7c0d71cbde1708207 Mon Sep 17 00:00:00 2001 From: Rafael Barreto Date: Thu, 27 May 2010 22:08:05 +0000 Subject: [PATCH] cover teammates who ask for it (teamwork rewarded) git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@5083 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/clients2c.cpp | 47 ++++++++++++++++--- source/src/server.cpp | 19 ++++++-- source/src/server.h | 5 ++ source/src/serverchecks.h | 99 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 152 insertions(+), 18 deletions(-) diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 4e346907..c47a2349 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -225,20 +225,55 @@ bool good_map() return checked; } -VARP(hudextras, 0, 0, 2); +VARP(hudextras, 0, 0, 3); + +char *stolower(const char *s, char *o) +{ + char *c = (char *)s; int n = 0; + char *r = o; + c++; o++; + while( *c!='\0' && n < 40 ) { + *o = tolower(*c); + n++; o++; c++; + } + *o='\0'; + return r; +} + +char *stoupper(const char *s, char *o) +{ + char *c = (char *)s; int n = 0; + char *r = o; + while( *c!='\0' && n < 40 ) { + *o = toupper(*c); + n++; o++; c++; + } + *o='\0'; + return r; +} void showhudextras(char hudextras, char value){ - void (*outf)(const char *s, ...) = (hudextras == 2 ? hudoutf : conoutf); + void (*outf)(const char *s, ...) = (hudextras > 1 ? hudoutf : conoutf); + char *(*spam)(const char *s, char *o) = (hudextras == 2 ? stolower : stoupper); + char o[50]; switch(value) { case HE_COMBO: - outf("\f2COMBO"); break; + outf("\f2%s",spam("COMBO",o)); break; case HE_FLAGDEFENDED: - outf("\f2FLAG DEFENDED"); break; + outf("\f2%s",spam("FLAG DEFENDED",o)); break; case HE_FLAGCOVERED: - outf("\f2FLAG COVERED"); break; + outf("\f2%s",spam("FLAG COVERED",o)); break; + case HE_COVER: + outf("\f2%s",spam("TEAMMATE COVERED",o)); break; default: - outf("\f2Update your client, NOOB!"); break; + { + if (value >= 100) { // beware here! this value is linked to checkteamplay::serverchecks.h value + outf("\f2Replied to %s",players[value-100]->name); + } + else outf("\f2Update your client, NOOB!"); + break; + } } } diff --git a/source/src/server.cpp b/source/src/server.cpp index bf5ae378..756665a7 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -2367,12 +2367,21 @@ void process(ENetPacket *packet, int sender, int chan) } case SV_VOICECOM: - getint(p); - QUEUE_MSG; - break; - case SV_VOICECOMTEAM: - sendvoicecomteam(getint(p), sender); + { + int s = getint(p); + /* spam filter */ + if ( servmillis > cl->mute ) { // client is not muted + if( s < S_AFFIRMATIVE || s > S_NICESHOT ) cl->mute = servmillis + 10000; // vc is invalid + else if ( cl->lastvc + 4000 < servmillis ) { if ( cl->spam > 0 ) cl->spam -= (servmillis - cl->lastvc) / 4; } // no vc in the last 4 seconds + else cl->spam++; // the guy is spamming + cl->lastvc = servmillis; // register + if ( cl->spam > 4 ) { cl->mute = servmillis + 10000; break; } // 5 vcs in less than 20 seconds... shut up please + if ( m_teammode ) checkteamplay(s,sender); // finally here we check the teamplay + if ( type == SV_VOICECOM ) { QUEUE_MSG; } + else sendvoicecomteam(s, sender); + } + } break; case SV_MAPIDENT: diff --git a/source/src/server.h b/source/src/server.h index c757410c..ff69d6a2 100644 --- a/source/src/server.h +++ b/source/src/server.h @@ -207,6 +207,7 @@ struct client // server side version of "dynent" type int vote; int role; int connectmillis; + int mute, spam, lastvc; // server side voice comm spam control int acversion, acbuildtype; bool isauthed; // for passworded servers bool haswelcome; @@ -231,6 +232,7 @@ struct client // server side version of "dynent" type enet_uint32 bottomRTT; int points, lasthit, lastgun, combohits, combo, combotime, combodamage, ncombos, ncovers, nhs; + int ask, askmillis, linked, linkmillis, linkreason; gameevent &addevent() { @@ -257,6 +259,8 @@ struct client // server side version of "dynent" type at3_lastforce = 0; mapcollisions = farpickups = 0; points = lasthit = lastgun = combohits = combo = combotime = combodamage = ncombos = ncovers = nhs = 0; + askmillis = linkmillis = 0; + linkreason = linked = ask = -1; } void reset() @@ -277,6 +281,7 @@ struct client // server side version of "dynent" type spectcn = FPCN_VOID; mapchange(); freshgame = false; // don't spawn into running games + mute = spam = lastvc = 0; } void zap() diff --git a/source/src/serverchecks.h b/source/src/serverchecks.h index d53cd118..9d5a0fe8 100644 --- a/source/src/serverchecks.h +++ b/source/src/serverchecks.h @@ -142,9 +142,77 @@ void checkcombo (client *target, client *actor, int damage, int gun) actor->lastgun = gun; } -int FlagFlag = MINFF * 1000; #define COVERDIST 2000 // about 45 cubes +int checkteamrequests(int sender) +{ + float bestdist = COVERDIST * 1000; + int bestid = -1; + client *ant = clients[sender]; + loopv(clients) { + client *prot = clients[i]; + if ( i!=sender && prot->type!=ST_EMPTY && prot->team==ant->team && prot->ask>=0 && prot->askmillis + 5000 > gamemillis ) { + float dist = POW2XY(ant->state.o,prot->state.o); + if (dist < bestdist) { + bestid = i; + bestdist = dist; + } + } + } + if ( bestdist < MINFF ) return bestid; + return -1; +} + +/** WIP */ +void checkteamplay(int s, int sender) +{ + client *actor = clients[sender]; + switch(s){ + case S_COVERME: + case S_STAYTOGETHER: + actor->ask = s; + actor->askmillis = gamemillis; + break; + case S_AFFIRMATIVE: + case S_ALLRIGHTSIR: + case S_YES: + { + int id = checkteamrequests(sender); + if (id >= 0) { + client *prot = clients[id]; + prot->linked = id; + prot->linkmillis = gamemillis; + prot->linkreason = s; + sendf(actor->clientnum, 1, "ri2", SV_HUDEXTRAS, 100+id); + } + break; + } +/* case S_NEGATIVE: + case S_NOCANDO: + case S_THERESNOWAYSIR: + + case S_COMEONMOVE: + case S_COMINGINWITHTHEFLAG: + case S_DEFENDTHEFLAG: + case S_ENEMYDOWN: + case S_GOGETEMBOYS: + case S_GOODJOBTEAM: + case S_IGOTONE: + case S_IMADECONTACT: + case S_IMATTACKING: + case S_IMONDEFENSE: + case S_IMONYOURTEAMMAN: + case S_RECOVERTHEFLAG: + case S_SORRY: + case S_SPREADOUT: + case S_STAYHERE: + case S_WEDIDIT: + case S_NICESHOT:*/ + } +} + +int FlagFlag = MINFF * 1000; + float a2c = 0, c2t = 0, a2t = 0; // distances: actor to covered, covered to target and actor to target inline void testcover(int msg, int factor, client *actor) @@ -161,12 +229,20 @@ inline void testcover(int msg, int factor, client *actor) c2t = POW2XY(C,target->state.o);\ a2t = POW2XY(actor->state.o,target->state.o) +bool validlink (client *actor, int cn) +{ + return actor->linked >= 0 && actor->linked == cn && gamemillis < actor->linkmillis + 20000 && valid_client(actor->linked); +} + /** WIP */ void checkcover (client *target, client *actor) { int team = actor->team; int oteam = team_opposite(team); + bool covered = false; + int coverid = -1; + if ( m_flags ) { sflaginfo &f = sflaginfos[team]; sflaginfo &of = sflaginfos[oteam]; @@ -174,25 +250,34 @@ void checkcover (client *target, client *actor) if ( m_ctf ) { if ( f.state == CTFF_INBASE ) { CALCCOVER(f); - testcover(1, 1, actor); /* Flag defended */ + testcover(HE_FLAGDEFENDED, 1, actor); /* Flag defended */ } if ( of.state == CTFF_STOLEN && actor->clientnum != of.actor_cn ) { + covered = true; coverid = of.actor_cn; CALCCOVER(clients[of.actor_cn]->state.o); - testcover(2, 2, actor); /* Flag covered */ + testcover(HE_FLAGCOVERED, 2, actor); /* Flag covered */ } } else if ( m_htf ) { if ( f.state == CTFF_DROPPED ) { struct { short x, y; } nf; nf.x = f.pos[0]; nf.y = f.pos[1]; CALCCOVER(nf); - testcover(1, 1, actor); /* Flag defended */ + testcover(HE_FLAGDEFENDED, 1, actor); /* Flag defended */ } if ( f.state == CTFF_STOLEN && actor->clientnum != f.actor_cn ) { + covered = true; coverid = f.actor_cn; CALCCOVER(clients[f.actor_cn]->state.o); - testcover(2, 3, actor); /* Flag covered */ + testcover(HE_FLAGCOVERED, 3, actor); /* Flag covered */ } } } + + if ( !(covered && actor->linked==coverid) && validlink(actor,actor->linked) ) + { + CALCCOVER(clients[actor->linked]->state.o); + testcover(HE_COVER, 2, actor); /* covered */ + } + } #undef CALCCOVER @@ -221,9 +306,9 @@ void checkfrag (client *target, client *actor, int gun, bool gib) else actor->points += 3 * target->points / 100; if (gib) { - if ( gun == GUN_GRENADE ) actor->points += 12; + if ( gun == GUN_GRENADE ) actor->points += 10; else if ( gun == GUN_SNIPER ) { - actor->points += 16; + actor->points += 15; actor->nhs++; } else if ( gun == GUN_KNIFE ) actor->points += 20;