mirror of
https://github.com/id-Software/quake-rerelease-qc.git
synced 2024-11-24 05:01:43 +00:00
1886 lines
54 KiB
C++
1886 lines
54 KiB
C++
/* Copyright (C) 1996-2022 id Software LLC
|
||
|
||
This program is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 2 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program; if not, write to the Free Software
|
||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
||
See file, 'COPYING', for details.
|
||
*/
|
||
|
||
// Rogue Teamplay Variants
|
||
// Jan'97 by ZOID <zoid@threewave.com>
|
||
// Under contract to id software for Rogue Entertainment
|
||
|
||
|
||
// New entity fields
|
||
|
||
.float steam; // selected team
|
||
.float suicide_count; // how many times has this player done something silly?
|
||
.float ctf_flags; // various flags for CTF
|
||
.float ctf_killed; // used for base spawning
|
||
.float ctf_flagsince; // when we picked up the flag
|
||
.float ctf_lasthurtcarrier; // when we last hurt the carrier
|
||
.float ctf_lastreturnedflag; // when we returned the flag
|
||
.float ctf_lastfraggedcarrier; // when we last fragged the carrier
|
||
|
||
float TEAM1 = 5; // color of team1 (red), note that this is self.team which
|
||
//is one more than the color setting, so 'color 4' is red.
|
||
float TEAM2 = 14; // color of team2 (blue), note that this is self.team which
|
||
//is one more than the color setting, so 'color 13' is blue.
|
||
float TEAM3 = 1; // color of team3 (grey) in alt CTF
|
||
|
||
entity team1_lastspawn; // last spawn spot for team1
|
||
entity team2_lastspawn; // last spawn spot for team2
|
||
float nextteamupdtime; // next time for a broadcast update
|
||
|
||
// TEAMPLAY VALUES
|
||
|
||
float TEAM_NORMAL_NODAMAGE = 1; // id's normal teamplay, can't hurt self
|
||
float TEAM_NORMAL_DAMAGE = 2; // id's alt teamplay, can hurt self/team
|
||
float TEAM_DMATCH_TAG = 3; // deathmatch tag, no 'team' stuff
|
||
float TEAM_CTF = 4; // regular CTF, locked colors
|
||
float TEAM_CTF_ONEFLAG = 5; // one flag CTF
|
||
float TEAM_CTF_ALT = 6; // alternate CTF (three teams)
|
||
|
||
// gamecfg cvar fields
|
||
|
||
float GAMECFG_ENABLE_RUNES = 1; // enable runes (default is disabled)
|
||
float GAMECFG_TEAM_ARMOR_DMG = 2; // 2 team damage affects armor (default is not)
|
||
float GAMECFG_TEAM_HEALTH_DMG = 4; // 4 team damage affects health (default is not)
|
||
float GAMECFG_USE_COLOR = 8; // use color player joins as (if you join and start with blue, you will go
|
||
// to blue team, same with red/green. If you are an illegal color, you'll
|
||
// get assigned).
|
||
float GAMECFG_ALLOW_CHG = 16; // allow people to change teams
|
||
|
||
float CTF_CAPTURE_BONUS = 15; // what you get for capture
|
||
float CTF_TEAM_BONUS = 10; // what your team gets for capture
|
||
float CTF_ALT_CAPTURE_BONUS = 8; // what you get for capture
|
||
float CTF_ALT_TEAM_BONUS = 4; // what your team gets for capture
|
||
float CTF_RECOVERY_BONUS = 1; // what you get for recovery
|
||
float CTF_FLAG_BONUS = 0; // what you get for picking up enemy flag
|
||
float CTF_FRAG_CARRIER_BONUS = 2; // what you get for fragging enemy flag carrier
|
||
float CTF_FLAG_RETURN_TIME = 40; // seconds until auto return
|
||
float CTF_CARRIER_DANGER_PROTECT_BONUS = 2; // bonus for fraggin someone
|
||
// who has recently hurt your flag carrier
|
||
float CTF_CARRIER_PROTECT_BONUS = 1; // bonus for fraggin someone while
|
||
// either you or your target are near your flag carrier
|
||
float CTF_FLAG_DEFENSE_BONUS = 1; // bonus for fraggin someone while
|
||
// either you or your target are near your flag
|
||
float CTF_RETURN_FLAG_ASSIST_BONUS = 1; // awarded for returning a flag that causes a
|
||
// capture to happen almost immediately
|
||
float CTF_FRAG_CARRIER_ASSIST_BONUS = 2; // award for fragging a flag carrier if a
|
||
// capture happens almost immediately
|
||
float CTF_TARGET_PROTECT_RADIUS = 400; // the radius around an object being
|
||
// defended where a target will be worth extra frags
|
||
float CTF_ATTACKER_PROTECT_RADIUS = 400; // the radius around an object being
|
||
// defended where an attacker will get extra frags when making kills
|
||
float CTF_CARRIER_DANGER_PROTECT_TIMEOUT = 4;
|
||
float CTF_CARRIER_FLAG_SINCE_TIMEOUT = 2;
|
||
float CTF_FRAG_CARRIER_ASSIST_TIMEOUT = 6;
|
||
float CTF_RETURN_FLAG_ASSIST_TIMEOUT = 4;
|
||
float CTF_UPDATE_TIME = 120;
|
||
|
||
// CTF flags
|
||
float CTF_FLAG_FLAG = 1; // palyer has flag in one flag mode
|
||
float CTF_FLAG_TEAM1 = 1; // player has team1's flag
|
||
float CTF_FLAG_TEAM2 = 2; // player has team2's flag
|
||
float CTF_FLAG_STUFF_COLOR = 4; // gotta stuff his color
|
||
|
||
// flag status used in cnt field of flag
|
||
float FLAG_AT_BASE = 0;
|
||
float FLAG_CARRIED = 1;
|
||
float FLAG_DROPPED = 2;
|
||
|
||
// Prototypes
|
||
float() W_BestWeapon;
|
||
void() W_SetCurrentAmmo;
|
||
void() bound_other_ammo;
|
||
void(float o, float n) Deathmatch_Weapon;
|
||
void() BackpackTouch;
|
||
void(entity comboOwner) EnableComboWeapons;
|
||
|
||
// Return a name for the color of a team
|
||
string(float Team) GetTeamColor =
|
||
{
|
||
if(Team == 1) return("White");
|
||
else if(Team == 2) return("Brown");
|
||
else if(Team == 3) return("Light blue");
|
||
else if(Team == 4) return("Green");
|
||
else if(Team == 5) return("Red");
|
||
else if(Team == 6) return("Olive");
|
||
else if(Team == 7) return("Orange");
|
||
else if(Team == 8) return("Peech");
|
||
else if(Team == 9) return("Purple");
|
||
else if(Team == 10) return("Majenta");
|
||
else if(Team == 11) return("Grey");
|
||
else if(Team == 12) return("Aqua");
|
||
else if(Team == 13) return("Yellow");
|
||
else if(Team == 14) return("Blue");
|
||
return "Unknown";
|
||
};
|
||
|
||
string(float Team) GetCTFTeam =
|
||
{
|
||
if (Team == TEAM1) return "<EFBFBD><EFBFBD><EFBFBD>";
|
||
else if (Team == TEAM2) return "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
else if (Team == TEAM3) return "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
return "UNKNOWN";
|
||
|
||
};
|
||
|
||
/*
|
||
================
|
||
TeamArmorDam
|
||
|
||
Return TRUE if the target's armor can take damage from this attacker.
|
||
================
|
||
*/
|
||
|
||
float(entity targ, entity inflictor, entity attacker, float damage) TeamArmorDam =
|
||
{
|
||
if (teamplay <= 0)
|
||
return TRUE; // PGM bug? fix
|
||
|
||
// teamplay modes 4,5,6 protect armor
|
||
if ((teamplay == TEAM_CTF ||
|
||
teamplay == TEAM_CTF_ONEFLAG ||
|
||
teamplay == TEAM_CTF_ALT) &&
|
||
attacker.steam == targ.steam &&
|
||
attacker != targ &&
|
||
!(cvar("gamecfg") & GAMECFG_TEAM_ARMOR_DMG)) {
|
||
// Armor is protected
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
};
|
||
|
||
/*
|
||
================
|
||
TeamHealthDam
|
||
|
||
Return TRUE if the target can take health damage from this attacker.
|
||
================
|
||
*/
|
||
|
||
float(entity targ, entity inflictor, entity attacker, float damage) TeamHealthDam =
|
||
{
|
||
if (teamplay <= 0)
|
||
return TRUE;
|
||
|
||
if (teamplay == TEAM_NORMAL_NODAMAGE && attacker.steam == targ.steam)
|
||
return FALSE;
|
||
|
||
// teamplay modes 4,5,6 protect health
|
||
if ((teamplay == TEAM_CTF ||
|
||
teamplay == TEAM_CTF_ONEFLAG ||
|
||
teamplay == TEAM_CTF_ALT) &&
|
||
attacker.steam == targ.steam &&
|
||
attacker != targ &&
|
||
!(cvar("gamecfg") & GAMECFG_TEAM_HEALTH_DMG)) {
|
||
// Health is protected
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
};
|
||
|
||
void(entity who) TeamResetCarrier =
|
||
{
|
||
local entity head;
|
||
|
||
// When the flag carrier dies, reset the last_hurt_carrier field in
|
||
// all players on the opposite team from the flag carrier. The carrier
|
||
// has been killed, so there is no longer a reason to award points for
|
||
// killing off his assailants
|
||
if (teamplay >= TEAM_CTF &&
|
||
(who.ctf_flags & (CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2))) {
|
||
|
||
head = find(world, classname, "player");
|
||
|
||
while (head != world) {
|
||
if (teamplay == TEAM_CTF_ONEFLAG ||
|
||
((who.ctf_flags & CTF_FLAG_TEAM1) && head.steam == TEAM1) ||
|
||
((who.ctf_flags & CTF_FLAG_TEAM2) && head.steam == TEAM2))
|
||
head.ctf_lasthurtcarrier = -10;
|
||
head = find(head, classname, "player");
|
||
}
|
||
}
|
||
};
|
||
|
||
void(entity targ, entity attacker) TeamAssists =
|
||
{
|
||
local float flag_radius;
|
||
local float flag_carrier_radius;
|
||
local string s;
|
||
local entity head;
|
||
|
||
if ((targ.ctf_flags & (CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2)) &&
|
||
targ.steam != attacker.steam) {
|
||
//ZOID: one team fragged the other team's flag carrier
|
||
|
||
// Mark the attacker with the time at which he killed the flag
|
||
// carrier, for awarding assist points
|
||
attacker.ctf_lastfraggedcarrier = time;
|
||
|
||
// give player only the normal amount of frags
|
||
// if the carrier has only had the flag for a few seconds, to
|
||
// prevent ppl intentionally allowing enemies to grab the flag,
|
||
// then immediately fragging them
|
||
if (targ.ctf_flagsince + CTF_CARRIER_FLAG_SINCE_TIMEOUT > time) {
|
||
sprint(attacker, "$qc_enemy_killed_no_bonus");
|
||
} else {
|
||
attacker.frags = attacker.frags + CTF_FRAG_CARRIER_BONUS;
|
||
s = ftos(CTF_FRAG_CARRIER_BONUS);
|
||
sprint(attacker, "$qc_enemy_killed_bonus", s);
|
||
}
|
||
}
|
||
|
||
// This code checks for all game-critical kills OTHER THAN fragging the enemy
|
||
// flag carrier, like killing players who are trying to kill your flag carrier
|
||
// or trying to grab your flag, and hands out bonus frags.
|
||
|
||
// The two variables below track whether special bonus frags have already
|
||
// been awarded for the attacker or target being near the flag or flag carrier.
|
||
|
||
flag_radius = 0;
|
||
flag_carrier_radius = 0;
|
||
|
||
// get a string for the attacker's team now, for later announcements
|
||
s = GetCTFTeam(attacker.steam);
|
||
|
||
if ((targ.ctf_lasthurtcarrier + CTF_CARRIER_DANGER_PROTECT_TIMEOUT > time) &&
|
||
!(attacker.ctf_flags & (CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2))) {
|
||
// a player on the same team as the flag carrier killed
|
||
// someone who recently shot the flag carrier
|
||
attacker.frags = attacker.frags + CTF_CARRIER_DANGER_PROTECT_BONUS;
|
||
flag_carrier_radius = 1;
|
||
// NOTE: getting CARRIER_DANGER_PROTECT_BONUS precludes getting
|
||
// other kinds of bonuses for defending the flag carrier, since
|
||
// it's worth more points
|
||
bprint("$qc_defend_flag_carrier_aggressive", attacker.netname, s);
|
||
}
|
||
|
||
// Bonusus for defending the flag carrier or the flag itself.
|
||
// Extra frags are awarded if either the attacker or the target are
|
||
// 1. within 40 feet of a flag carrier on the same team as the attacker
|
||
// 2. within 40 feet of the attacker's flag
|
||
// These bonuses are cumulative with respect to defending both the
|
||
// flag and the flag carrier at the same time, but not cumulative with
|
||
// respect to both the target and attacker being near the object being defended
|
||
|
||
// find flags or flag carriers within a radius of the attacker
|
||
head = findradius(attacker.origin, CTF_ATTACKER_PROTECT_RADIUS);
|
||
|
||
while (head) {
|
||
if (head.classname == "player") {
|
||
if ( (head.steam == attacker.steam) &&
|
||
(head.ctf_flags & (CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2)) &&
|
||
(head != attacker) && // self defense
|
||
(!flag_carrier_radius) ) {
|
||
// attacker was near his own flag carrier
|
||
attacker.frags = attacker.frags + CTF_CARRIER_PROTECT_BONUS;
|
||
flag_carrier_radius = 1;
|
||
bprint("$qc_defend_flag_carrier", attacker.netname, s);
|
||
}
|
||
}
|
||
if ((attacker.steam == TEAM1 && head.classname == "item_flag_team1") ||
|
||
(attacker.steam == TEAM2 && head.classname == "item_flag_team2") ||
|
||
head.classname == "item_flag") { // one flag mode
|
||
// attacker was near his own flag
|
||
attacker.frags = attacker.frags + CTF_FLAG_DEFENSE_BONUS;
|
||
flag_radius = 1;
|
||
if (teamplay != TEAM_CTF_ONEFLAG) {
|
||
bprint("$qc_defend_team_flag", attacker.netname, s);
|
||
} else {
|
||
bprint("$qc_defends_flag", attacker.netname);
|
||
}
|
||
}
|
||
head = head.chain;
|
||
}
|
||
|
||
// find flags or flag carriers within a radius from the target
|
||
head = findradius(targ.origin, CTF_TARGET_PROTECT_RADIUS);
|
||
while (head) {
|
||
if (head.classname == "player") {
|
||
if ( (head.steam == attacker.steam) &&
|
||
(head.ctf_flags & (CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2)) &&
|
||
(head != attacker) &&
|
||
(!flag_carrier_radius)) { // prevents redundant points awarded
|
||
// target was near attacker's flag carrier
|
||
attacker.frags = attacker.frags + CTF_CARRIER_PROTECT_BONUS;
|
||
flag_carrier_radius = 1;
|
||
bprint("$qc_defend_flag_carrier", attacker.netname, s);
|
||
}
|
||
}
|
||
if ((attacker.steam == TEAM1 && head.classname == "item_flag_team1") ||
|
||
(attacker.steam == TEAM2 && head.classname == "item_flag_team2") ||
|
||
head.classname == "item_flag" && // one flag mode
|
||
(!flag_radius)) { // prevents redundant points awarded
|
||
// target was near attacker's flag
|
||
attacker.frags = attacker.frags + CTF_FLAG_DEFENSE_BONUS;
|
||
flag_radius = 1;
|
||
if (teamplay != TEAM_CTF_ONEFLAG) {
|
||
bprint("$qc_defend_team_flag", attacker.netname, s);
|
||
} else {
|
||
bprint("$qc_defends_flag", attacker.netname);
|
||
}
|
||
}
|
||
head = head.chain;
|
||
}
|
||
};
|
||
|
||
/*
|
||
==================
|
||
TeamColorIsLegal
|
||
|
||
Return TRUE if the indicated color is legal
|
||
==================
|
||
*/
|
||
float(float color) TeamColorIsLegal =
|
||
{
|
||
// All colors are legal if teamplay is not CTF
|
||
if( teamplay < TEAM_CTF) {
|
||
if (color > 0)
|
||
return TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
// In regular CTF and CTF_ONEFLAG, only two colors are legal
|
||
if (teamplay == TEAM_CTF || teamplay == TEAM_CTF_ONEFLAG)
|
||
if (color == TEAM1 || color == TEAM2)
|
||
return TRUE;
|
||
else
|
||
return FALSE;
|
||
|
||
// In ALT CTF, three colors are legal
|
||
if (teamplay == TEAM_CTF_ALT)
|
||
if (color == TEAM1 || color == TEAM2 || color == TEAM3)
|
||
return TRUE;
|
||
else
|
||
return FALSE;
|
||
|
||
// dunno what teamplay we're in, let'em all be ok
|
||
return TRUE;
|
||
};
|
||
|
||
/* TeamSetSkin - set the skin of the player model to the
|
||
apropriate skin based on team and teamplay settings.
|
||
*/
|
||
void() TeamSetSkin =
|
||
{
|
||
self.skin = 0;
|
||
if (deathmatch)
|
||
{
|
||
if (teamplay >= TEAM_CTF)
|
||
self.skin = 1;
|
||
}
|
||
/*
|
||
if ( deathmatch )
|
||
{
|
||
if ( teamplay >= TEAM_CTF )
|
||
{
|
||
// if (self.team == TEAM3)
|
||
// self.skin = 2;
|
||
// else
|
||
self.skin = 1;
|
||
}
|
||
if ( teamplay < TEAM_CTF )
|
||
self.skin = 1;
|
||
else
|
||
{
|
||
if (self.team == TEAM1)
|
||
self.skin = 2;
|
||
else if (self.team == TEAM2)
|
||
self.skin = 3;
|
||
else if (self.team == TEAM3)
|
||
self.skin = 4;
|
||
}
|
||
}
|
||
*/
|
||
};
|
||
|
||
/*
|
||
==================
|
||
TeamCheckTeam
|
||
|
||
Check if the team self is on is legal, and put self in a legal team if not.
|
||
==================
|
||
*/
|
||
void() TeamCheckTeam =
|
||
{
|
||
local float team1count;
|
||
local float team2count;
|
||
local float team3count;
|
||
local float newcolor;
|
||
local float t;
|
||
local entity p;
|
||
local string n;
|
||
|
||
if (self.steam >= 0 || teamplay < TEAM_CTF) {
|
||
if(TeamColorIsLegal(self.team)) {
|
||
self.steam = self.team;
|
||
TeamSetSkin();
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Assign the player to a team.
|
||
|
||
// Sum the players on all the teams.
|
||
team1count = 0;
|
||
team2count = 0;
|
||
team3count = 0;
|
||
|
||
p = find (world, classname, "player");
|
||
|
||
while(p) {
|
||
if (p != self) {
|
||
if (p.steam == TEAM1)
|
||
team1count = team1count + 1;
|
||
else if (p.steam == TEAM2)
|
||
team2count = team2count + 1;
|
||
else if (p.steam == TEAM3)
|
||
team3count = team3count + 1;
|
||
}
|
||
p = find(p, classname, "player");
|
||
}
|
||
|
||
// Find the team with the least players.
|
||
newcolor = TEAM1;
|
||
t = team1count;
|
||
|
||
if (team2count < t || (team2count == t && random() < 0.5)) {
|
||
newcolor = TEAM2;
|
||
t = team2count;
|
||
}
|
||
|
||
// in CTF_ALT, there's three teams
|
||
team3count = team3count * 2; // grey team only gets half as many players
|
||
if (teamplay == TEAM_CTF_ALT && team3count < t) {
|
||
newcolor = TEAM3;
|
||
t = team3count;
|
||
}
|
||
|
||
// Put the player on a the new team.
|
||
self.ctf_flags = self.ctf_flags | CTF_FLAG_STUFF_COLOR;
|
||
|
||
n = GetCTFTeam(newcolor);
|
||
sprint(self, "$qc_assigned_team", n);
|
||
|
||
self.steam = newcolor; // Remember what team we're on
|
||
self.team = newcolor;
|
||
TeamSetSkin();
|
||
};
|
||
|
||
/* Check for team changing and perform whatever actions are neccessary. */
|
||
void() TeamCheckLock =
|
||
{
|
||
local float n;
|
||
local string s;
|
||
|
||
if (!deathmatch || teamplay < TEAM_CTF) {
|
||
// all colors are legal, no force
|
||
self.steam = self.team;
|
||
return;
|
||
}
|
||
|
||
if (self.ctf_flags & CTF_FLAG_STUFF_COLOR) {
|
||
self.ctf_flags = self.ctf_flags - CTF_FLAG_STUFF_COLOR;
|
||
stuffcmd(self, "color ");
|
||
n = self.steam - 1;
|
||
s = ftos(n);
|
||
stuffcmd(self, s);
|
||
stuffcmd(self, "\n");
|
||
TeamSetSkin();
|
||
return;
|
||
}
|
||
|
||
if (!TeamColorIsLegal(self.team) && self.team == self.steam)
|
||
self.steam = -1; // full reset
|
||
|
||
// Check to see if the player has changed colors
|
||
if (self.team != self.steam) {
|
||
if (self.steam >= 0) {
|
||
if (TeamColorIsLegal(self.steam)) {
|
||
|
||
if (!(cvar("gamecfg") & GAMECFG_ALLOW_CHG)) {
|
||
// changing teams sucks, kill him
|
||
|
||
// if he has tried to change teams several
|
||
// times, kick him off the server.
|
||
if (self.suicide_count > 3) {
|
||
sprint(self, "$qc_color_games");
|
||
stuffcmd(self, "disconnect\n");
|
||
bprint("$qc_death_color_sense", self.netname);
|
||
}
|
||
// case base respawn
|
||
if (self.ctf_killed != 1)
|
||
self.ctf_killed = 2;
|
||
T_Damage(self,self,self,1000); // Kill the player
|
||
// trying to change teams counts as a suicide
|
||
self.suicide_count = self.suicide_count + 1;
|
||
|
||
sprint(self, "$qc_cannot_change_teams");
|
||
stuffcmd(self, "color ");
|
||
n = self.steam - 1;
|
||
s = ftos(n);
|
||
stuffcmd(self, s);
|
||
stuffcmd(self, "\n");
|
||
self.team = self.steam;
|
||
return;
|
||
}
|
||
} else {
|
||
// If we're on an illegal team, force a change.
|
||
self.steam = -50;
|
||
}
|
||
}
|
||
|
||
if (self.steam > 0) {
|
||
// case base respawn
|
||
if (self.ctf_killed != 1)
|
||
self.ctf_killed = 2;
|
||
T_Damage(self,self,self,1000); // Kill the player
|
||
}
|
||
self.frags = 0; // Zero out frags
|
||
TeamCheckTeam(); // re-assignment
|
||
}
|
||
};
|
||
|
||
/* Toss out a backpack containing some ammo from your current weapon,
|
||
and any weapons you don't have.
|
||
*/
|
||
void() TossBackpack =
|
||
{
|
||
local entity item;
|
||
|
||
// If we don't have any ammo, return
|
||
if(self.currentammo <= 0)
|
||
return;
|
||
|
||
// only valid in teamplay modes
|
||
if (teamplay < 1)
|
||
return;
|
||
|
||
item = spawn();
|
||
|
||
// See if you have the Shotgun or Super Shotgun on
|
||
if ((self.weapon == IT_SHOTGUN) || (self.weapon == IT_SUPER_SHOTGUN)) {
|
||
if( self.ammo_shells1 >= 20 ) {
|
||
item.ammo_shells1 = 20;
|
||
self.ammo_shells1 = self.ammo_shells1 - 20;
|
||
}
|
||
else
|
||
{
|
||
item.ammo_shells1 = self.ammo_shells1;
|
||
self.ammo_shells1 = 0;
|
||
}
|
||
}
|
||
|
||
// See if you have neither the Shotgun or Super Shotgun
|
||
if ( !(self.items & IT_SHOTGUN) && !(self.items & IT_SUPER_SHOTGUN)) {
|
||
if( self.ammo_shells1 >= 20 ) {
|
||
item.ammo_shells1 = 20;
|
||
self.ammo_shells1 = self.ammo_shells1 - 20;
|
||
} else {
|
||
item.ammo_shells1 = self.ammo_shells1;
|
||
self.ammo_shells1 = 0;
|
||
}
|
||
}
|
||
|
||
// See if we are using a nailgun
|
||
if ((self.weapon == IT_NAILGUN) || (self.weapon == IT_SUPER_NAILGUN) ) {
|
||
if( self.ammo_nails1 >= 20 ) {
|
||
item.ammo_nails1 = 20;
|
||
self.ammo_nails1 = self.ammo_nails1 - 20;
|
||
} else {
|
||
item.ammo_nails1 = self.ammo_nails1;
|
||
self.ammo_nails1 = 0;
|
||
}
|
||
}
|
||
|
||
// See if we are using the lava nailguns
|
||
if ((self.weapon == IT_LAVA_NAILGUN) || (self.weapon == IT_LAVA_SUPER_NAILGUN) ) {
|
||
if( self.ammo_lava_nails >= 20 ) {
|
||
item.ammo_lava_nails = 20;
|
||
self.ammo_lava_nails = self.ammo_lava_nails - 20;
|
||
} else {
|
||
item.ammo_lava_nails = self.ammo_lava_nails;
|
||
self.ammo_lava_nails = 0;
|
||
}
|
||
}
|
||
|
||
// Check to see if we have neither nailgun
|
||
if (!(self.items & IT_NAILGUN) && !(self.items & IT_SUPER_NAILGUN)) {
|
||
// put both regular and lava nails in
|
||
if (self.ammo_nails1 >= 20) {
|
||
item.ammo_nails1 = 20;
|
||
self.ammo_nails1 = self.ammo_nails1 - 20;
|
||
} else {
|
||
item.ammo_nails1 = self.ammo_nails1;
|
||
self.ammo_nails1 = 0;
|
||
}
|
||
if( self.ammo_lava_nails >= 20 ) {
|
||
item.ammo_lava_nails = 20;
|
||
self.ammo_lava_nails = self.ammo_lava_nails - 20;
|
||
} else {
|
||
item.ammo_lava_nails = self.ammo_lava_nails;
|
||
self.ammo_lava_nails = 0;
|
||
}
|
||
}
|
||
|
||
// See if we are using a grenade or rocket launcher
|
||
if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_ROCKET_LAUNCHER)) {
|
||
if( self.ammo_rockets1 >= 10 ) {
|
||
item.ammo_rockets1 = 10;
|
||
self.ammo_rockets1 = self.ammo_rockets1 - 10;
|
||
} else {
|
||
item.ammo_rockets1 = self.ammo_rockets1;
|
||
self.ammo_rockets1 = 0;
|
||
}
|
||
}
|
||
|
||
// See if we are using the multi grenade or rocket launcher
|
||
if ((self.weapon == IT_MULTI_GRENADE) || (self.weapon == IT_MULTI_ROCKET)) {
|
||
if (self.ammo_multi_rockets >= 10 ) {
|
||
item.ammo_multi_rockets = 10;
|
||
self.ammo_multi_rockets = self.ammo_multi_rockets - 10;
|
||
} else {
|
||
item.ammo_multi_rockets = self.ammo_multi_rockets;
|
||
self.ammo_multi_rockets = 0;
|
||
}
|
||
}
|
||
|
||
// See if we have neither the Grenade or rocket launcher
|
||
if ( !(self.items & IT_GRENADE_LAUNCHER) && !(self.items & IT_ROCKET_LAUNCHER) ) {
|
||
if( self.ammo_rockets1 >= 10 ) {
|
||
item.ammo_rockets1 = 10;
|
||
self.ammo_rockets1 = self.ammo_rockets1 - 10;
|
||
} else {
|
||
item.ammo_rockets1 = self.ammo_rockets1;
|
||
self.ammo_rockets1 = 0;
|
||
}
|
||
if (self.ammo_multi_rockets >= 10 ) {
|
||
item.ammo_multi_rockets = 10;
|
||
self.ammo_multi_rockets = self.ammo_multi_rockets - 10;
|
||
} else {
|
||
item.ammo_multi_rockets = self.ammo_multi_rockets;
|
||
self.ammo_multi_rockets = 0;
|
||
}
|
||
}
|
||
|
||
// See if we're using the lightning gun
|
||
if (self.weapon == IT_LIGHTNING) {
|
||
if( self.ammo_cells1 >= 20 ) {
|
||
item.ammo_cells1 = 20;
|
||
self.ammo_cells1 = self.ammo_cells1 - 20;
|
||
} else {
|
||
item.ammo_cells1 = self.ammo_cells1;
|
||
self.ammo_cells1 = 0;
|
||
}
|
||
}
|
||
|
||
// see if we are using the plasma gun
|
||
if (self.weapon == IT_PLASMA_GUN) {
|
||
if( self.ammo_plasma >= 10 ) {
|
||
item.ammo_plasma = 10;
|
||
self.ammo_plasma = self.ammo_plasma - 10;
|
||
} else {
|
||
item.ammo_plasma = self.ammo_plasma;
|
||
self.ammo_plasma = 0;
|
||
}
|
||
}
|
||
|
||
// see if we don't have the lightning gun
|
||
if (!(self.items & IT_LIGHTNING)) {
|
||
if( self.ammo_cells1 >= 20 ) {
|
||
item.ammo_cells1 = 20;
|
||
self.ammo_cells1 = self.ammo_cells1 - 20;
|
||
} else {
|
||
item.ammo_cells1 = self.ammo_cells1;
|
||
self.ammo_cells1 = 0;
|
||
}
|
||
if( self.ammo_plasma >= 10 ) {
|
||
item.ammo_plasma = 10;
|
||
self.ammo_plasma = self.ammo_plasma - 10;
|
||
} else {
|
||
item.ammo_plasma = self.ammo_plasma;
|
||
self.ammo_plasma = 0;
|
||
}
|
||
}
|
||
|
||
if (item.ammo_shells1 + item.ammo_nails1 + item.ammo_lava_nails +
|
||
item.ammo_rockets1 + item.ammo_multi_rockets + item.ammo_cells1 +
|
||
item.ammo_plasma == 0) {
|
||
sprint(self, "$qc_no_ammo_available");
|
||
remove(item);
|
||
return;
|
||
}
|
||
|
||
item.owner = self;
|
||
makevectors(self.v_angle);
|
||
|
||
setorigin(item, self.origin + '0 0 16');
|
||
item.velocity = aim(self, 1000);
|
||
item.velocity = item.velocity * 500;
|
||
item.flags = FL_ITEM;
|
||
item.solid = SOLID_TRIGGER;
|
||
item.movetype = MOVETYPE_BOUNCE;
|
||
|
||
setmodel (item, "progs/backpack.mdl");
|
||
setsize(item, '-16 -16 0', '16 16 56');
|
||
item.touch = BackpackTouch;
|
||
item.nextthink = time + 120; // remove after 2 minutes
|
||
item.think = SUB_Remove;
|
||
|
||
W_SetCurrentAmmo();
|
||
};
|
||
|
||
void() Team_weapon_touch =
|
||
{
|
||
local float hadammo, best, new, old;
|
||
local entity stemp;
|
||
|
||
if (!(other.flags & FL_CLIENT))
|
||
return;
|
||
// Don't let the owner pick up his own weapon for a second.
|
||
if ((other == self.owner) && ((self.nextthink - time) > 119))
|
||
return;
|
||
|
||
// if the player was using his best weapon, change up to the new one if better
|
||
stemp = self;
|
||
self = other;
|
||
best = W_BestWeapon();
|
||
self = stemp;
|
||
|
||
if (self.classname == "weapon_nailgun")
|
||
new = IT_NAILGUN;
|
||
else if (self.classname == "weapon_supernailgun")
|
||
new = IT_SUPER_NAILGUN;
|
||
else if (self.classname == "weapon_supershotgun")
|
||
new = IT_SUPER_SHOTGUN;
|
||
else if (self.classname == "weapon_rocketlauncher")
|
||
new = IT_ROCKET_LAUNCHER;
|
||
else if (self.classname == "weapon_grenadelauncher")
|
||
new = IT_GRENADE_LAUNCHER;
|
||
else if (self.classname == "weapon_lightning")
|
||
new = IT_LIGHTNING;
|
||
else
|
||
objerror ("Team_weapon_touch: unknown classname");
|
||
|
||
sprint(other, "$qc_got_item", self.netname);
|
||
// weapon touch sound
|
||
sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
|
||
stuffcmd (other, "bf\n");
|
||
|
||
bound_other_ammo ();
|
||
|
||
// change to the weapon
|
||
old = other.items;
|
||
other.items = other.items | new;
|
||
|
||
remove(self);
|
||
self = other;
|
||
|
||
if (!deathmatch)
|
||
self.weapon = new;
|
||
else
|
||
Deathmatch_Weapon (old, new);
|
||
|
||
EnableComboWeapons(self);
|
||
UpdateAmmoCounts(self);
|
||
|
||
W_SetCurrentAmmo();
|
||
|
||
// dropped weapon doesn't target, so no need to call UseTargets
|
||
};
|
||
|
||
void() TossWeapon =
|
||
{
|
||
local entity item;
|
||
|
||
if (deathmatch != 1)
|
||
return; // only in deathmatch 1
|
||
|
||
// only valid in teamplay modes
|
||
if (teamplay < 1)
|
||
return;
|
||
|
||
if((self.weapon == IT_AXE) || (self.weapon == IT_SHOTGUN) ||
|
||
(self.weapon == IT_GRAPPLE))
|
||
return;
|
||
|
||
item = spawn();
|
||
item.owner = self;
|
||
makevectors(self.v_angle);
|
||
item.weapon = 0;
|
||
|
||
setorigin(item, self.origin + '0 0 16');
|
||
item.velocity = aim(self, 1000);
|
||
item.velocity = item.velocity * 500;
|
||
item.flags = FL_ITEM;
|
||
item.solid = SOLID_TRIGGER;
|
||
item.movetype = MOVETYPE_BOUNCE;
|
||
|
||
if(self.weapon == IT_SUPER_SHOTGUN)
|
||
{
|
||
setmodel (item, "progs/g_shot.mdl");
|
||
item.weapon = IT_SUPER_SHOTGUN;
|
||
item.netname = "$qc_double_shotgun";
|
||
item.classname = "weapon_supershotgun";
|
||
self.items = self.items - IT_SUPER_SHOTGUN;
|
||
}
|
||
|
||
if( self.weapon == IT_NAILGUN || self.weapon == IT_LAVA_NAILGUN )
|
||
{
|
||
setmodel (item, "progs/g_nail.mdl");
|
||
item.weapon = IT_NAILGUN;
|
||
item.netname = "$qc_nailgun";
|
||
item.classname = "weapon_nailgun";
|
||
self.items = self.items - (self.items & (IT_NAILGUN | IT_LAVA_NAILGUN));
|
||
}
|
||
|
||
if( self.weapon == IT_SUPER_NAILGUN || self.weapon == IT_LAVA_SUPER_NAILGUN)
|
||
{
|
||
setmodel (item, "progs/g_nail2.mdl");
|
||
item.weapon = IT_SUPER_NAILGUN;
|
||
item.netname = "$qc_super_nailgun";
|
||
item.classname = "weapon_supernailgun";
|
||
self.items = self.items - (self.items & (IT_SUPER_NAILGUN | IT_LAVA_SUPER_NAILGUN));
|
||
}
|
||
|
||
if( self.weapon == IT_GRENADE_LAUNCHER || self.weapon == IT_MULTI_GRENADE)
|
||
{
|
||
setmodel (item, "progs/g_rock.mdl");
|
||
item.weapon = IT_GRENADE_LAUNCHER;
|
||
item.netname = "$qc_grenade_launcher";
|
||
item.classname = "weapon_grenadelauncher";
|
||
self.items = self.items - (self.items & (IT_GRENADE_LAUNCHER | IT_MULTI_GRENADE));
|
||
}
|
||
|
||
if( self.weapon == IT_ROCKET_LAUNCHER || self.weapon == IT_MULTI_ROCKET)
|
||
{
|
||
setmodel (item, "progs/g_rock2.mdl");
|
||
item.weapon = IT_ROCKET_LAUNCHER;
|
||
item.netname = "$qc_rocket_launcher";
|
||
item.classname = "weapon_rocketlauncher";
|
||
self.items = self.items - (self.items & (IT_ROCKET_LAUNCHER | IT_MULTI_ROCKET));
|
||
}
|
||
|
||
if( self.weapon == IT_LIGHTNING || self.weapon == IT_PLASMA_GUN)
|
||
{
|
||
setmodel (item, "progs/g_light.mdl");
|
||
item.weapon = IT_LIGHTNING;
|
||
item.netname = "$qc_thunderbolt";
|
||
item.classname = "weapon_lightning";
|
||
self.items = self.items - (self.items & (IT_LIGHTNING | IT_PLASMA_GUN));
|
||
}
|
||
setsize(item, '-16 -16 0', '16 16 56');
|
||
item.touch = Team_weapon_touch;
|
||
item.think = SUB_Remove;
|
||
item.nextthink = time + 120;
|
||
|
||
self.weapon = W_BestWeapon();
|
||
W_SetCurrentAmmo();
|
||
};
|
||
|
||
void(entity flg) RegenFlag =
|
||
{
|
||
flg.movetype = MOVETYPE_TOSS;
|
||
flg.solid = SOLID_TRIGGER;
|
||
sound (flg, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM); // play respawn sound
|
||
setorigin(flg, flg.oldorigin);
|
||
flg.angles = flg.mangle;
|
||
flg.cnt = FLAG_AT_BASE; // it's at home base
|
||
flg.owner = world;
|
||
};
|
||
|
||
void(entity flg) TeamReturnFlag =
|
||
{
|
||
local entity p;
|
||
local string n;
|
||
|
||
RegenFlag(flg);
|
||
|
||
p = find(world, classname, "player");
|
||
while (p != world) {
|
||
if (teamplay == TEAM_CTF_ONEFLAG) // one flag mode?
|
||
centerprint(p, "$qc_flag_returned");
|
||
else {
|
||
if (teamplay == TEAM_CTF_ALT) {
|
||
if (flg.team == TEAM1)
|
||
centerprint(p, "<EFBFBD><EFBFBD><EFBFBD> flag has been returned to base!\n");
|
||
else if (flg.team == TEAM2)
|
||
centerprint(p, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> flag has been returned to base!\n");
|
||
else
|
||
centerprint(p, "$qc_some_flag_returned_base");
|
||
} else {
|
||
if (p.steam != flg.team)
|
||
centerprint(p, "$qc_enemy_flag_returned_base");
|
||
else if (p.steam == flg.team)
|
||
centerprint(p, "$qc_your_flag_returned_base");
|
||
}
|
||
}
|
||
p = find(p, classname, "player");
|
||
}
|
||
};
|
||
|
||
void () TeamRegenFlags =
|
||
{
|
||
local entity f;
|
||
|
||
if (teamplay == TEAM_CTF_ONEFLAG) {
|
||
f = find(world, classname, "item_flag");
|
||
if (f != world)
|
||
RegenFlag(f);
|
||
return;
|
||
}
|
||
|
||
f = find(world, classname, "item_flag_team1");
|
||
if (f != world)
|
||
RegenFlag(f);
|
||
f = find(world, classname, "item_flag_team2");
|
||
if (f != world)
|
||
RegenFlag(f);
|
||
};
|
||
|
||
void(entity flg) TeamDropFlag =
|
||
{
|
||
local entity item, f, oself;
|
||
local entity p;
|
||
|
||
p = flg.owner;
|
||
|
||
bprint(p.netname);
|
||
if (teamplay == TEAM_CTF_ONEFLAG)
|
||
bprint(" <20><><EFBFBD><EFBFBD> the flag!\n");
|
||
else {
|
||
if (flg.team == TEAM1)
|
||
bprint(" <20><><EFBFBD><EFBFBD> the <20><><EFBFBD> flag!\n"); // red
|
||
else
|
||
bprint(" <20><><EFBFBD><EFBFBD> the <20><><EFBFBD><EFBFBD> flag!\n"); // blue
|
||
}
|
||
|
||
setorigin(flg, p.origin - '0 0 24');
|
||
flg.cnt = FLAG_DROPPED;
|
||
flg.velocity_z = 300;
|
||
flg.velocity_x = 0;
|
||
flg.velocity_y = 0;
|
||
flg.flags = FL_ITEM | FL_OBJECTIVE;
|
||
flg.solid = SOLID_TRIGGER;
|
||
flg.movetype = MOVETYPE_TOSS;
|
||
setsize(flg, '-16 -16 0', '16 16 74');
|
||
// return it after so long
|
||
flg.super_time = time + CTF_FLAG_RETURN_TIME;
|
||
};
|
||
|
||
void(entity player) TeamDropFlagOfPlayer =
|
||
{
|
||
local string kn;
|
||
local entity e;
|
||
|
||
if (teamplay == TEAM_CTF_ONEFLAG && (player.ctf_flags & CTF_FLAG_FLAG))
|
||
kn = "item_flag";
|
||
else if (player.ctf_flags & CTF_FLAG_TEAM1)
|
||
kn = "item_flag_team1";
|
||
else if (player.ctf_flags & CTF_FLAG_TEAM2)
|
||
kn = "item_flag_team2";
|
||
else
|
||
return; // doesn't have a flg
|
||
player.ctf_flags = player.ctf_flags -
|
||
(player.ctf_flags & (CTF_FLAG_FLAG | CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2));
|
||
e = find(world, classname, kn);
|
||
if (e != world)
|
||
TeamDropFlag(e);
|
||
};
|
||
|
||
// A flag was touched. In one flag mode, the player always just picks it up
|
||
// (the flagbase models at each base will cause the score). In two flag mode,
|
||
// it could be the guy returning his flag, or the guy getting the enemy flag
|
||
// Three team mode gets more complicated as the third team touches the
|
||
// flagbase to score
|
||
void() TeamFlagTouch =
|
||
{
|
||
local entity p, oself;
|
||
|
||
if (other.classname != "player")
|
||
return;
|
||
if (other.health <= 0)
|
||
return;
|
||
|
||
if (other.team != other.steam)
|
||
return; // something is fishy, somebody is playing with colors
|
||
|
||
if (self.cnt == FLAG_CARRIED)
|
||
return; // huh?
|
||
|
||
// Ok, first up, let's do it for one flag mode
|
||
if (teamplay == TEAM_CTF_ONEFLAG) {
|
||
// in one flag mode, we always pick up the flag. The touch of the
|
||
// flagbase entities does the scoring
|
||
bprint(other.netname);
|
||
bprint(" <20><><EFBFBD> the flag!\n");
|
||
if (CTF_FLAG_BONUS)
|
||
other.frags = other.frags + CTF_FLAG_BONUS;
|
||
//centerprint(other, "$qc_got_flag_enemy_base");
|
||
centerprint(other, "<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>\n\n<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>\n");
|
||
|
||
sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
|
||
|
||
other.ctf_flags = other.ctf_flags | CTF_FLAG_FLAG;
|
||
other.items = other.items | self.items;
|
||
other.ctf_flagsince = time;
|
||
|
||
// pick up the flag
|
||
self.cnt = FLAG_CARRIED;
|
||
self.movetype = MOVETYPE_NOCLIP;
|
||
self.solid = SOLID_NOT;
|
||
self.owner = other;
|
||
|
||
p = find(world, classname, "player");
|
||
while (p != world) {
|
||
if (p != other)
|
||
centerprint(p, "$qc_flag_taken");
|
||
p = find(p, classname, "player");
|
||
}
|
||
return;
|
||
}
|
||
|
||
// Regular and Alt CTF mode
|
||
if (teamplay != TEAM_CTF && teamplay != TEAM_CTF_ALT)
|
||
return; // odd, but ignore it
|
||
|
||
if (self.team == other.steam) {
|
||
// same team, if the flag is *not* at the base, return
|
||
// it to base. we overload the 'cnt' field for this
|
||
if (self.cnt == FLAG_AT_BASE) {
|
||
// the flag is at home base. if the player has the enemy
|
||
// flag, he's just won!
|
||
if ((self.team == TEAM1 && (other.ctf_flags & CTF_FLAG_TEAM2)) ||
|
||
(self.team == TEAM2 && (other.ctf_flags & CTF_FLAG_TEAM1))) {
|
||
bprint(other.netname);
|
||
if (other.team == TEAM1)
|
||
bprint(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> the <20><><EFBFBD><EFBFBD> flag!\n"); // blue
|
||
else
|
||
bprint(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> the <20><><EFBFBD> flag!\n"); // red
|
||
other.items = other.items - (other.items & (IT_KEY1 | IT_KEY2));
|
||
|
||
sound (other, CHAN_VOICE, "misc/flagcap.wav", 1, ATTN_NONE);
|
||
|
||
// other gets another 10 frag bonus
|
||
other.frags = other.frags + CTF_CAPTURE_BONUS;
|
||
|
||
// Ok, let's do the player loop, hand out the bonuses
|
||
p = find(world, classname, "player");
|
||
while (p != world) {
|
||
self = p;
|
||
if (self.team == other.team && self != other)
|
||
self.frags = self.frags + CTF_TEAM_BONUS;
|
||
if (self.team != other.team) {
|
||
if (self.team == TEAM3)
|
||
if (other.team == TEAM1)
|
||
centerprint(self, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> flag was captured!\n");
|
||
else
|
||
centerprint(self, "<EFBFBD><EFBFBD><EFBFBD> flag was captured!\n");
|
||
else
|
||
centerprint(self, "$qc_your_flag_captured");
|
||
// reset the last_hurt_carrier variable in all enemy players, so that you don't get
|
||
// bonuses for defending the flag carrier if the flag carrier has already
|
||
// completed a capture
|
||
self.ctf_lasthurtcarrier = -5;
|
||
} else if (self.team == other.team) {
|
||
// done to all players on the capturing team
|
||
centerprint(self, "$qc_your_team_captured");
|
||
// award extra points for capture assists
|
||
if (self.ctf_lastreturnedflag + CTF_RETURN_FLAG_ASSIST_TIMEOUT > time) {
|
||
bprint(self.netname);
|
||
if (self.team == TEAM1)
|
||
bprint(" gets an assist for returning the <20><><EFBFBD> flag!\n");
|
||
else
|
||
bprint(" gets an assist for returning the <20><><EFBFBD><EFBFBD> flag!\n");
|
||
self.frags = self.frags + CTF_RETURN_FLAG_ASSIST_BONUS;
|
||
}
|
||
if (self.ctf_lastfraggedcarrier + CTF_FRAG_CARRIER_ASSIST_TIMEOUT > time) {
|
||
bprint(self.netname);
|
||
bprint(" gets an assist for fragging the flag carrier!\n");
|
||
self.frags = self.frags + CTF_FRAG_CARRIER_ASSIST_BONUS;
|
||
}
|
||
}
|
||
self.ctf_flags = self.ctf_flags - (self.ctf_flags &
|
||
(CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2));
|
||
p = find(p, classname, "player");
|
||
}
|
||
// respawn flags
|
||
TeamRegenFlags();
|
||
return;
|
||
}
|
||
return; // its at home base already
|
||
}
|
||
// hey, its not home. return it by teleporting it back
|
||
bprint(other.netname);
|
||
if (other.team == TEAM1)
|
||
bprint(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> the <20><><EFBFBD> flag!\n"); // red
|
||
else
|
||
bprint(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> the <20><><EFBFBD><EFBFBD> flag!\n"); // blue
|
||
other.frags = other.frags + CTF_RECOVERY_BONUS;
|
||
other.ctf_lastreturnedflag = time;
|
||
sound (other, CHAN_ITEM, self.noise1, 1, ATTN_NORM);
|
||
TeamReturnFlag(self);
|
||
return;
|
||
}
|
||
|
||
// if we have any flags, leave now
|
||
if (other.ctf_flags & (CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2))
|
||
return;
|
||
|
||
// hey, its not our flag, pick it up
|
||
bprint(other.netname);
|
||
if (self.team == TEAM1)
|
||
bprint(" <20><><EFBFBD> the <20><><EFBFBD> flag!\n"); // red
|
||
else
|
||
bprint(" <20><><EFBFBD> the <20><><EFBFBD><EFBFBD> flag!\n"); // blue
|
||
other.frags = other.frags + CTF_FLAG_BONUS;
|
||
|
||
// if in three team, messages are a little different
|
||
if (other.team == TEAM3) {
|
||
// centerprint(other, "$qc_got_flag_other");
|
||
centerprint(other, "<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>\n\n<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>\n");
|
||
} else {
|
||
// centerprint(other, "$qc_got_flag_return_base");
|
||
centerprint(other, "<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>\n\n<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>\n");
|
||
}
|
||
sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
|
||
|
||
if (self.team == TEAM1)
|
||
other.ctf_flags = other.ctf_flags | CTF_FLAG_TEAM1;
|
||
else
|
||
other.ctf_flags = other.ctf_flags | CTF_FLAG_TEAM2;
|
||
other.items = other.items | self.items;
|
||
|
||
other.ctf_flagsince = time;
|
||
|
||
// pick up the flag
|
||
self.cnt = FLAG_CARRIED;
|
||
self.movetype = MOVETYPE_NOCLIP;
|
||
self.solid = SOLID_NOT;
|
||
self.owner = other;
|
||
|
||
// PGM Fix - 03/06/97 Made it work right in three team.
|
||
p = find(world, classname, "player");
|
||
while (p != world)
|
||
{
|
||
if (p != other)
|
||
{
|
||
if (p.steam == self.team)
|
||
{
|
||
centerprint(p, "$qc_your_flag_taken");
|
||
}
|
||
else if (p.steam == other.team)
|
||
{
|
||
if (self.team == TEAM1)
|
||
centerprint(p, "Your team has the <20><><EFBFBD> flag!\n"); // Red Flag
|
||
else
|
||
centerprint(p, "Your team has the <20><><EFBFBD><EFBFBD> flag!\n"); // Blue Flag
|
||
}
|
||
else
|
||
{
|
||
if (self.team == TEAM1)
|
||
if (other.steam == TEAM2)
|
||
centerprint(p, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> team has the <20><><EFBFBD> flag!\n"); // Blue has red
|
||
else // must be team3
|
||
centerprint(p, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> team has the <20><><EFBFBD> flag!\n"); // grey has red
|
||
else
|
||
if (other.steam == TEAM1)
|
||
centerprint(p, "<EFBFBD><EFBFBD><EFBFBD> team has the <20><><EFBFBD><EFBFBD> flag!\n"); // red has blue
|
||
else // must be team3
|
||
centerprint(p, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> team has the <20><><EFBFBD><EFBFBD> flag!\n");// grey has blue
|
||
}
|
||
}
|
||
p = find(p, classname, "player");
|
||
}
|
||
};
|
||
|
||
// A flagbase was touched. In one flag mode, this is how a capture is made.
|
||
// in three team mode, only team3 touches this. In regular CTF, this is
|
||
// ignored
|
||
void() TeamFlagBaseTouch =
|
||
{
|
||
local entity p, oself, f;
|
||
|
||
if (other.classname != "player")
|
||
return;
|
||
if (other.health <= 0)
|
||
return;
|
||
if (other.team != other.steam)
|
||
return; // something is fishy, somebody is playing with colors
|
||
|
||
// Ok, first up, let's do it for one flag mode
|
||
if (teamplay == TEAM_CTF_ONEFLAG) {
|
||
// ok, if they guy touching it has the flag and this is his
|
||
// base, capture!
|
||
if (((self.team == TEAM1 && other.steam == TEAM2) ||
|
||
(self.team == TEAM2 && other.steam == TEAM1)) &&
|
||
(other.ctf_flags & CTF_FLAG_FLAG)) {
|
||
// he just touched enemy base, capture it
|
||
bprint(other.netname);
|
||
bprint(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> the flag!\n"); // blue
|
||
other.items = other.items - (other.items & (IT_KEY1 | IT_KEY2));
|
||
sound (other, CHAN_VOICE, "misc/flagcap.wav", 1, ATTN_NONE);
|
||
|
||
// other gets another 10 frag bonus
|
||
other.frags = other.frags + CTF_CAPTURE_BONUS;
|
||
|
||
// Ok, let's do the player loop, hand out the bonuses
|
||
p = find(world, classname, "player");
|
||
while (p != world) {
|
||
self = p;
|
||
if (self.team == other.team && self != other)
|
||
self.frags = self.frags + CTF_TEAM_BONUS;
|
||
if (self.team != other.team) {
|
||
self.ctf_lasthurtcarrier = -5;
|
||
} else if (self.team == other.team) {
|
||
// award extra points for capture assists
|
||
if (self.ctf_lastfraggedcarrier + CTF_FRAG_CARRIER_ASSIST_TIMEOUT > time) {
|
||
bprint(self.netname);
|
||
bprint(" gets an assist for fragging the flag carrier!\n");
|
||
self.frags = self.frags + CTF_FRAG_CARRIER_ASSIST_BONUS;
|
||
}
|
||
}
|
||
self.ctf_flags = self.ctf_flags - (self.ctf_flags & CTF_FLAG_FLAG);
|
||
p = find(p, classname, "player");
|
||
}
|
||
// respawn flags
|
||
TeamRegenFlags();
|
||
return;
|
||
}
|
||
}
|
||
|
||
// in three team mode (TEAM_CTF_ALT) and we're on team3, see if we capture
|
||
if (teamplay != TEAM_CTF_ALT || other.steam != TEAM3)
|
||
return;
|
||
|
||
if (((other.ctf_flags & CTF_FLAG_TEAM1) && (self.team == TEAM2)) ||
|
||
((other.ctf_flags & CTF_FLAG_TEAM2) && (self.team == TEAM1))) {
|
||
// third team captured
|
||
|
||
bprint(other.netname);
|
||
if (self.team == TEAM1)
|
||
bprint(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> the <20><><EFBFBD><EFBFBD> flag!\n"); // blue
|
||
else
|
||
bprint(" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> the <20><><EFBFBD> flag!\n"); // red
|
||
other.items = other.items - (other.items & (IT_KEY1 | IT_KEY2));
|
||
|
||
sound (other, CHAN_VOICE, "misc/flagcap.wav", 1, ATTN_NONE);
|
||
|
||
// other gets another 10 frag bonus
|
||
other.frags = other.frags + CTF_ALT_CAPTURE_BONUS;
|
||
|
||
// Ok, let's do the player loop, hand out the bonuses
|
||
p = find(world, classname, "player");
|
||
while (p != world) {
|
||
self = p;
|
||
if (self.team == other.team && self != other)
|
||
self.frags = self.frags + CTF_ALT_TEAM_BONUS;
|
||
if (self.team != other.team) {
|
||
if ((other.ctf_flags & CTF_FLAG_TEAM1) && self.team == TEAM1)
|
||
centerprint(self, "$qc_your_flag_captured");
|
||
else if ((other.ctf_flags & CTF_FLAG_TEAM2) && self.team == TEAM2)
|
||
centerprint(self, "$qc_enemy_flag_captured");
|
||
// reset the last_hurt_carrier variable in all enemy players, so that you don't get
|
||
// bonuses for defending the flag carrier if the flag carrier has already
|
||
// completed a capture
|
||
self.ctf_lasthurtcarrier = -5;
|
||
} else if (self.team == other.team) {
|
||
// done to all players on the capturing team
|
||
centerprint(self, "$qc_your_team_captured");
|
||
}
|
||
p = find(p, classname, "player");
|
||
}
|
||
// respawn flags
|
||
if (other.ctf_flags & CTF_FLAG_TEAM1) {
|
||
f = find(world, classname, "item_flag_team1");
|
||
if (f != world)
|
||
RegenFlag(f);
|
||
} else { // must be flag2
|
||
f = find(world, classname, "item_flag_team2");
|
||
if (f != world)
|
||
RegenFlag(f);
|
||
}
|
||
other.ctf_flags = other.ctf_flags - (other.ctf_flags &
|
||
(CTF_FLAG_TEAM1 | CTF_FLAG_TEAM2));
|
||
return;
|
||
}
|
||
};
|
||
|
||
|
||
void() TeamFlagThink =
|
||
{
|
||
local entity e;
|
||
local vector v;
|
||
local float f;
|
||
local string s;
|
||
|
||
self.nextthink = time + 0.1;
|
||
|
||
if (self.cnt == FLAG_AT_BASE)
|
||
return; // just sitting around waiting to be picked up
|
||
|
||
if (self.cnt == FLAG_DROPPED) {
|
||
if (time - self.super_time > CTF_FLAG_RETURN_TIME)
|
||
TeamReturnFlag(self);
|
||
return;
|
||
}
|
||
|
||
if (self.cnt != FLAG_CARRIED)
|
||
objerror("Flag in invalid state\n");
|
||
|
||
e = self.owner;
|
||
if (e.classname != "player" || e.deadflag) {
|
||
TeamDropFlag(self);
|
||
return;
|
||
}
|
||
|
||
if (teamplay == TEAM_CTF_ONEFLAG && !(e.ctf_flags & CTF_FLAG_FLAG)) {
|
||
TeamDropFlag(self);
|
||
return;
|
||
}
|
||
// must be TEAM_CTF or TEAM_CTF_ALT
|
||
if ((!(e.ctf_flags & CTF_FLAG_TEAM1) && self.team == TEAM1) ||
|
||
(!(e.ctf_flags & CTF_FLAG_TEAM2) && self.team == TEAM2)) {
|
||
TeamDropFlag(self);
|
||
return;
|
||
}
|
||
|
||
makevectors (e.angles);
|
||
v = v_forward;
|
||
v_z = (-1) * v_z; // reverse z component
|
||
|
||
f = 14;
|
||
if (self.owner.frame >= 29 && self.owner.frame <= 40) {
|
||
if (self.owner.frame >= 29 && self.owner.frame <= 34) { //axpain
|
||
if (self.owner.frame == 29) f = f + 2;
|
||
else if (self.owner.frame == 30) f = f + 8;
|
||
else if (self.owner.frame == 31) f = f + 12;
|
||
else if (self.owner.frame == 32) f = f + 11;
|
||
else if (self.owner.frame == 33) f = f + 10;
|
||
else if (self.owner.frame == 34) f = f + 4;
|
||
} else if (self.owner.frame >= 35 && self.owner.frame <= 40) { // pain
|
||
if (self.owner.frame == 35) f = f + 2;
|
||
else if (self.owner.frame == 36) f = f + 10;
|
||
else if (self.owner.frame == 37) f = f + 10;
|
||
else if (self.owner.frame == 38) f = f + 8;
|
||
else if (self.owner.frame == 39) f = f + 4;
|
||
else if (self.owner.frame == 40) f = f + 2;
|
||
}
|
||
} else if (self.owner.frame >= 103 && self.owner.frame <= 118) {
|
||
if (self.owner.frame >= 103 && self.owner.frame <= 104) f = f + 6; //nailattack
|
||
else if (self.owner.frame >= 105 && self.owner.frame <= 106) f = f + 6; //light
|
||
else if (self.owner.frame >= 107 && self.owner.frame <= 112) f = f + 7; //rocketattack
|
||
else if (self.owner.frame >= 112 && self.owner.frame <= 118) f = f + 7; //shotattack
|
||
}
|
||
self.origin = e.origin + '0 0 -16' - f*v + v_right * 22;
|
||
self.angles = e.angles + '0 0 -45';
|
||
setorigin (self, self.origin);
|
||
self.nextthink = time + 0.01;
|
||
};
|
||
|
||
void() TeamFlagStatusReport =
|
||
{
|
||
local entity flag1, flag2, p;
|
||
local string n;
|
||
|
||
if (!deathmatch)
|
||
return;
|
||
|
||
if (teamplay != TEAM_CTF && teamplay != TEAM_CTF_ONEFLAG &&
|
||
teamplay != TEAM_CTF_ALT) {
|
||
sprint(self, "$qc_ctf_disabled");
|
||
return;
|
||
}
|
||
|
||
if (teamplay == TEAM_CTF_ONEFLAG) {
|
||
flag1 = find (world, classname, "item_flag");
|
||
if (flag1 == world)
|
||
sprint(self, "$qc_flag_missing");
|
||
else if (flag1.cnt == FLAG_AT_BASE)
|
||
sprint(self, "$qc_flag_at_base");
|
||
else if (flag1.cnt == FLAG_DROPPED)
|
||
sprint(self, "$qc_flag_lying_about");
|
||
else if (flag1.cnt == FLAG_CARRIED) {
|
||
if (flag1.owner == self)
|
||
sprint(self, "$qc_you_have_flag");
|
||
else {
|
||
sprint(self, flag1.owner.netname);
|
||
n = GetCTFTeam(flag1.owner.steam);
|
||
sprint(self, " of the ");
|
||
sprint(self, n);
|
||
sprint(self, " team has the flag!\n");
|
||
}
|
||
} else
|
||
sprint(self, "$qc_flag_screwed_up");
|
||
return;
|
||
}
|
||
|
||
// normal CTF
|
||
if (teamplay == TEAM_CTF) {
|
||
// Find the flags at home base
|
||
flag1 = find (world,classname, "item_flag_team1");
|
||
flag2 = find (world,classname, "item_flag_team2");
|
||
|
||
// If on team 2 switch meanings of flags
|
||
if (self.team != TEAM1) {
|
||
p = flag1;
|
||
flag1 = flag2;
|
||
flag2 = p;
|
||
}
|
||
|
||
if (flag1 != world && flag1.cnt == FLAG_CARRIED) {
|
||
sprint(self, flag1.owner.netname);
|
||
sprint(self, " has your flag. ");
|
||
} else {
|
||
sprint(self, "Your flag is ");
|
||
if (flag1 == world)
|
||
sprint(self, "missing!\n");
|
||
if (flag1.cnt == FLAG_AT_BASE)
|
||
sprint(self, "in your base.\n");
|
||
else if (flag1.cnt == FLAG_DROPPED)
|
||
sprint(self, "lying about.\n");
|
||
else
|
||
sprint(self, " corrupt.\n");
|
||
}
|
||
|
||
if (flag2 != world && flag2.cnt == FLAG_CARRIED) {
|
||
if (self == flag2.owner)
|
||
sprint(self, "$qc_you_have_enemy_flag");
|
||
else {
|
||
sprint(self, flag2.owner.netname);
|
||
sprint(self, " has the enemy flag.\n");
|
||
}
|
||
} else {
|
||
sprint(self, "The enemy flag is ");
|
||
if (flag2 == world)
|
||
sprint(self, "missing!\n");
|
||
if (flag2.cnt == FLAG_AT_BASE)
|
||
sprint(self, "in their base.\n");
|
||
else if (flag2.cnt == FLAG_DROPPED)
|
||
sprint(self, "lying about.\n");
|
||
else
|
||
sprint(self, " corrupt.\n");
|
||
}
|
||
}
|
||
|
||
// three team CTF
|
||
if (teamplay == TEAM_CTF_ALT) {
|
||
// Find the flags at home base
|
||
flag1 = find (world,classname, "item_flag_team1");
|
||
flag2 = find (world,classname, "item_flag_team2");
|
||
|
||
if (flag1 != world && flag1.cnt == FLAG_CARRIED) {
|
||
if (flag1.owner == self)
|
||
sprint(self, "You have the <20><><EFBFBD> flag!\n");
|
||
else {
|
||
sprint(self, flag1.owner.netname);
|
||
n = GetCTFTeam(flag1.owner.steam);
|
||
sprint(self, " of the ");
|
||
sprint(self, n);
|
||
sprint(self, " team has the <20><><EFBFBD> flag.\n");
|
||
}
|
||
} else {
|
||
if (self.steam == flag1.team)
|
||
sprint(self, "Your flag is ");
|
||
else
|
||
sprint(self, "<EFBFBD><EFBFBD><EFBFBD> flag is ");
|
||
if (flag1 == world)
|
||
sprint(self, "missing!\n");
|
||
if (flag1.cnt == FLAG_AT_BASE)
|
||
sprint(self, "at base.\n");
|
||
else if (flag1.cnt == FLAG_DROPPED)
|
||
sprint(self, "lying about.\n");
|
||
else
|
||
sprint(self, " corrupt.\n");
|
||
}
|
||
|
||
if (flag2 != world && flag2.cnt == FLAG_CARRIED) {
|
||
if (flag2.owner == self)
|
||
sprint(self, "You have the <20><><EFBFBD><EFBFBD> flag.\n");
|
||
else {
|
||
sprint(self, flag2.owner.netname);
|
||
n = GetCTFTeam(flag2.owner.steam);
|
||
sprint(self, " of the ");
|
||
sprint(self, n);
|
||
sprint(self, " team has the <20><><EFBFBD><EFBFBD> flag.\n");
|
||
}
|
||
} else {
|
||
if (self.steam == flag1.team)
|
||
sprint(self, "Your flag is ");
|
||
else
|
||
sprint(self, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> flag is ");
|
||
if (flag2 == world)
|
||
sprint(self, "missing!\n");
|
||
if (flag2.cnt == FLAG_AT_BASE)
|
||
sprint(self, "at base.\n");
|
||
else if (flag2.cnt == FLAG_DROPPED)
|
||
sprint(self, "lying about.\n");
|
||
else
|
||
sprint(self, " corrupt.\n");
|
||
}
|
||
}
|
||
};
|
||
|
||
/////////////////////////////////////////////////////////////////////////
|
||
|
||
$cd id1/models/flag
|
||
$base base
|
||
$skin skin
|
||
|
||
void() place_flag = {
|
||
self.mdl = self.model; // so it can be restored on respawn
|
||
self.flags = FL_ITEM | FL_OBJECTIVE; // make extra wide
|
||
self.solid = SOLID_TRIGGER;
|
||
self.movetype = MOVETYPE_TOSS;
|
||
self.velocity = '0 0 0';
|
||
self.origin_z = self.origin_z + 6;
|
||
self.think = TeamFlagThink;
|
||
self.touch = TeamFlagTouch;
|
||
self.nextthink = time + 0.1;
|
||
self.cnt = FLAG_AT_BASE;
|
||
self.mangle = self.angles;
|
||
self.effects = self.effects | EF_DIMLIGHT;
|
||
if (!droptofloor()) {
|
||
dprint ("Flag fell out of level at ");
|
||
dprint (vtos(self.origin));
|
||
dprint ("\n");
|
||
remove(self);
|
||
return;
|
||
}
|
||
self.oldorigin = self.origin; // save for flag return
|
||
};
|
||
|
||
void(entity flg, string cname) place_flagbase =
|
||
{
|
||
local entity oself;
|
||
|
||
teamplay = cvar("teamplay");
|
||
|
||
oself = self;
|
||
self = spawn();
|
||
self.classname = cname;
|
||
setorigin(self, flg.origin);
|
||
self.angles = flg.angles;
|
||
precache_model ("progs/ctfbase.mdl");
|
||
setmodel (self, "progs/ctfbase.mdl");
|
||
self.skin = flg.skin;
|
||
self.team = flg.team;
|
||
// setsize(self, '-8 -8 -4', '8 8 4');
|
||
setsize(self, '-8 -8 0', '8 8 8');
|
||
self.flags = FL_ITEM; // make extra wide
|
||
self.movetype = MOVETYPE_TOSS;
|
||
self.velocity = '0 0 0';
|
||
self.origin_z = self.origin_z + 6;
|
||
if (teamplay == TEAM_CTF_ONEFLAG || teamplay == TEAM_CTF_ALT) {
|
||
self.solid = SOLID_TRIGGER;
|
||
self.touch = TeamFlagBaseTouch;
|
||
} else
|
||
self.solid = SOLID_NOT;
|
||
if (!droptofloor()) {
|
||
dprint ("Flagbase fell out of level at ");
|
||
dprint (vtos(self.origin));
|
||
dprint ("\n");
|
||
remove(self);
|
||
self = oself;
|
||
return;
|
||
}
|
||
self = oself;
|
||
};
|
||
|
||
// ZOID Capture the flag
|
||
/*QUAKED item_flag_team1 (0 .5 .8) (-8 -8 -32) (8 8 24)
|
||
red team flag
|
||
Only appears in CTF teamplay
|
||
|
||
The flag waves 90 degrees off from the entity angle. If
|
||
you want the flag to point at 180, set then entity angle
|
||
to 90.
|
||
*/
|
||
void() item_flag_team1 =
|
||
{
|
||
if (!deathmatch) {
|
||
remove(self);
|
||
return;
|
||
}
|
||
|
||
teamplay = cvar("teamplay");
|
||
|
||
if (teamplay == TEAM_CTF_ONEFLAG) {
|
||
precache_sound ("misc/flagtk.wav"); // flag taken
|
||
precache_sound ("misc/flagcap.wav"); // flag capture
|
||
self.skin = 0;
|
||
self.team = TEAM1;
|
||
place_flagbase(self, "item_flagbase_team1");
|
||
remove(self);
|
||
return;
|
||
}
|
||
|
||
if (teamplay == TEAM_CTF || teamplay == TEAM_CTF_ALT) {
|
||
self.team = TEAM1;
|
||
self.items = IT_KEY2;
|
||
precache_model ("progs/ctfmodel.mdl");
|
||
setmodel (self, "progs/ctfmodel.mdl");
|
||
self.skin = 0;
|
||
precache_sound ("misc/flagtk.wav"); // flag taken
|
||
precache_sound ("misc/flagcap.wav"); // flag capture
|
||
precache_sound ("misc/flagret.wav"); // flag return
|
||
self.noise = "misc/flagtk.wav";
|
||
self.noise1 = "misc/flagret.wav";
|
||
setsize(self, '-16 -16 0', '16 16 74');
|
||
self.nextthink = time + 0.2; // items start after other solids
|
||
self.think = place_flag;
|
||
place_flagbase(self, "item_flagbase_team1");
|
||
} else {
|
||
remove(self); // not teamplay or deathmatch
|
||
}
|
||
};
|
||
|
||
/*QUAKED item_flag_team2 (0 .5 .8) (-8 -8 -32) (8 8 24)
|
||
blue team flag
|
||
Only appears in CTF teamplay
|
||
|
||
The flag waves 90 degrees off from the entity angle. If
|
||
you want the flag to point at 180, set then entity angle
|
||
to 90.
|
||
*/
|
||
void() item_flag_team2 =
|
||
{
|
||
if (!deathmatch) {
|
||
remove(self);
|
||
return;
|
||
}
|
||
|
||
teamplay = cvar("teamplay");
|
||
|
||
if (teamplay == TEAM_CTF_ONEFLAG) {
|
||
precache_sound ("misc/flagtk.wav"); // flag taken
|
||
precache_sound ("misc/flagcap.wav"); // flag capture
|
||
self.team = TEAM2;
|
||
self.skin = 1;
|
||
place_flagbase(self, "item_flagbase_team2");
|
||
remove(self);
|
||
return;
|
||
}
|
||
|
||
if (teamplay == TEAM_CTF || teamplay == TEAM_CTF_ALT) {
|
||
self.team = TEAM2;
|
||
self.items = IT_KEY1;
|
||
precache_model ("progs/ctfmodel.mdl");
|
||
setmodel (self, "progs/ctfmodel.mdl");
|
||
self.skin = 1;
|
||
precache_sound ("misc/flagtk.wav"); // flag taken
|
||
precache_sound ("misc/flagcap.wav"); // flag capture
|
||
precache_sound ("misc/flagret.wav"); // flag return
|
||
self.noise = "misc/flagtk.wav";
|
||
self.noise1 = "misc/flagret.wav";
|
||
setsize(self, '-16 -16 0', '16 16 74');
|
||
self.nextthink = time + 0.2; // items start after other solids
|
||
self.think = place_flag;
|
||
place_flagbase(self, "item_flagbase_team2");
|
||
} else {
|
||
remove(self); // not teamplay or deathmatch
|
||
}
|
||
};
|
||
|
||
/*QUAKED item_flag (0 .5 .8) (-8 -8 -32) (8 8 24)
|
||
flag for OneTeam play.
|
||
Only appears in CTF teamplay
|
||
|
||
The flag waves 90 degrees off from the entity angle. If
|
||
you want the flag to point at 180, set then entity angle
|
||
to 90.
|
||
*/
|
||
void() item_flag =
|
||
{
|
||
if (cvar("teamplay") != TEAM_CTF_ONEFLAG) {
|
||
remove(self);
|
||
return;
|
||
}
|
||
self.team = 0; // no team
|
||
self.items = IT_KEY1 | IT_KEY2;
|
||
// precache_model ("progs/flag.mdl");
|
||
// setmodel (self, "progs/flag.mdl");
|
||
precache_model ("progs/ctfmodel.mdl"); // PGM 01/18/97
|
||
setmodel (self, "progs/ctfmodel.mdl"); // PGM 01/18/97
|
||
self.skin = 2;
|
||
precache_sound ("misc/flagtk.wav"); // flag taken
|
||
precache_sound ("misc/flagcap.wav"); // flag capture
|
||
precache_sound ("misc/flagret.wav"); // flag return
|
||
self.noise = "misc/flagtk.wav";
|
||
self.noise1 = "misc/flagret.wav";
|
||
setsize(self, '-16 -16 0', '16 16 74');
|
||
self.nextthink = time + 0.2; // items start after other solids
|
||
self.think = place_flag;
|
||
place_flagbase(self, "item_flagbase");
|
||
};
|
||
|
||
/*QUAKED info_player_team1 (1 0 1) (-16 -16 -24) (16 16 24)
|
||
potential spawning position for CTF games team 1.
|
||
*/
|
||
void() info_player_team1 =
|
||
{
|
||
};
|
||
|
||
/*QUAKED info_player_team2 (1 0 1) (-16 -16 -24) (16 16 24)
|
||
potential spawning position for CTF games team 2.
|
||
*/
|
||
void() info_player_team2 =
|
||
{
|
||
};
|
||
|
||
void() TeamSetUpdate =
|
||
{
|
||
nextteamupdtime = time + CTF_UPDATE_TIME;
|
||
};
|
||
|
||
void() TeamCheckUpdate =
|
||
{
|
||
local float total1, total2, total3;
|
||
local entity p;
|
||
local string s;
|
||
local string ts1, ts2, ts3;
|
||
|
||
if (nextteamupdtime > time || teamplay < 1 || !deathmatch)
|
||
return;
|
||
|
||
TeamSetUpdate();
|
||
|
||
// count up total
|
||
total1 = total2 = total3 = 0;
|
||
|
||
ts1 = GetCTFTeam(TEAM1);
|
||
ts2 = GetCTFTeam(TEAM2);
|
||
ts3 = GetCTFTeam(TEAM3);
|
||
|
||
if (teamplay == TEAM_CTF || teamplay == TEAM_CTF_ALT || teamplay == TEAM_CTF_ONEFLAG) {
|
||
p = find(world, classname, "player");
|
||
while (p != world) {
|
||
if (p.steam == TEAM1)
|
||
total1 = total1 + p.frags;
|
||
else if (p.steam == TEAM2)
|
||
total2 = total2 + p.frags;
|
||
else if (p.steam == TEAM3)
|
||
total3 = total3 + p.frags;
|
||
p = find(p, classname, "player");
|
||
}
|
||
|
||
if (teamplay == TEAM_CTF || teamplay == TEAM_CTF_ONEFLAG) {
|
||
if (total1 > total2) {
|
||
bprint(ts1);
|
||
bprint(" team is leading by ");
|
||
s = ftos(total1 - total2);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else if (total1 < total2) {
|
||
bprint(ts2);
|
||
bprint(" team is leading by ");
|
||
s = ftos(total2 - total1);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else {
|
||
bprint(ts1);
|
||
bprint(" and ");
|
||
bprint(ts2);
|
||
bprint(" teams are tied with ");
|
||
s = ftos(total1);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
}
|
||
} else if (teamplay == TEAM_CTF_ALT) {
|
||
if (total1 > total2 && total1 > total3) {
|
||
bprint(ts1);
|
||
bprint(" team is leading by ");
|
||
if (total2 > total3)
|
||
s = ftos(total1 - total2);
|
||
else
|
||
s = ftos(total1 - total3);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else if (total2 > total1 && total2 > total3) {
|
||
bprint(ts2);
|
||
bprint(" team is leading by ");
|
||
if (total1 > total3)
|
||
s = ftos(total2 - total1);
|
||
else
|
||
s = ftos(total2 - total3);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else if (total3 > total1 && total3 > total2) {
|
||
bprint(ts3);
|
||
bprint(" team is leading by ");
|
||
if (total1 > total2)
|
||
s = ftos(total3 - total1);
|
||
else
|
||
s = ftos(total3 - total2);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else if (total1 == total2) {
|
||
bprint(ts1);
|
||
bprint(" and ");
|
||
bprint(ts2);
|
||
bprint(" teams are tied with ");
|
||
s = ftos(total1);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else if (total3 == total2) {
|
||
bprint(ts2);
|
||
bprint(" and ");
|
||
bprint(ts3);
|
||
bprint(" teams are tied with ");
|
||
s = ftos(total3);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else if (total3 == total1) {
|
||
bprint(ts1);
|
||
bprint(" and ");
|
||
bprint(ts3);
|
||
bprint(" teams are tied with ");
|
||
s = ftos(total1);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
} else {
|
||
bprint(ts1);
|
||
bprint(", ");
|
||
bprint(ts2);
|
||
bprint(" and ");
|
||
bprint(ts3);
|
||
bprint(" teams are tied with ");
|
||
s = ftos(total1);
|
||
bprint(s);
|
||
bprint(" points!\n");
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
/*QUAKED func_ctf_wall (0 .5 .8) ?
|
||
This is just a solid wall if not inhibitted
|
||
Only appears in CTF teamplay
|
||
*/
|
||
void() func_ctf_wall =
|
||
{
|
||
teamplay = cvar("teamplay");
|
||
if (teamplay == TEAM_CTF || teamplay == TEAM_CTF_ONEFLAG ||
|
||
teamplay == TEAM_CTF_ALT) {
|
||
self.angles = '0 0 0';
|
||
self.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything
|
||
self.solid = SOLID_BSP;
|
||
setmodel (self, self.model);
|
||
} else
|
||
remove(self);
|
||
};
|
||
|