q2wf-portable/wf_flagcap.c

454 lines
11 KiB
C
Raw Normal View History

/*==============================================================================
The Weapons Factory -
Team Fortress Style Flag Capture Functions
Original code by Gregg Reno
==============================================================================*/
#include "g_local.h"
#include "stdlog.h" // StdLog - Mark Davies
extern gitem_t *flag1_item;
extern gitem_t *flag2_item;
extern ctfgame_t ctfgame;
void CTFResetFlags(void);
void CTFResetFlag(int ctf_team);
void WFRemoveDisguise(edict_t *ent);
int PlayerChangeScore(edict_t *self, int points);
qboolean WFUnbalanced_Teams(edict_t *flag, edict_t *player)
{
int team_limit;
int flagteamcount = 0, playerteamcount = 0;
int i;
int diff;
edict_t *target;
int flagteam;
team_limit = wf_game.unbalanced_limit;
// figure out what team this flag is
if (strcmp(flag->classname, "item_flag_team1") == 0)
flagteam = CTF_TEAM1;
else if (strcmp(flag->classname, "item_flag_team2") == 0)
flagteam = CTF_TEAM2;
else
flagteam = 0;
//Is any limit set?
if (team_limit <= 0)
{
//gi.dprintf("No Limit Set\n");
return false;
}
//Teams must be set
if ((flagteam == 0) || (player->wf_team == 0))
{
//gi.dprintf("Someone doesn't have their wf_team flag set: %d, %d\n",
// flagteam, player->wf_team );
return false;
}
//Must be on different teams
if (flagteam == player->wf_team == 0)
//Count players on each team
for (i = 1; i <= maxclients->value; i++)
{
target = &g_edicts[i];
if (!target->inuse)
continue;
if (target->wf_team == flagteam )
flagteamcount++;
if (target->wf_team == player->wf_team)
playerteamcount++;
}
diff = playerteamcount - flagteamcount;
//gi.dprintf("Diff=%d, playercount = %d, flagcount = %d, team limit = %d\n",
// diff, playerteamcount,flagteamcount,team_limit);
if (diff >= team_limit)
{
safe_cprintf(player, PRINT_HIGH, "Sorry, you can't pick up flag. Teams are not balanced.\n");
return true;
}
else
return false;
}
qboolean WFPickup_Flag(edict_t *ent, edict_t *other)
{
int ctf_team;
gitem_t *flag_item, *enemy_flag_item;
// figure out what team this flag is
if (strcmp(ent->classname, "item_flag_team1") == 0)
{
ctf_team = CTF_TEAM1;
}
else if (strcmp(ent->classname, "item_flag_team2") == 0)
{
ctf_team = CTF_TEAM2;
}
else
{
safe_cprintf(other, PRINT_HIGH, "Don't know what team the flag is on.\n");
return false;
}
// same team, if the flag at base, check to he has the enemy flag
if (ctf_team == CTF_TEAM1)
{
flag_item = flag1_item;
enemy_flag_item = flag2_item;
}
else
{
flag_item = flag2_item;
enemy_flag_item = flag1_item;
}
//Cant create decoy in observer/spectator mode
if (other->solid == SOLID_NOT)
{
safe_cprintf(other, PRINT_HIGH, "Nice try, but observers can't pick up the flag!.\n");
return false;
}
if (other->client->resp.ctf_team != CTF_TEAM1 &&
other->client->resp.ctf_team != CTF_TEAM2)
{
safe_cprintf(other, PRINT_HIGH, "I don't know how you did it, but you don't have a team!.\n");
return false;
}
//Note - you can't pick up your own flag - just the enemy's
if (ctf_team != other->client->resp.ctf_team)
{
// hey, its not our flag, pick it up
if (PlayerChangeScore(other,CTF_FLAG_BONUS))
{
gi.bprintf(PRINT_HIGH, "%s got the %s flag!\n",
other->client->pers.netname, CTFTeamName(ctf_team));
// Log Flag Pickup - MarkDavies
sl_LogScore( &gi,
other->client->pers.netname,
NULL,
"F Pickup",
-1,
CTF_FLAG_BONUS);
}
if (ctf_team == CTF_TEAM1)
flag1dropped = 0; //clear the dropped flag flag
else if (ctf_team == CTF_TEAM2)
flag2dropped = 0;
other->client->pers.inventory[ITEM_INDEX(flag_item)] = 1;
other->client->resp.ctf_flagsince = level.time;
//Remove player disguise
if (other->disguised) WFRemoveDisguise(other);
// pick up the flag
// if it's not a dropped flag, we just make is disappear
// if it's dropped, it will be removed by the pickup caller
if (!(ent->spawnflags & DROPPED_ITEM))
{
ent->flags |= FL_RESPAWN;
ent->svflags |= SVF_NOCLIENT;
ent->solid = SOLID_NOT;
}
return true;
}
return false;
}
//Something touched home base
void Home_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
int i;
edict_t *player;
gitem_t *flag_item, *enemy_flag_item;
//Did someone try to put something on top of the base? If so, blow it up!
if (!strcmp(other->classname, "SentryGun") )
{
turret_remove(other->creator);
}
if (!strcmp(other->classname, "SentryStand") )
{
turret_remove(other->standowner);
}
if (!strcmp(other->classname, "depot") )
{
if (other->owner) other->owner->supply = NULL;
//G_FreeEdict(other);
BecomeExplosion1 (other);
}
if (!strcmp(other->classname, "healingdepot") )
{
if (other->owner) other->owner->supply = NULL;
//G_FreeEdict(other);
BecomeExplosion1 (other);
}
//Did a player touch?
if (!other->client)
return;
//Home base and player must be on same team
if (ent->wf_team != other->wf_team)
return;
// same team, if the flag at base, check to see if he has the enemy flag
if (other->wf_team == CTF_TEAM1)
{
flag_item = flag1_item;
enemy_flag_item = flag2_item;
}
else
{
flag_item = flag2_item;
enemy_flag_item = flag1_item;
}
//Does the player have the enemy flag?
if (other->client->pers.inventory[ITEM_INDEX(enemy_flag_item)])
{
//Yes - TOUCHDOWN!
other->client->pers.inventory[ITEM_INDEX(enemy_flag_item)] = 0;
ctfgame.last_flag_capture = level.time;
ctfgame.last_capture_team = other->wf_team;
if (other->wf_team == CTF_TEAM1)
ctfgame.team1++;
else
ctfgame.team2++;
gi.sound (ent, CHAN_RELIABLE+CHAN_NO_PHS_ADD+CHAN_VOICE, gi.soundindex("ctf/flagcap.wav"), 1, ATTN_NONE, 0);
// other gets another 10 frag bonus
if (PlayerChangeScore(other,CTF_CAPTURE_BONUS))
{
gi.bprintf(PRINT_HIGH, "%s captured the %s flag!\n",
other->client->pers.netname, CTFOtherTeamName(other->wf_team));
// Log Flag Capture - MarkDavies
sl_LogScore( &gi,
other->client->pers.netname,
NULL,
"F Capture",
-1,
CTF_CAPTURE_BONUS);
}
//execute the trigger if it exists
if (ent->orig_map_entity)
{
G_UseTargets (ent->orig_map_entity, other);
//if (wfdebug) gi.dprintf("Using Target %s\n", ent->orig_map_entity->target);
}
else
{
//if (wfdebug) gi.dprintf("No Target\n");
}
// Ok, let's do the player loop, hand out the bonuses
for (i = 1; i <= maxclients->value; i++)
{
player = &g_edicts[i];
if (!player->inuse)
continue;
if (!player->client)
continue;
if (!other->client)
continue;
if (player->client->resp.ctf_team != other->client->resp.ctf_team)
{
player->client->resp.ctf_lasthurtcarrier = -5;
}
else if (player->client->resp.ctf_team == other->client->resp.ctf_team)
{
if (player != other)
{
if (PlayerChangeScore(player,CTF_TEAM_BONUS))
{
// Log Flag Capture Team Score - MarkDavies
sl_LogScore( &gi,
player->client->pers.netname,
NULL,
"Team Score",
-1,
CTF_TEAM_BONUS);
}
}
// award extra points for capture assists
if (player->client->resp.ctf_lastreturnedflag + CTF_RETURN_FLAG_ASSIST_TIMEOUT > level.time)
{
if (PlayerChangeScore(player,CTF_RETURN_FLAG_ASSIST_BONUS))
{
gi.bprintf(PRINT_HIGH, "%s gets an assist for returning the flag!\n", player->client->pers.netname);
// Log Flag Capture Team Score - MarkDavies
sl_LogScore( &gi,
player->client->pers.netname,
NULL,
"F Return Assist",
-1,
CTF_RETURN_FLAG_ASSIST_BONUS);
}
}
if (player->client->resp.ctf_lastfraggedcarrier + CTF_FRAG_CARRIER_ASSIST_TIMEOUT > level.time)
{
if (PlayerChangeScore(player,CTF_FRAG_CARRIER_ASSIST_BONUS))
{
gi.bprintf(PRINT_HIGH, "%s gets an assist for fragging the flag carrier!\n", player->client->pers.netname);
// Log Flag Capture Frag Assist Score - MarkDavies
sl_LogScore( &gi,
player->client->pers.netname,
NULL,
"FC Frag Assist",
-1,
CTF_FRAG_CARRIER_ASSIST_BONUS);
}
}
}
}
if (ent->wf_team == CTF_TEAM1)
CTFResetFlag(CTF_TEAM2);
else
CTFResetFlag(CTF_TEAM1);
}
}
void Home_Think (edict_t *ent)
{
//For some reason, entity needs a think function
ent->nextthink = level.time + 5.0;
}
void Create_Home_Base(edict_t *flag, int team)
{
edict_t *home;
home = G_Spawn ();
home->wf_team = team;
//gi.dprintf("--Create Home: %s. Target = %s, ent = %d\n", flag->classname, flag->target, flag);
//Save a pointer to the flag/home base entity so the
//triggers will work
if ((flag->target) && (flag->target[0] != 0))
home->orig_map_entity = flag;
VectorCopy(flag->s.origin, home->s.origin);
home->s.origin[2] += 40;
//home->classname="depot";
home->takedamage=DAMAGE_NO;
home->movetype= MOVETYPE_TOSS;
home->mass = 200;
home->solid = SOLID_BBOX;
home->clipmask=MASK_ALL;
home->deadflag =DEAD_NO;
home->clipmask = MASK_SHOT;
home->model = flag->model;
home->s.modelindex = gi.modelindex ("models/objects/flagbase/tris.md2");
if (team == CTF_TEAM1)
{
home->classname="home_team1";
home->s.skinnum = 0;
}
else
{
home->classname="home_team2";
home->s.skinnum = 1;
}
home->solid = SOLID_BBOX;
VectorSet (home->mins, -20, -20, -15);
VectorSet (home->maxs, 20, 20, -13);
home->s.frame =0;
home->waterlevel = 0;
home->watertype=0;
home->health= 100;
home->max_health =100;
home->gib_health = -80;
// home->die = supplydepot_die;
home->owner = flag;
home->dmg = 100;
home->dmg_radius = 100;
// home->touch = SupplyTouch;
// home->think =SupplyThink;
home->touch = Home_Touch;
home->think = Home_Think;
home->nextthink = level.time + 1.0;
VectorClear (home->velocity);
gi.linkentity (home);
// gi.dprintf("FLAG CREATED.\n");
}
void Create_All_Home_Bases (void)
{
edict_t *spot;
spot = NULL;
//Team 1 home base
//First try home base (flag return) position
spot = G_Find (spot, FOFS(classname), "item_flagreturn_team1");
//Next try flag spot
if (!spot) spot = G_Find (spot, FOFS(classname), "item_flag_team1");
if (!spot)
{
gi.dprintf("WARNING - Could not place flag return entity for team 1!\n");
}
else
{
Create_Home_Base(spot, CTF_TEAM1);
}
//Team 2 home base
//First try home base (flag return) position
spot = NULL;
spot = G_Find (spot, FOFS(classname), "item_flagreturn_team2");
//Next try flag spot
if (!spot) spot = G_Find (spot, FOFS(classname), "item_flag_team2");
if (!spot)
{
gi.dprintf("WARNING - Could not place flag return entity for team 2!\n");
}
else
{
if (strcmp(spot->classname, "item_flagreturn_team2") == 0)//4/99
spot->s.skinnum = 1;//3/99 small fix for g_items.c/bot
Create_Home_Base(spot, CTF_TEAM2);
}
}