X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fmutator%2Fgamemode_ctf.qc;h=fe63fa7e4ec2fb023a922f9c3793d2ca086c645a;hb=75f32635eb47f324db31c8f257c935018dedbc23;hp=d4524479d167dec53dc1d9dd363290390a46bf16;hpb=7f5ad47610dc8b5580cc96ae961a57cca96e6975;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/mutators/mutator/gamemode_ctf.qc b/qcsrc/server/mutators/mutator/gamemode_ctf.qc index d4524479d..fe63fa7e4 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ctf.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ctf.qc @@ -1,6 +1,6 @@ -#ifndef GAMEMODE_CTF_H -#define GAMEMODE_CTF_H +#include "gamemode_ctf.qh" +#ifdef IMPLEMENTATION #ifndef CSQC void ctf_Initialize(); @@ -13,7 +13,7 @@ REGISTER_MUTATOR(ctf, false) ctf_Initialize(); ActivateTeamplay(); - SetLimits(autocvar_capturelimit_override, autocvar_captureleadlimit_override, -1, -1); + SetLimits(autocvar_capturelimit_override, autocvar_captureleadlimit_override, autocvar_timelimit_override, -1); have_team_spawns = -1; // request team spawns } @@ -35,184 +35,11 @@ REGISTER_MUTATOR(ctf, false) #endif #ifdef SVQC -// used in cheats.qc -void ctf_RespawnFlag(entity flag); - -// score rule declarations -const int ST_CTF_CAPS = 1; -const int SP_CTF_CAPS = 4; -const int SP_CTF_CAPTIME = 5; -const int SP_CTF_PICKUPS = 6; -const int SP_CTF_DROPS = 7; -const int SP_CTF_FCKILLS = 8; -const int SP_CTF_RETURNS = 9; - -CLASS(Flag, Pickup) - ATTRIB(Flag, m_mins, vector, PL_MIN_CONST + '0 0 -13') - ATTRIB(Flag, m_maxs, vector, PL_MAX_CONST + '0 0 -13') -ENDCLASS(Flag) -Flag CTF_FLAG; STATIC_INIT(Flag) { CTF_FLAG = NEW(Flag); } -void ctf_FlagTouch() { SELFPARAM(); ITEM_HANDLE(Pickup, CTF_FLAG, this, other); } - -// flag constants // for most of these, there is just one question to be asked: WHYYYYY? - -const float FLAG_SCALE = 0.6; - -const float FLAG_THINKRATE = 0.2; -const float FLAG_TOUCHRATE = 0.5; -const float WPFE_THINKRATE = 0.5; - -const vector FLAG_DROP_OFFSET = ('0 0 32'); -const vector FLAG_CARRY_OFFSET = ('-16 0 8'); -#define FLAG_SPAWN_OFFSET ('0 0 1' * (PL_MAX_CONST.z - 13)) -const vector FLAG_WAYPOINT_OFFSET = ('0 0 64'); -const vector FLAG_FLOAT_OFFSET = ('0 0 32'); -const vector FLAG_PASS_ARC_OFFSET = ('0 0 -10'); - -const vector VEHICLE_FLAG_OFFSET = ('0 0 96'); -const float VEHICLE_FLAG_SCALE = 1.0; - -// waypoint colors -#define WPCOLOR_ENEMYFC(t) ((t) ? colormapPaletteColor(t - 1, false) * 0.75 : '1 1 1') -#define WPCOLOR_FLAGCARRIER(t) (WP_FlagCarrier.m_color) -#define WPCOLOR_DROPPEDFLAG(t) ((t) ? ('0.25 0.25 0.25' + colormapPaletteColor(t - 1, false)) * 0.5 : '1 1 1') - -// sounds -#define snd_flag_taken noise -#define snd_flag_returned noise1 -#define snd_flag_capture noise2 -#define snd_flag_respawn noise3 -.string snd_flag_dropped; -.string snd_flag_touch; -.string snd_flag_pass; - -// effects -.string toucheffect; -.string passeffect; -.string capeffect; - -// list of flags on the map -entity ctf_worldflaglist; -.entity ctf_worldflagnext; -.entity ctf_staleflagnext; - -// waypoint sprites -.entity bot_basewaypoint; // flag waypointsprite -.entity wps_helpme; -.entity wps_flagbase; -.entity wps_flagcarrier; -.entity wps_flagdropped; -.entity wps_enemyflagcarrier; -.float wps_helpme_time; -bool wpforenemy_announced; -float wpforenemy_nextthink; - -// statuses -const int FLAG_BASE = 1; -const int FLAG_DROPPED = 2; -const int FLAG_CARRY = 3; -const int FLAG_PASSING = 4; - -const int DROP_NORMAL = 1; -const int DROP_THROW = 2; -const int DROP_PASS = 3; -const int DROP_RESET = 4; - -const int PICKUP_BASE = 1; -const int PICKUP_DROPPED = 2; - -const int CAPTURE_NORMAL = 1; -const int CAPTURE_DROPPED = 2; - -const int RETURN_TIMEOUT = 1; -const int RETURN_DROPPED = 2; -const int RETURN_DAMAGE = 3; -const int RETURN_SPEEDRUN = 4; -const int RETURN_NEEDKILL = 5; - -void ctf_Handle_Throw(entity player, entity receiver, float droptype); - -// flag properties -#define ctf_spawnorigin dropped_origin -bool ctf_stalemate; // indicates that a stalemate is active -float ctf_captimerecord; // record time for capturing the flag -.float ctf_pickuptime; -.float ctf_droptime; -.int ctf_status; // status of the flag (FLAG_BASE, FLAG_DROPPED, FLAG_CARRY declared globally) -.entity ctf_dropper; // don't allow spam of dropping the flag -.int max_flag_health; -.float next_take_time; -.bool ctf_flagdamaged; -int ctf_teams; - -// passing/throwing properties -.float pass_distance; -.entity pass_sender; -.entity pass_target; -.float throw_antispam; -.float throw_prevtime; -.int throw_count; - -// CaptureShield: If the player is too bad to be allowed to capture, shield them from taking the flag. -.bool ctf_captureshielded; // set to 1 if the player is too bad to be allowed to capture -float ctf_captureshield_min_negscore; // punish at -20 points -float ctf_captureshield_max_ratio; // punish at most 30% of each team -float ctf_captureshield_force; // push force of the shield - -// 1 flag ctf -bool ctf_oneflag; // indicates whether or not a neutral flag has been found - -// bot player logic -const int HAVOCBOT_CTF_ROLE_NONE = 0; -const int HAVOCBOT_CTF_ROLE_DEFENSE = 2; -const int HAVOCBOT_CTF_ROLE_MIDDLE = 4; -const int HAVOCBOT_CTF_ROLE_OFFENSE = 8; -const int HAVOCBOT_CTF_ROLE_CARRIER = 16; -const int HAVOCBOT_CTF_ROLE_RETRIEVER = 32; -const int HAVOCBOT_CTF_ROLE_ESCORT = 64; - -.bool havocbot_cantfindflag; - -vector havocbot_ctf_middlepoint; -float havocbot_ctf_middlepoint_radius; - -void havocbot_role_ctf_setrole(entity bot, int role); - -// team checking -#define CTF_SAMETEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? DIFF_TEAM(a,b) : SAME_TEAM(a,b)) -#define CTF_DIFFTEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? SAME_TEAM(a,b) : DIFF_TEAM(a,b)) - -// networked flag statuses -.int ctf_flagstatus = _STAT(CTF_FLAGSTATUS); -#endif - -const int CTF_RED_FLAG_TAKEN = 1; -const int CTF_RED_FLAG_LOST = 2; -const int CTF_RED_FLAG_CARRYING = 3; -const int CTF_BLUE_FLAG_TAKEN = 4; -const int CTF_BLUE_FLAG_LOST = 8; -const int CTF_BLUE_FLAG_CARRYING = 12; -const int CTF_YELLOW_FLAG_TAKEN = 16; -const int CTF_YELLOW_FLAG_LOST = 32; -const int CTF_YELLOW_FLAG_CARRYING = 48; -const int CTF_PINK_FLAG_TAKEN = 64; -const int CTF_PINK_FLAG_LOST = 128; -const int CTF_PINK_FLAG_CARRYING = 192; -const int CTF_NEUTRAL_FLAG_TAKEN = 256; -const int CTF_NEUTRAL_FLAG_LOST = 512; -const int CTF_NEUTRAL_FLAG_CARRYING = 768; -const int CTF_FLAG_NEUTRAL = 2048; -const int CTF_SHIELDED = 4096; -#endif - -#ifdef IMPLEMENTATION - -#ifdef SVQC -#include "../../../common/vehicles/all.qh" -#include "../../teamplay.qh" +#include +#include #endif -#include "../../../lib/warpzone/common.qh" +#include bool autocvar_g_ctf_allow_vehicle_carry; bool autocvar_g_ctf_allow_vehicle_touch; @@ -310,9 +137,9 @@ void ctf_CaptureRecord(entity flag, entity player) // notify about shit if(ctf_oneflag) { Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_CTF_CAPTURE_NEUTRAL, player.netname); } - else if(!ctf_captimerecord) { Send_Notification(NOTIF_ALL, world, MSG_CHOICE, APP_TEAM_ENT_4(flag, CHOICE_CTF_CAPTURE_TIME_), player.netname, (cap_time * 100)); } - else if(cap_time < cap_record) { Send_Notification(NOTIF_ALL, world, MSG_CHOICE, APP_TEAM_ENT_4(flag, CHOICE_CTF_CAPTURE_BROKEN_), player.netname, refername, (cap_time * 100), (cap_record * 100)); } - else { Send_Notification(NOTIF_ALL, world, MSG_CHOICE, APP_TEAM_ENT_4(flag, CHOICE_CTF_CAPTURE_UNBROKEN_), player.netname, refername, (cap_time * 100), (cap_record * 100)); } + else if(!ctf_captimerecord) { Send_Notification(NOTIF_ALL, world, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_CAPTURE_TIME), player.netname, (cap_time * 100)); } + else if(cap_time < cap_record) { Send_Notification(NOTIF_ALL, world, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_CAPTURE_BROKEN), player.netname, refername, (cap_time * 100), (cap_record * 100)); } + else { Send_Notification(NOTIF_ALL, world, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_CAPTURE_UNBROKEN), player.netname, refername, (cap_time * 100), (cap_record * 100)); } // write that shit in the database if(!ctf_oneflag) // but not in 1-flag mode @@ -401,7 +228,6 @@ bool ctf_CheckPassDirection(vector head_center, vector passer_center, vector pas bool ctf_CaptureShield_CheckStatus(entity p) { int s, s2, s3, s4, se, se2, se3, se4, sr, ser; - entity e; int players_worseeq, players_total; if(ctf_captureshield_max_ratio <= 0) @@ -418,21 +244,20 @@ bool ctf_CaptureShield_CheckStatus(entity p) return false; players_total = players_worseeq = 0; - FOR_EACH_PLAYER(e) - { - if(DIFF_TEAM(e, p)) + FOREACH_CLIENT(IS_PLAYER(it), LAMBDA( + if(DIFF_TEAM(it, p)) continue; - se = PlayerScore_Add(e, SP_CTF_CAPS, 0); - se2 = PlayerScore_Add(e, SP_CTF_PICKUPS, 0); - se3 = PlayerScore_Add(e, SP_CTF_RETURNS, 0); - se4 = PlayerScore_Add(e, SP_CTF_FCKILLS, 0); + se = PlayerScore_Add(it, SP_CTF_CAPS, 0); + se2 = PlayerScore_Add(it, SP_CTF_PICKUPS, 0); + se3 = PlayerScore_Add(it, SP_CTF_RETURNS, 0); + se4 = PlayerScore_Add(it, SP_CTF_FCKILLS, 0); ser = ((se - se2) + (se3 + se4)); if(ser <= sr) ++players_worseeq; ++players_total; - } + )); // player is in the worse half, if >= half the players are better than him, or consequently, if < half of the players are worse // use this rule here @@ -453,16 +278,16 @@ void ctf_CaptureShield_Update(entity player, bool wanted_status) } } -bool ctf_CaptureShield_Customize() -{SELFPARAM(); +bool ctf_CaptureShield_Customize(entity this) +{ if(!other.ctf_captureshielded) { return false; } if(CTF_SAMETEAM(self, other)) { return false; } return true; } -void ctf_CaptureShield_Touch() -{SELFPARAM(); +void ctf_CaptureShield_Touch(entity this) +{ if(!other.ctf_captureshielded) { return; } if(CTF_SAMETEAM(self, other)) { return; } @@ -474,20 +299,20 @@ void ctf_CaptureShield_Touch() } void ctf_CaptureShield_Spawn(entity flag) -{SELFPARAM(); +{ entity shield = new(ctf_captureshield); - shield.enemy = self; - shield.team = self.team; - shield.touch = ctf_CaptureShield_Touch; - shield.customizeentityforclient = ctf_CaptureShield_Customize; + shield.enemy = flag; + shield.team = flag.team; + settouch(shield, ctf_CaptureShield_Touch); + setcefc(shield, ctf_CaptureShield_Customize); shield.effects = EF_ADDITIVE; shield.movetype = MOVETYPE_NOCLIP; shield.solid = SOLID_TRIGGER; shield.avelocity = '7 0 11'; shield.scale = 0.5; - setorigin(shield, self.origin); + setorigin(shield, flag.origin); setmodel(shield, MDL_CTF_SHIELD); setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs); } @@ -512,7 +337,7 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype) flag.ctf_status = FLAG_DROPPED; // messages and sounds - Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_LOST_) : INFO_CTF_LOST_NEUTRAL), player.netname); + Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_LOST) : INFO_CTF_LOST_NEUTRAL), player.netname); _sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE); ctf_EventLog("dropped", player.team, player); @@ -544,7 +369,6 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype) void ctf_Handle_Retrieve(entity flag, entity player) { - entity tmp_player; // temporary entity which the FOR_EACH_PLAYER loop uses to scan players entity sender = flag.pass_sender; // transfer flag to player @@ -573,15 +397,14 @@ void ctf_Handle_Retrieve(entity flag, entity player) _sound(player, CH_TRIGGER, flag.snd_flag_pass, VOL_BASE, ATTEN_NORM); ctf_EventLog("receive", flag.team, player); - FOR_EACH_REALPLAYER(tmp_player) - { - if(tmp_player == sender) - Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT_4(flag, CENTER_CTF_PASS_SENT_) : CENTER_CTF_PASS_SENT_NEUTRAL), player.netname); - else if(tmp_player == player) - Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT_4(flag, CENTER_CTF_PASS_RECEIVED_) : CENTER_CTF_PASS_RECEIVED_NEUTRAL), sender.netname); - else if(SAME_TEAM(tmp_player, sender)) - Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT_4(flag, CENTER_CTF_PASS_OTHER_) : CENTER_CTF_PASS_OTHER_NEUTRAL), sender.netname, player.netname); - } + FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), LAMBDA( + if(it == sender) + Send_Notification(NOTIF_ONE, it, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT(flag, CENTER_CTF_PASS_SENT) : CENTER_CTF_PASS_SENT_NEUTRAL), player.netname); + else if(it == player) + Send_Notification(NOTIF_ONE, it, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT(flag, CENTER_CTF_PASS_RECEIVED) : CENTER_CTF_PASS_RECEIVED_NEUTRAL), sender.netname); + else if(SAME_TEAM(it, sender)) + Send_Notification(NOTIF_ONE, it, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT(flag, CENTER_CTF_PASS_OTHER) : CENTER_CTF_PASS_OTHER_NEUTRAL), sender.netname, player.netname); + )); // create new waypoint ctf_FlagcarrierWaypoints(player); @@ -648,7 +471,7 @@ void ctf_Handle_Throw(entity player, entity receiver, int droptype) makevectors((player.v_angle.y * '0 1 0') + (bound(autocvar_g_ctf_throw_angle_min, player.v_angle.x, autocvar_g_ctf_throw_angle_max) * '1 0 0')); flag_velocity = (('0 0 1' * autocvar_g_ctf_throw_velocity_up) + ((v_forward * autocvar_g_ctf_throw_velocity_forward) * ((player.items & ITEM_Strength.m_itemid) ? autocvar_g_ctf_throw_strengthmultiplier : 1))); - flag.velocity = W_CalculateProjectileVelocity(player.velocity, flag_velocity, false); + flag.velocity = W_CalculateProjectileVelocity(player, player.velocity, flag_velocity, false); ctf_Handle_Drop(flag, player, droptype); break; } @@ -662,7 +485,7 @@ void ctf_Handle_Throw(entity player, entity receiver, int droptype) default: case DROP_NORMAL: { - flag.velocity = W_CalculateProjectileVelocity(player.velocity, (('0 0 1' * autocvar_g_ctf_drop_velocity_up) + ((('0 1 0' * crandom()) + ('1 0 0' * crandom())) * autocvar_g_ctf_drop_velocity_side)), false); + flag.velocity = W_CalculateProjectileVelocity(player, player.velocity, (('0 0 1' * autocvar_g_ctf_drop_velocity_up) + ((('0 1 0' * crandom()) + ('1 0 0' * crandom())) * autocvar_g_ctf_drop_velocity_side)), false); ctf_Handle_Drop(flag, player, droptype); break; } @@ -688,6 +511,8 @@ void shockwave_spawn(string m, vector org, float sz, float t1, float t2) // Event Handlers // ============== +void nades_GiveBonus(entity player, float score); + void ctf_Handle_Capture(entity flag, entity toucher, int capturetype) { entity enemy_flag = ((capturetype == CAPTURE_NORMAL) ? toucher.flagcarried : toucher); @@ -712,7 +537,7 @@ void ctf_Handle_Capture(entity flag, entity toucher, int capturetype) player.throw_count = 0; // messages and sounds - Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((enemy_flag.team) ? APP_TEAM_ENT_4(enemy_flag, CENTER_CTF_CAPTURE_) : CENTER_CTF_CAPTURE_NEUTRAL)); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((enemy_flag.team) ? APP_TEAM_ENT(enemy_flag, CENTER_CTF_CAPTURE) : CENTER_CTF_CAPTURE_NEUTRAL)); ctf_CaptureRecord(enemy_flag, player); _sound(player, CH_TRIGGER, ((ctf_oneflag) ? player_team_flag.snd_flag_capture : ((DIFF_TEAM(player, flag)) ? enemy_flag.snd_flag_capture : flag.snd_flag_capture)), VOL_BASE, ATTEN_NONE); @@ -756,12 +581,12 @@ void ctf_Handle_Return(entity flag, entity player) // messages and sounds if(IS_MONSTER(player)) { - Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(flag, INFO_CTF_RETURN_MONSTER_), player.monster_name); + Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT(flag, INFO_CTF_RETURN_MONSTER), player.monster_name); } else if(flag.team) { - Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_4(flag, CENTER_CTF_RETURN_)); - Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(flag, INFO_CTF_RETURN_), player.netname); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT(flag, CENTER_CTF_RETURN)); + Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT(flag, INFO_CTF_RETURN), player.netname); } _sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE); ctf_EventLog("return", flag.team, player); @@ -796,7 +621,6 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype) { // declarations float pickup_dropped_score; // used to calculate dropped pickup score - entity tmp_entity; // temporary entity // attach the flag to the player flag.owner = player; @@ -828,28 +652,25 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype) } // messages and sounds - Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_PICKUP_) : INFO_CTF_PICKUP_NEUTRAL), player.netname); + Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_PICKUP) : INFO_CTF_PICKUP_NEUTRAL), player.netname); if(ctf_stalemate) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER); } if(!flag.team) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PICKUP_NEUTRAL); } - else if(CTF_DIFFTEAM(player, flag)) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_4(flag, CENTER_CTF_PICKUP_)); } + else if(CTF_DIFFTEAM(player, flag)) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT(flag, CENTER_CTF_PICKUP)); } else { Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((SAME_TEAM(player, flag)) ? CENTER_CTF_PICKUP_TEAM : CENTER_CTF_PICKUP_TEAM_ENEMY), Team_ColorCode(flag.team)); } - Send_Notification(NOTIF_TEAM_EXCEPT, player, MSG_CHOICE, ((flag.team) ? APP_TEAM_ENT_4(flag, CHOICE_CTF_PICKUP_TEAM_) : CHOICE_CTF_PICKUP_TEAM_NEUTRAL), Team_ColorCode(player.team), player.netname); + Send_Notification(NOTIF_TEAM_EXCEPT, player, MSG_CHOICE, ((flag.team) ? APP_TEAM_ENT(flag, CHOICE_CTF_PICKUP_TEAM) : CHOICE_CTF_PICKUP_TEAM_NEUTRAL), Team_ColorCode(player.team), player.netname); if(!flag.team) - FOR_EACH_PLAYER(tmp_entity) - if(tmp_entity != player) - if(DIFF_TEAM(player, tmp_entity)) - Send_Notification(NOTIF_ONE, tmp_entity, MSG_CHOICE, CHOICE_CTF_PICKUP_ENEMY_NEUTRAL, Team_ColorCode(player.team), player.netname); + FOREACH_CLIENT(IS_PLAYER(it) && it != player && DIFF_TEAM(it, player), LAMBDA(Send_Notification(NOTIF_ONE, it, MSG_CHOICE, CHOICE_CTF_PICKUP_ENEMY_NEUTRAL, Team_ColorCode(player.team), player.netname))); if(flag.team) - FOR_EACH_PLAYER(tmp_entity) - if(tmp_entity != player) - if(CTF_SAMETEAM(flag, tmp_entity)) - if(SAME_TEAM(player, tmp_entity)) - Send_Notification(NOTIF_ONE, tmp_entity, MSG_CHOICE, APP_TEAM_ENT_4(flag, CHOICE_CTF_PICKUP_TEAM_), Team_ColorCode(player.team), player.netname); - else - Send_Notification(NOTIF_ONE, tmp_entity, MSG_CHOICE, ((SAME_TEAM(flag, player)) ? CHOICE_CTF_PICKUP_ENEMY_TEAM : CHOICE_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), player.netname); + FOREACH_CLIENT(IS_PLAYER(it) && it != player, LAMBDA( + if(CTF_SAMETEAM(flag, it)) + if(SAME_TEAM(player, it)) + Send_Notification(NOTIF_ONE, it, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_PICKUP_TEAM), Team_ColorCode(player.team), player.netname); + else + Send_Notification(NOTIF_ONE, it, MSG_CHOICE, ((SAME_TEAM(flag, player)) ? CHOICE_CTF_PICKUP_ENEMY_TEAM : CHOICE_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), player.netname); + )); _sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE); @@ -910,14 +731,14 @@ void ctf_CheckFlagReturn(entity flag, int returntype) { switch(returntype) { - case RETURN_DROPPED: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_FLAGRETURN_DROPPED_) : INFO_CTF_FLAGRETURN_DROPPED_NEUTRAL)); break; - case RETURN_DAMAGE: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_FLAGRETURN_DAMAGED_) : INFO_CTF_FLAGRETURN_DAMAGED_NEUTRAL)); break; - case RETURN_SPEEDRUN: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_FLAGRETURN_SPEEDRUN_) : INFO_CTF_FLAGRETURN_SPEEDRUN_NEUTRAL), ctf_captimerecord); break; - case RETURN_NEEDKILL: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_FLAGRETURN_NEEDKILL_) : INFO_CTF_FLAGRETURN_NEEDKILL_NEUTRAL)); break; + case RETURN_DROPPED: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_DROPPED) : INFO_CTF_FLAGRETURN_DROPPED_NEUTRAL)); break; + case RETURN_DAMAGE: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_DAMAGED) : INFO_CTF_FLAGRETURN_DAMAGED_NEUTRAL)); break; + case RETURN_SPEEDRUN: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_SPEEDRUN) : INFO_CTF_FLAGRETURN_SPEEDRUN_NEUTRAL), ctf_captimerecord); break; + case RETURN_NEEDKILL: Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_NEEDKILL) : INFO_CTF_FLAGRETURN_NEEDKILL_NEUTRAL)); break; default: case RETURN_TIMEOUT: - { Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_FLAGRETURN_TIMEOUT_) : INFO_CTF_FLAGRETURN_TIMEOUT_NEUTRAL)); break; } + { Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_TIMEOUT) : INFO_CTF_FLAGRETURN_TIMEOUT_NEUTRAL)); break; } } _sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE); ctf_EventLog("returned", flag.team, world); @@ -926,8 +747,8 @@ void ctf_CheckFlagReturn(entity flag, int returntype) } } -bool ctf_Stalemate_Customize() -{SELFPARAM(); +bool ctf_Stalemate_Customize(entity this) +{ // make spectators see what the player would see entity e, wp_owner; e = WaypointSprite_getviewentity(other); @@ -993,46 +814,45 @@ void ctf_CheckStalemate() { entity wp = WaypointSprite_Spawn(((ctf_oneflag) ? WP_FlagCarrier : WP_FlagCarrierEnemy), 0, 0, tmp_entity.owner, FLAG_WAYPOINT_OFFSET, world, 0, tmp_entity.owner, wps_enemyflagcarrier, true, RADARICON_FLAG); wp.colormod = WPCOLOR_ENEMYFC(tmp_entity.owner.team); - tmp_entity.owner.wps_enemyflagcarrier.customizeentityforclient = ctf_Stalemate_Customize; + setcefc(tmp_entity.owner.wps_enemyflagcarrier, ctf_Stalemate_Customize); } } if (!wpforenemy_announced) { - FOR_EACH_REALPLAYER(tmp_entity) - Send_Notification(NOTIF_ONE, tmp_entity, MSG_CENTER, ((tmp_entity.flagcarried) ? CENTER_CTF_STALEMATE_CARRIER : CENTER_CTF_STALEMATE_OTHER)); + FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), LAMBDA(Send_Notification(NOTIF_ONE, it, MSG_CENTER, ((it.flagcarried) ? CENTER_CTF_STALEMATE_CARRIER : CENTER_CTF_STALEMATE_OTHER)))); wpforenemy_announced = true; } } } -void ctf_FlagDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) -{SELFPARAM(); +void ctf_FlagDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) +{ if(ITEM_DAMAGE_NEEDKILL(deathtype)) { if(autocvar_g_ctf_flag_return_damage_delay) { - self.ctf_flagdamaged = true; + this.ctf_flagdamaged = true; } else { - self.health = 0; - ctf_CheckFlagReturn(self, RETURN_NEEDKILL); + this.health = 0; + ctf_CheckFlagReturn(this, RETURN_NEEDKILL); } return; } if(autocvar_g_ctf_flag_return_damage) { // reduce health and check if it should be returned - self.health = self.health - damage; - ctf_CheckFlagReturn(self, RETURN_DAMAGE); + this.health = this.health - damage; + ctf_CheckFlagReturn(this, RETURN_DAMAGE); return; } } -void ctf_FlagThink() -{SELFPARAM(); +void ctf_FlagThink(entity this) +{ // declarations entity tmp_entity; @@ -1040,8 +860,7 @@ void ctf_FlagThink() // captureshield if(self == ctf_worldflaglist) // only for the first flag - FOR_EACH_CLIENT(tmp_entity) - ctf_CaptureShield_Update(tmp_entity, 1); // release shield only + FOREACH_CLIENT(true, LAMBDA(ctf_CaptureShield_Update(it, 1))); // release shield only // sanity checks if(self.mins != CTF_FLAG.m_mins || self.maxs != CTF_FLAG.m_maxs) { // reset the flag boundaries in case it got squished @@ -1124,10 +943,8 @@ void ctf_FlagThink() self.health = 0; ctf_CheckFlagReturn(self, RETURN_SPEEDRUN); - setself(self.owner); - self.impulse = CHIMPULSE_SPEEDRUN.impulse; // move the player back to the waypoint they set - ImpulseCommands(self); - setself(this); + self.owner.impulse = CHIMPULSE_SPEEDRUN.impulse; // move the player back to the waypoint they set + ImpulseCommands(self.owner); } if(autocvar_g_ctf_stalemate) { @@ -1154,7 +971,7 @@ void ctf_FlagThink() WarpZone_TraceLine(self.origin, targ_origin, MOVE_NOMONSTERS, self); if((self.pass_target == world) - || (self.pass_target.deadflag != DEAD_NO) + || (IS_DEAD(self.pass_target)) || (self.pass_target.flagcarried) || (vlen(self.origin - targ_origin) > autocvar_g_ctf_pass_radius) || ((trace_fraction < 1) && (trace_ent != self.pass_target)) @@ -1199,10 +1016,10 @@ METHOD(Flag, giveTo, bool(Flag this, entity flag, entity toucher)) } int num_perteam = 0; - entity tmp_entity; FOR_EACH_PLAYER(tmp_entity) if(SAME_TEAM(toucher, tmp_entity)) { ++num_perteam; } + FOREACH_CLIENT(IS_PLAYER(it) && SAME_TEAM(toucher, it), LAMBDA(++num_perteam)); // special touch behaviors - if(toucher.frozen) { return; } + if(STAT(FROZEN, toucher)) { return; } else if(IS_VEHICLE(toucher)) { if(autocvar_g_ctf_allow_vehicle_touch && toucher.owner) @@ -1225,7 +1042,7 @@ METHOD(Flag, giveTo, bool(Flag this, entity flag, entity toucher)) } return; } - else if(toucher.deadflag != DEAD_NO) { return; } + else if(IS_DEAD(toucher)) { return; } switch(flag.ctf_status) { @@ -1267,7 +1084,7 @@ METHOD(Flag, giveTo, bool(Flag this, entity flag, entity toucher)) case FLAG_PASSING: { - if((IS_PLAYER(toucher)) && (toucher.deadflag == DEAD_NO) && (toucher != flag.pass_sender)) + if((IS_PLAYER(toucher)) && !IS_DEAD(toucher) && (toucher != flag.pass_sender)) { if(DIFF_TEAM(toucher, flag.pass_sender)) ctf_Handle_Return(flag, toucher); @@ -1339,16 +1156,16 @@ void ctf_Reset(entity this) ctf_RespawnFlag(this); } -void ctf_DelayedFlagSetup() // called after a flag is placed on a map by ctf_FlagSetup() -{SELFPARAM(); +void ctf_DelayedFlagSetup(entity this) // called after a flag is placed on a map by ctf_FlagSetup() +{ // bot waypoints - waypoint_spawnforitem_force(self, self.origin); - self.nearestwaypointtimeout = 0; // activate waypointing again - self.bot_basewaypoint = self.nearestwaypoint; + waypoint_spawnforitem_force(this, this.origin); + this.nearestwaypointtimeout = 0; // activate waypointing again + this.bot_basewaypoint = this.nearestwaypoint; // waypointsprites entity basename; - switch (self.team) + switch (this.team) { case NUM_TEAM_1: basename = WP_FlagBaseRed; break; case NUM_TEAM_2: basename = WP_FlagBaseBlue; break; @@ -1357,19 +1174,18 @@ void ctf_DelayedFlagSetup() // called after a flag is placed on a map by ctf_Fla default: basename = WP_FlagBaseNeutral; break; } - entity wp = WaypointSprite_SpawnFixed(basename, self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG); - wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 1 1'); - WaypointSprite_UpdateTeamRadar(self.wps_flagbase, RADARICON_FLAG, ((self.team) ? colormapPaletteColor(self.team - 1, false) : '1 1 1')); + entity wp = WaypointSprite_SpawnFixed(basename, this.origin + FLAG_WAYPOINT_OFFSET, this, wps_flagbase, RADARICON_FLAG); + wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 1 1'); + WaypointSprite_UpdateTeamRadar(this.wps_flagbase, RADARICON_FLAG, ((this.team) ? colormapPaletteColor(this.team - 1, false) : '1 1 1')); // captureshield setup - ctf_CaptureShield_Spawn(self); + ctf_CaptureShield_Spawn(this); } -void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag entity on the map as a spawnfunc -{SELFPARAM(); - // declarations - setself(flag); // for later usage with droptofloor() +.bool pushable; +void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag entity on the map as a spawnfunc +{ // main setup flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist ctf_worldflaglist = flag; @@ -1389,14 +1205,14 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e flag.event_damage = ctf_FlagDamage; flag.pushable = true; flag.teleportable = TELEPORT_NORMAL; - flag.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; + flag.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP; flag.damagedbytriggers = autocvar_g_ctf_flag_return_when_unreachable; flag.damagedbycontents = autocvar_g_ctf_flag_return_when_unreachable; flag.velocity = '0 0 0'; flag.mangle = flag.angles; flag.reset = ctf_Reset; - flag.touch = ctf_FlagTouch; - flag.think = ctf_FlagThink; + settouch(flag, ctf_FlagTouch); + setthink(flag, ctf_FlagThink); flag.nextthink = time + FLAG_THINKRATE; flag.ctf_status = FLAG_BASE; @@ -1410,16 +1226,18 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e if (flag.capeffect == "") { flag.capeffect = EFFECT_CAP(teamnumber).eent_eff_name; } // sounds - flag.snd_flag_taken = strzone(SND(CTF_TAKEN(teamnumber))); - flag.snd_flag_returned = strzone(SND(CTF_RETURNED(teamnumber))); - flag.snd_flag_capture = strzone(SND(CTF_CAPTURE(teamnumber))); - flag.snd_flag_dropped = strzone(SND(CTF_DROPPED(teamnumber))); - if (flag.snd_flag_respawn == "") flag.snd_flag_respawn = strzone(SND(CTF_RESPAWN)); // if there is ever a team-based sound for this, update the code to match. - precache_sound(flag.snd_flag_respawn); - if (flag.snd_flag_touch == "") flag.snd_flag_touch = strzone(SND(CTF_TOUCH)); // again has no team-based sound - precache_sound(flag.snd_flag_touch); - if (flag.snd_flag_pass == "") flag.snd_flag_pass = strzone(SND(CTF_PASS)); // same story here - precache_sound(flag.snd_flag_pass); +#define X(s,b) \ + if(flag.s == "") flag.s = b; \ + precache_sound(flag.s); + + X(snd_flag_taken, strzone(SND(CTF_TAKEN(teamnumber)))) + X(snd_flag_returned, strzone(SND(CTF_RETURNED(teamnumber)))) + X(snd_flag_capture, strzone(SND(CTF_CAPTURE(teamnumber)))) + X(snd_flag_dropped, strzone(SND(CTF_DROPPED(teamnumber)))) + X(snd_flag_respawn, strzone(SND(CTF_RESPAWN))) + X(snd_flag_touch, strzone(SND(CTF_TOUCH))) + X(snd_flag_pass, strzone(SND(CTF_PASS))) +#undef X // precache precache_model(flag.model); @@ -1467,8 +1285,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e else // drop to floor, automatically find a platform and set that as spawn origin { flag.noalign = false; - setself(flag); - droptofloor(); + droptofloor(flag); flag.movetype = MOVETYPE_TOSS; } @@ -1548,109 +1365,107 @@ int havocbot_ctf_teamcount(entity bot, vector org, float tc_radius) return 0; int c = 0; - entity head; - FOR_EACH_PLAYER(head) - { - if(DIFF_TEAM(head, bot) || head.deadflag != DEAD_NO || head == bot) + FOREACH_CLIENT(IS_PLAYER(it), LAMBDA( + if(DIFF_TEAM(it, bot) || IS_DEAD(it) || it == bot) continue; - if(vlen(head.origin - org) < tc_radius) + if(vlen(it.origin - org) < tc_radius) ++c; - } + )); return c; } -void havocbot_goalrating_ctf_ourflag(float ratingscale) -{SELFPARAM(); +void havocbot_goalrating_ctf_ourflag(entity this, float ratingscale) +{ entity head; head = ctf_worldflaglist; while (head) { - if (CTF_SAMETEAM(self, head)) + if (CTF_SAMETEAM(this, head)) break; head = head.ctf_worldflagnext; } if (head) - navigation_routerating(head, ratingscale, 10000); + navigation_routerating(this, head, ratingscale, 10000); } -void havocbot_goalrating_ctf_ourbase(float ratingscale) -{SELFPARAM(); +void havocbot_goalrating_ctf_ourbase(entity this, float ratingscale) +{ entity head; head = ctf_worldflaglist; while (head) { - if (CTF_SAMETEAM(self, head)) + if (CTF_SAMETEAM(this, head)) break; head = head.ctf_worldflagnext; } if (!head) return; - navigation_routerating(head.bot_basewaypoint, ratingscale, 10000); + navigation_routerating(this, head.bot_basewaypoint, ratingscale, 10000); } -void havocbot_goalrating_ctf_enemyflag(float ratingscale) -{SELFPARAM(); +void havocbot_goalrating_ctf_enemyflag(entity this, float ratingscale) +{ entity head; head = ctf_worldflaglist; while (head) { if(ctf_oneflag) { - if(CTF_DIFFTEAM(self, head)) + if(CTF_DIFFTEAM(this, head)) { if(head.team) { - if(self.flagcarried) + if(this.flagcarried) break; } - else if(!self.flagcarried) + else if(!this.flagcarried) break; } } - else if(CTF_DIFFTEAM(self, head)) + else if(CTF_DIFFTEAM(this, head)) break; head = head.ctf_worldflagnext; } if (head) - navigation_routerating(head, ratingscale, 10000); + navigation_routerating(this, head, ratingscale, 10000); } -void havocbot_goalrating_ctf_enemybase(float ratingscale) -{SELFPARAM(); +void havocbot_goalrating_ctf_enemybase(entity this, float ratingscale) +{ if (!bot_waypoints_for_items) { - havocbot_goalrating_ctf_enemyflag(ratingscale); + havocbot_goalrating_ctf_enemyflag(this, ratingscale); return; } entity head; - head = havocbot_ctf_find_enemy_flag(self); + head = havocbot_ctf_find_enemy_flag(this); if (!head) return; - navigation_routerating(head.bot_basewaypoint, ratingscale, 10000); + navigation_routerating(this, head.bot_basewaypoint, ratingscale, 10000); } -void havocbot_goalrating_ctf_ourstolenflag(float ratingscale) -{SELFPARAM(); +void havocbot_goalrating_ctf_ourstolenflag(entity this, float ratingscale) +{ entity mf; - mf = havocbot_ctf_find_flag(self); + mf = havocbot_ctf_find_flag(this); if(mf.ctf_status == FLAG_BASE) return; if(mf.tag_entity) - navigation_routerating(mf.tag_entity, ratingscale, 10000); + navigation_routerating(this, mf.tag_entity, ratingscale, 10000); } -void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float df_radius) +void havocbot_goalrating_ctf_droppedflags(entity this, float ratingscale, vector org, float df_radius) { entity head; head = ctf_worldflaglist; @@ -1663,18 +1478,18 @@ void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float d if(df_radius) { if(vlen(org-head.origin) 0) - navigation_routerating(head, t * ratingscale, 500); + navigation_routerating(this, head, t * ratingscale, 500); } head = head.chain; } } -void havocbot_ctf_reset_role(entity bot) +void havocbot_ctf_reset_role(entity this) { float cdefense, cmiddle, coffense; - entity mf, ef, head; + entity mf, ef; float c; - if(bot.deadflag != DEAD_NO) + if(IS_DEAD(this)) return; - if(vlen(havocbot_ctf_middlepoint)==0) + if(havocbot_ctf_middlepoint == '0 0 0') havocbot_calculate_middlepoint(); // Check ctf flags - if (bot.flagcarried) + if (this.flagcarried) { - havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_CARRIER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_CARRIER); return; } - mf = havocbot_ctf_find_flag(bot); - ef = havocbot_ctf_find_enemy_flag(bot); + mf = havocbot_ctf_find_flag(this); + ef = havocbot_ctf_find_enemy_flag(this); // Retrieve stolen flag if(mf.ctf_status!=FLAG_BASE) { - havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_RETRIEVER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_RETRIEVER); return; } // If enemy flag is taken go to the middle to intercept pursuers if(ef.ctf_status!=FLAG_BASE) { - havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_MIDDLE); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_MIDDLE); return; } // if there is only me on the team switch to offense c = 0; - FOR_EACH_PLAYER(head) - if(SAME_TEAM(head, bot)) - ++c; + FOREACH_CLIENT(IS_PLAYER(it) && SAME_TEAM(it, this), LAMBDA(++c)); if(c==1) { - havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_OFFENSE); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_OFFENSE); return; } // Evaluate best position to take // Count mates on middle position - cmiddle = havocbot_ctf_teamcount(bot, havocbot_ctf_middlepoint, havocbot_ctf_middlepoint_radius * 0.5); + cmiddle = havocbot_ctf_teamcount(this, havocbot_ctf_middlepoint, havocbot_ctf_middlepoint_radius * 0.5); // Count mates on defense position - cdefense = havocbot_ctf_teamcount(bot, mf.dropped_origin, havocbot_ctf_middlepoint_radius * 0.5); + cdefense = havocbot_ctf_teamcount(this, mf.dropped_origin, havocbot_ctf_middlepoint_radius * 0.5); // Count mates on offense position - coffense = havocbot_ctf_teamcount(bot, ef.dropped_origin, havocbot_ctf_middlepoint_radius); + coffense = havocbot_ctf_teamcount(this, ef.dropped_origin, havocbot_ctf_middlepoint_radius); if(cdefense<=coffense) - havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_DEFENSE); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_DEFENSE); else if(coffense<=cmiddle) - havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_OFFENSE); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_OFFENSE); else - havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_MIDDLE); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_MIDDLE); } -void havocbot_role_ctf_carrier() -{SELFPARAM(); - if(self.deadflag != DEAD_NO) +void havocbot_role_ctf_carrier(entity this) +{ + if(IS_DEAD(this)) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.flagcarried == world) + if (this.flagcarried == world) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); + navigation_goalrating_start(this); if(ctf_oneflag) - havocbot_goalrating_ctf_enemybase(50000); + havocbot_goalrating_ctf_enemybase(this, 50000); else - havocbot_goalrating_ctf_ourbase(50000); + havocbot_goalrating_ctf_ourbase(this, 50000); - if(self.health<100) - havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000); + if(this.health<100) + havocbot_goalrating_ctf_carrieritems(this, 1000, this.origin, 1000); - navigation_goalrating_end(); + navigation_goalrating_end(this); - if (self.navigation_hasgoals) - self.havocbot_cantfindflag = time + 10; - else if (time > self.havocbot_cantfindflag) + if (this.navigation_hasgoals) + this.havocbot_cantfindflag = time + 10; + else if (time > this.havocbot_cantfindflag) { // Can't navigate to my own base, suicide! // TODO: drop it and wander around - Damage(self, self, self, 100000, DEATH_KILL.m_id, self.origin, '0 0 0'); + Damage(this, this, this, 100000, DEATH_KILL.m_id, this.origin, '0 0 0'); return; } } } -void havocbot_role_ctf_escort() -{SELFPARAM(); +void havocbot_role_ctf_escort(entity this) +{ entity mf, ef; - if(self.deadflag != DEAD_NO) + if(IS_DEAD(this)) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.flagcarried) + if (this.flagcarried) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_CARRIER); return; } // If enemy flag is back on the base switch to previous role - ef = havocbot_ctf_find_enemy_flag(self); + ef = havocbot_ctf_find_enemy_flag(this); if(ef.ctf_status==FLAG_BASE) { - self.havocbot_role = self.havocbot_previous_role; - self.havocbot_role_timeout = 0; + this.havocbot_role = this.havocbot_previous_role; + this.havocbot_role_timeout = 0; return; } // If the flag carrier reached the base switch to defense - mf = havocbot_ctf_find_flag(self); + mf = havocbot_ctf_find_flag(this); if(mf.ctf_status!=FLAG_BASE) if(vlen(ef.origin - mf.dropped_origin) < 300) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_DEFENSE); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_DEFENSE); return; } // Set the role timeout if necessary - if (!self.havocbot_role_timeout) + if (!this.havocbot_role_timeout) { - self.havocbot_role_timeout = time + random() * 30 + 60; + this.havocbot_role_timeout = time + random() * 30 + 60; } // If nothing happened just switch to previous role - if (time > self.havocbot_role_timeout) + if (time > this.havocbot_role_timeout) { - self.havocbot_role = self.havocbot_previous_role; - self.havocbot_role_timeout = 0; + this.havocbot_role = this.havocbot_previous_role; + this.havocbot_role_timeout = 0; return; } // Chase the flag carrier - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); - havocbot_goalrating_ctf_enemyflag(30000); - havocbot_goalrating_ctf_ourstolenflag(40000); - havocbot_goalrating_items(10000, self.origin, 10000); - navigation_goalrating_end(); + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_start(this); + havocbot_goalrating_ctf_enemyflag(this, 30000); + havocbot_goalrating_ctf_ourstolenflag(this, 40000); + havocbot_goalrating_items(this, 10000, this.origin, 10000); + navigation_goalrating_end(this); } } -void havocbot_role_ctf_offense() -{SELFPARAM(); +void havocbot_role_ctf_offense(entity this) +{ entity mf, ef; vector pos; - if(self.deadflag != DEAD_NO) + if(IS_DEAD(this)) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.flagcarried) + if (this.flagcarried) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_CARRIER); return; } // Check flags - mf = havocbot_ctf_find_flag(self); - ef = havocbot_ctf_find_enemy_flag(self); + mf = havocbot_ctf_find_flag(this); + ef = havocbot_ctf_find_enemy_flag(this); // Own flag stolen if(mf.ctf_status!=FLAG_BASE) @@ -1891,9 +1704,9 @@ void havocbot_role_ctf_offense() pos = mf.origin; // Try to get it if closer than the enemy base - if(vlen(self.origin-ef.dropped_origin)>vlen(self.origin-pos)) + if(vlen(this.origin-ef.dropped_origin)>vlen(this.origin-pos)) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_RETRIEVER); return; } } @@ -1908,173 +1721,173 @@ void havocbot_role_ctf_offense() if(vlen(pos-mf.dropped_origin)>700) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_ESCORT); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_ESCORT); return; } } // About to fail, switch to middlefield - if(self.health<50) + if(this.health<50) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_MIDDLE); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_MIDDLE); return; } // Set the role timeout if necessary - if (!self.havocbot_role_timeout) - self.havocbot_role_timeout = time + 120; + if (!this.havocbot_role_timeout) + this.havocbot_role_timeout = time + 120; - if (time > self.havocbot_role_timeout) + if (time > this.havocbot_role_timeout) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); - havocbot_goalrating_ctf_ourstolenflag(50000); - havocbot_goalrating_ctf_enemybase(20000); - havocbot_goalrating_items(5000, self.origin, 1000); - havocbot_goalrating_items(1000, self.origin, 10000); - navigation_goalrating_end(); + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_start(this); + havocbot_goalrating_ctf_ourstolenflag(this, 50000); + havocbot_goalrating_ctf_enemybase(this, 20000); + havocbot_goalrating_items(this, 5000, this.origin, 1000); + havocbot_goalrating_items(this, 1000, this.origin, 10000); + navigation_goalrating_end(this); } } // Retriever (temporary role): -void havocbot_role_ctf_retriever() -{SELFPARAM(); +void havocbot_role_ctf_retriever(entity this) +{ entity mf; - if(self.deadflag != DEAD_NO) + if(IS_DEAD(this)) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.flagcarried) + if (this.flagcarried) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_CARRIER); return; } // If flag is back on the base switch to previous role - mf = havocbot_ctf_find_flag(self); + mf = havocbot_ctf_find_flag(this); if(mf.ctf_status==FLAG_BASE) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (!self.havocbot_role_timeout) - self.havocbot_role_timeout = time + 20; + if (!this.havocbot_role_timeout) + this.havocbot_role_timeout = time + 20; - if (time > self.havocbot_role_timeout) + if (time > this.havocbot_role_timeout) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { float rt_radius; rt_radius = 10000; - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); - havocbot_goalrating_ctf_ourstolenflag(50000); - havocbot_goalrating_ctf_droppedflags(40000, self.origin, rt_radius); - havocbot_goalrating_ctf_enemybase(30000); - havocbot_goalrating_items(500, self.origin, rt_radius); - navigation_goalrating_end(); + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_start(this); + havocbot_goalrating_ctf_ourstolenflag(this, 50000); + havocbot_goalrating_ctf_droppedflags(this, 40000, this.origin, rt_radius); + havocbot_goalrating_ctf_enemybase(this, 30000); + havocbot_goalrating_items(this, 500, this.origin, rt_radius); + navigation_goalrating_end(this); } } -void havocbot_role_ctf_middle() -{SELFPARAM(); +void havocbot_role_ctf_middle(entity this) +{ entity mf; - if(self.deadflag != DEAD_NO) + if(IS_DEAD(this)) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.flagcarried) + if (this.flagcarried) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_CARRIER); return; } - mf = havocbot_ctf_find_flag(self); + mf = havocbot_ctf_find_flag(this); if(mf.ctf_status!=FLAG_BASE) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_RETRIEVER); return; } - if (!self.havocbot_role_timeout) - self.havocbot_role_timeout = time + 10; + if (!this.havocbot_role_timeout) + this.havocbot_role_timeout = time + 10; - if (time > self.havocbot_role_timeout) + if (time > this.havocbot_role_timeout) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { vector org; org = havocbot_ctf_middlepoint; - org.z = self.origin.z; + org.z = this.origin.z; - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); - havocbot_goalrating_ctf_ourstolenflag(50000); - havocbot_goalrating_ctf_droppedflags(30000, self.origin, 10000); - havocbot_goalrating_enemyplayers(10000, org, havocbot_ctf_middlepoint_radius * 0.5); - havocbot_goalrating_items(5000, org, havocbot_ctf_middlepoint_radius * 0.5); - havocbot_goalrating_items(2500, self.origin, 10000); - havocbot_goalrating_ctf_enemybase(2500); - navigation_goalrating_end(); + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_start(this); + havocbot_goalrating_ctf_ourstolenflag(this, 50000); + havocbot_goalrating_ctf_droppedflags(this, 30000, this.origin, 10000); + havocbot_goalrating_enemyplayers(this, 10000, org, havocbot_ctf_middlepoint_radius * 0.5); + havocbot_goalrating_items(this, 5000, org, havocbot_ctf_middlepoint_radius * 0.5); + havocbot_goalrating_items(this, 2500, this.origin, 10000); + havocbot_goalrating_ctf_enemybase(this, 2500); + navigation_goalrating_end(this); } } -void havocbot_role_ctf_defense() -{SELFPARAM(); +void havocbot_role_ctf_defense(entity this) +{ entity mf; - if(self.deadflag != DEAD_NO) + if(IS_DEAD(this)) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.flagcarried) + if (this.flagcarried) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_CARRIER); return; } // If own flag was captured - mf = havocbot_ctf_find_flag(self); + mf = havocbot_ctf_find_flag(this); if(mf.ctf_status!=FLAG_BASE) { - havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER); + havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_RETRIEVER); return; } - if (!self.havocbot_role_timeout) - self.havocbot_role_timeout = time + 30; + if (!this.havocbot_role_timeout) + this.havocbot_role_timeout = time + 30; - if (time > self.havocbot_role_timeout) + if (time > this.havocbot_role_timeout) { - havocbot_ctf_reset_role(self); + havocbot_ctf_reset_role(this); return; } - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { float mp_radius; vector org; @@ -2082,37 +1895,33 @@ void havocbot_role_ctf_defense() org = mf.dropped_origin; mp_radius = havocbot_ctf_middlepoint_radius; - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_start(this); // if enemies are closer to our base, go there - entity head, closestplayer = world; + entity closestplayer = world; float distance, bestdistance = 10000; - FOR_EACH_PLAYER(head) - { - if(head.deadflag!=DEAD_NO) - continue; - - distance = vlen(org - head.origin); + FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), LAMBDA( + distance = vlen(org - it.origin); if(distance1000) - if(checkpvs(self.origin,closestplayer)||random()<0.5) - havocbot_goalrating_ctf_ourbase(30000); + if(DIFF_TEAM(closestplayer, this)) + if(vlen(org - this.origin)>1000) + if(checkpvs(this.origin,closestplayer)||random()<0.5) + havocbot_goalrating_ctf_ourbase(this, 30000); - havocbot_goalrating_ctf_ourstolenflag(20000); - havocbot_goalrating_ctf_droppedflags(20000, org, mp_radius); - havocbot_goalrating_enemyplayers(15000, org, mp_radius); - havocbot_goalrating_items(10000, org, mp_radius); - havocbot_goalrating_items(5000, self.origin, 10000); - navigation_goalrating_end(); + havocbot_goalrating_ctf_ourstolenflag(this, 20000); + havocbot_goalrating_ctf_droppedflags(this, 20000, org, mp_radius); + havocbot_goalrating_enemyplayers(this, 15000, org, mp_radius); + havocbot_goalrating_items(this, 10000, org, mp_radius); + havocbot_goalrating_items(this, 5000, this.origin, 10000); + navigation_goalrating_end(this); } } @@ -2167,12 +1976,13 @@ void havocbot_role_ctf_setrole(entity bot, int role) // ============== MUTATOR_HOOKFUNCTION(ctf, PlayerPreThink) -{SELFPARAM(); - entity flag; +{ + entity player = M_ARGV(0, entity); + int t = 0, t2 = 0, t3 = 0; // initially clear items so they can be set as necessary later. - self.ctf_flagstatus &= ~(CTF_RED_FLAG_CARRYING | CTF_RED_FLAG_TAKEN | CTF_RED_FLAG_LOST + player.ctf_flagstatus &= ~(CTF_RED_FLAG_CARRYING | CTF_RED_FLAG_TAKEN | CTF_RED_FLAG_LOST | CTF_BLUE_FLAG_CARRYING | CTF_BLUE_FLAG_TAKEN | CTF_BLUE_FLAG_LOST | CTF_YELLOW_FLAG_CARRYING | CTF_YELLOW_FLAG_TAKEN | CTF_YELLOW_FLAG_LOST | CTF_PINK_FLAG_CARRYING | CTF_PINK_FLAG_TAKEN | CTF_PINK_FLAG_LOST @@ -2180,46 +1990,49 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerPreThink) | CTF_FLAG_NEUTRAL | CTF_SHIELDED); // scan through all the flags and notify the client about them - for(flag = ctf_worldflaglist; flag; flag = flag.ctf_worldflagnext) + for(entity flag = ctf_worldflaglist; flag; flag = flag.ctf_worldflagnext) { if(flag.team == NUM_TEAM_1) { t = CTF_RED_FLAG_CARRYING; t2 = CTF_RED_FLAG_TAKEN; t3 = CTF_RED_FLAG_LOST; } if(flag.team == NUM_TEAM_2) { t = CTF_BLUE_FLAG_CARRYING; t2 = CTF_BLUE_FLAG_TAKEN; t3 = CTF_BLUE_FLAG_LOST; } if(flag.team == NUM_TEAM_3) { t = CTF_YELLOW_FLAG_CARRYING; t2 = CTF_YELLOW_FLAG_TAKEN; t3 = CTF_YELLOW_FLAG_LOST; } if(flag.team == NUM_TEAM_4) { t = CTF_PINK_FLAG_CARRYING; t2 = CTF_PINK_FLAG_TAKEN; t3 = CTF_PINK_FLAG_LOST; } - if(flag.team == 0) { t = CTF_NEUTRAL_FLAG_CARRYING; t2 = CTF_NEUTRAL_FLAG_TAKEN; t3 = CTF_NEUTRAL_FLAG_LOST; self.ctf_flagstatus |= CTF_FLAG_NEUTRAL; } + if(flag.team == 0) { t = CTF_NEUTRAL_FLAG_CARRYING; t2 = CTF_NEUTRAL_FLAG_TAKEN; t3 = CTF_NEUTRAL_FLAG_LOST; player.ctf_flagstatus |= CTF_FLAG_NEUTRAL; } switch(flag.ctf_status) { case FLAG_PASSING: case FLAG_CARRY: { - if((flag.owner == self) || (flag.pass_sender == self)) - self.ctf_flagstatus |= t; // carrying: self is currently carrying the flag + if((flag.owner == player) || (flag.pass_sender == player)) + player.ctf_flagstatus |= t; // carrying: player is currently carrying the flag else - self.ctf_flagstatus |= t2; // taken: someone else is carrying the flag + player.ctf_flagstatus |= t2; // taken: someone else is carrying the flag break; } case FLAG_DROPPED: { - self.ctf_flagstatus |= t3; // lost: the flag is dropped somewhere on the map + player.ctf_flagstatus |= t3; // lost: the flag is dropped somewhere on the map break; } } } // item for stopping players from capturing the flag too often - if(self.ctf_captureshielded) - self.ctf_flagstatus |= CTF_SHIELDED; + if(player.ctf_captureshielded) + player.ctf_flagstatus |= CTF_SHIELDED; // update the health of the flag carrier waypointsprite - if(self.wps_flagcarrier) - WaypointSprite_UpdateHealth(self.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id)); - - return false; + if(player.wps_flagcarrier) + WaypointSprite_UpdateHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(player.health, player.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id)); } MUTATOR_HOOKFUNCTION(ctf, PlayerDamage_Calculate) // for changing damage and force values that are applied to players in g_damage.qc { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + float frag_damage = M_ARGV(4, float); + vector frag_force = M_ARGV(6, vector); + if(frag_attacker.flagcarried) // if the attacker is a flagcarrier { if(frag_target == frag_attacker) // damage done to yourself @@ -2232,8 +2045,11 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerDamage_Calculate) // for changing damage and for frag_damage *= autocvar_g_ctf_flagcarrier_damagefactor; frag_force *= autocvar_g_ctf_flagcarrier_forcefactor; } + + M_ARGV(4, float) = frag_damage; + M_ARGV(6, vector) = frag_force; } - else if(frag_target.flagcarried && (frag_target.deadflag == DEAD_NO) && CTF_DIFFTEAM(frag_target, frag_attacker)) // if the target is a flagcarrier + else if(frag_target.flagcarried && !IS_DEAD(frag_target) && CTF_DIFFTEAM(frag_target, frag_attacker)) // if the target is a flagcarrier { if(autocvar_g_ctf_flagcarrier_auto_helpme_damage > ('1 0 0' * healtharmor_maxdamage(frag_target.health, frag_target.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id))) if(time > frag_target.wps_helpme_time + autocvar_g_ctf_flagcarrier_auto_helpme_time) @@ -2243,11 +2059,13 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerDamage_Calculate) // for changing damage and for } // todo: add notification for when flag carrier needs help? } - return false; } MUTATOR_HOOKFUNCTION(ctf, PlayerDies) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)) && (frag_target.flagcarried)) { PlayerTeamScore_AddScore(frag_attacker, ((SAME_TEAM(frag_attacker, frag_target)) ? -autocvar_g_ctf_score_kill : autocvar_g_ctf_score_kill)); @@ -2260,13 +2078,11 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerDies) ctf_Handle_Throw(frag_target, world, DROP_NORMAL); tmp_entity.ctf_dropper = world; } - - return false; } MUTATOR_HOOKFUNCTION(ctf, GiveFragsForKill) { - frag_score = 0; + M_ARGV(2, float) = 0; // frag score return (autocvar_g_ctf_ignore_frags); // no frags counted in ctf if this is true } @@ -2284,33 +2100,35 @@ void ctf_RemovePlayer(entity player) } MUTATOR_HOOKFUNCTION(ctf, MakePlayerObserver) -{SELFPARAM(); - ctf_RemovePlayer(self); - return false; +{ + entity player = M_ARGV(0, entity); + + ctf_RemovePlayer(player); } MUTATOR_HOOKFUNCTION(ctf, ClientDisconnect) -{SELFPARAM(); - ctf_RemovePlayer(self); - return false; +{ + entity player = M_ARGV(0, entity); + + ctf_RemovePlayer(player); } MUTATOR_HOOKFUNCTION(ctf, PortalTeleport) -{SELFPARAM(); - if(self.flagcarried) - if(!autocvar_g_ctf_portalteleport) - { ctf_Handle_Throw(self, world, DROP_NORMAL); } +{ + entity player = M_ARGV(0, entity); - return false; + if(player.flagcarried) + if(!autocvar_g_ctf_portalteleport) + { ctf_Handle_Throw(player, world, DROP_NORMAL); } } MUTATOR_HOOKFUNCTION(ctf, PlayerUseKey) -{SELFPARAM(); - if(MUTATOR_RETURNVALUE || gameover) { return false; } +{ + if(MUTATOR_RETURNVALUE || gameover) { return; } - entity player = self; + entity player = M_ARGV(0, entity); - if((time > player.throw_antispam) && (player.deadflag == DEAD_NO) && !player.speedrunning && (!player.vehicle || autocvar_g_ctf_allow_vehicle_touch)) + if((time > player.throw_antispam) && !IS_DEAD(player) && !player.speedrunning && (!player.vehicle || autocvar_g_ctf_allow_vehicle_touch)) { // pass the flag to a team mate if(autocvar_g_ctf_pass) @@ -2320,7 +2138,7 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerUseKey) while(head) // find the closest acceptable target to pass to { - if(IS_PLAYER(head) && head.deadflag == DEAD_NO) + if(IS_PLAYER(head) && !IS_DEAD(head)) if(head != player && SAME_TEAM(head, player)) if(!head.speedrunning && !head.vehicle) { @@ -2393,21 +2211,21 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerUseKey) } } } - - return false; } MUTATOR_HOOKFUNCTION(ctf, HelpMePing) -{SELFPARAM(); - if(self.wps_flagcarrier) // update the flagcarrier waypointsprite with "NEEDING HELP" notification +{ + entity player = M_ARGV(0, entity); + + if(player.wps_flagcarrier) // update the flagcarrier waypointsprite with "NEEDING HELP" notification { - self.wps_helpme_time = time; - WaypointSprite_HelpMePing(self.wps_flagcarrier); + player.wps_helpme_time = time; + WaypointSprite_HelpMePing(player.wps_flagcarrier); } else // create a normal help me waypointsprite { - WaypointSprite_Spawn(WP_Helpme, waypointsprite_deployed_lifetime, waypointsprite_limitedrange, self, FLAG_WAYPOINT_OFFSET, world, self.team, self, wps_helpme, false, RADARICON_HELPME); - WaypointSprite_Ping(self.wps_helpme); + WaypointSprite_Spawn(WP_Helpme, waypointsprite_deployed_lifetime, waypointsprite_limitedrange, player, FLAG_WAYPOINT_OFFSET, world, player.team, player, wps_helpme, false, RADARICON_HELPME); + WaypointSprite_Ping(player.wps_helpme); } return true; @@ -2415,52 +2233,53 @@ MUTATOR_HOOKFUNCTION(ctf, HelpMePing) MUTATOR_HOOKFUNCTION(ctf, VehicleEnter) { - if(vh_player.flagcarried) + entity player = M_ARGV(0, entity); + entity veh = M_ARGV(1, entity); + + if(player.flagcarried) { - vh_player.flagcarried.nodrawtoclient = vh_player; // hide the flag from the driver + player.flagcarried.nodrawtoclient = player; // hide the flag from the driver if(!autocvar_g_ctf_allow_vehicle_carry && !autocvar_g_ctf_allow_vehicle_touch) { - ctf_Handle_Throw(vh_player, world, DROP_NORMAL); + ctf_Handle_Throw(player, world, DROP_NORMAL); } else { - setattachment(vh_player.flagcarried, vh_vehicle, ""); - setorigin(vh_player.flagcarried, VEHICLE_FLAG_OFFSET); - vh_player.flagcarried.scale = VEHICLE_FLAG_SCALE; - //vh_player.flagcarried.angles = '0 0 0'; + setattachment(player.flagcarried, veh, ""); + setorigin(player.flagcarried, VEHICLE_FLAG_OFFSET); + player.flagcarried.scale = VEHICLE_FLAG_SCALE; + //player.flagcarried.angles = '0 0 0'; } return true; } - - return false; } MUTATOR_HOOKFUNCTION(ctf, VehicleExit) { - if(vh_player.flagcarried) + entity player = M_ARGV(0, entity); + + if(player.flagcarried) { - setattachment(vh_player.flagcarried, vh_player, ""); - setorigin(vh_player.flagcarried, FLAG_CARRY_OFFSET); - vh_player.flagcarried.scale = FLAG_SCALE; - vh_player.flagcarried.angles = '0 0 0'; - vh_player.flagcarried.nodrawtoclient = world; + setattachment(player.flagcarried, player, ""); + setorigin(player.flagcarried, FLAG_CARRY_OFFSET); + player.flagcarried.scale = FLAG_SCALE; + player.flagcarried.angles = '0 0 0'; + player.flagcarried.nodrawtoclient = world; return true; } - - return false; } MUTATOR_HOOKFUNCTION(ctf, AbortSpeedrun) -{SELFPARAM(); - if(self.flagcarried) +{ + entity player = M_ARGV(0, entity); + + if(player.flagcarried) { - Send_Notification(NOTIF_ALL, world, MSG_INFO, ((self.flagcarried.team) ? APP_TEAM_ENT_4(self.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN_) : INFO_CTF_FLAGRETURN_ABORTRUN_NEUTRAL)); - ctf_RespawnFlag(self.flagcarried); + Send_Notification(NOTIF_ALL, world, MSG_INFO, ((player.flagcarried.team) ? APP_TEAM_ENT(player.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN) : INFO_CTF_FLAGRETURN_ABORTRUN_NEUTRAL)); + ctf_RespawnFlag(player.flagcarried); return true; } - - return false; } MUTATOR_HOOKFUNCTION(ctf, MatchEnd) @@ -2493,31 +2312,36 @@ MUTATOR_HOOKFUNCTION(ctf, MatchEnd) } } } - - return false; } MUTATOR_HOOKFUNCTION(ctf, HavocBot_ChooseRole) -{SELFPARAM(); - havocbot_ctf_reset_role(self); +{ + entity bot = M_ARGV(0, entity); + + havocbot_ctf_reset_role(bot); return true; } MUTATOR_HOOKFUNCTION(ctf, GetTeamCount) { - //ret_float = ctf_teams; - ret_string = "ctf_team"; + //M_ARGV(0, float) = ctf_teams; + M_ARGV(1, string) = "ctf_team"; return true; } MUTATOR_HOOKFUNCTION(ctf, SpectateCopy) -{SELFPARAM(); - self.ctf_flagstatus = other.ctf_flagstatus; - return false; +{ + entity spectatee = M_ARGV(0, entity); + entity client = M_ARGV(1, entity); + + client.ctf_flagstatus = spectatee.ctf_flagstatus; } MUTATOR_HOOKFUNCTION(ctf, GetRecords) { + int record_page = M_ARGV(0, int); + string ret_string = M_ARGV(1, string); + for(int i = record_page * 200; i < MapInfo_count && i < record_page * 200 + 200; ++i) { if (MapInfo_Get_ByID(i)) @@ -2533,21 +2357,24 @@ MUTATOR_HOOKFUNCTION(ctf, GetRecords) } } - return false; + M_ARGV(1, string) = ret_string; } -bool superspec_Spectate(entity _player); // TODO +bool superspec_Spectate(entity this, entity targ); // TODO void superspec_msg(string _center_title, string _con_title, entity _to, string _msg, float _spamlevel); // TODO MUTATOR_HOOKFUNCTION(ctf, SV_ParseClientCommand) { - if(IS_PLAYER(self) || MUTATOR_RETURNVALUE || !cvar("g_superspectate")) { return false; } + entity player = M_ARGV(0, entity); + string cmd_name = M_ARGV(1, string); + int cmd_argc = M_ARGV(2, int); + + if(IS_PLAYER(player) || MUTATOR_RETURNVALUE || !cvar("g_superspectate")) { return false; } if(cmd_name == "followfc") { if(!g_ctf) return true; - entity _player; int _team = 0; bool found = false; @@ -2562,31 +2389,28 @@ MUTATOR_HOOKFUNCTION(ctf, SV_ParseClientCommand) } } - FOR_EACH_PLAYER(_player) - { - if(_player.flagcarried && (_player.team == _team || _team == 0)) + FOREACH_CLIENT(IS_PLAYER(it), LAMBDA( + if(it.flagcarried && (it.team == _team || _team == 0)) { found = true; - if(_team == 0 && IS_SPEC(self) && self.enemy == _player) - continue; // already spectating a fc, try to find the other fc - return superspec_Spectate(_player); + if(_team == 0 && IS_SPEC(player) && player.enemy == it) + continue; // already spectating this fc, try another + return superspec_Spectate(player, it); } - } + )); if(!found) - superspec_msg("", "", self, "No active flag carrier\n", 1); + superspec_msg("", "", player, "No active flag carrier\n", 1); return true; } - - return false; } MUTATOR_HOOKFUNCTION(ctf, DropSpecialItems) { + entity frag_target = M_ARGV(0, entity); + if(frag_target.flagcarried) ctf_Handle_Throw(frag_target, world, DROP_THROW); - - return false; } @@ -2607,9 +2431,9 @@ Keys: "noise5" sound played when flag touches the ground... */ spawnfunc(item_flag_team1) { - if(!g_ctf) { remove(self); return; } + if(!g_ctf) { remove(this); return; } - ctf_FlagSetup(NUM_TEAM_1, self); + ctf_FlagSetup(NUM_TEAM_1, this); } /*QUAKED spawnfunc_item_flag_team2 (0 0.5 0.8) (-48 -48 -37) (48 48 37) @@ -2625,9 +2449,9 @@ Keys: "noise5" sound played when flag touches the ground... */ spawnfunc(item_flag_team2) { - if(!g_ctf) { remove(self); return; } + if(!g_ctf) { remove(this); return; } - ctf_FlagSetup(NUM_TEAM_2, self); + ctf_FlagSetup(NUM_TEAM_2, this); } /*QUAKED spawnfunc_item_flag_team3 (0 0.5 0.8) (-48 -48 -37) (48 48 37) @@ -2643,9 +2467,9 @@ Keys: "noise5" sound played when flag touches the ground... */ spawnfunc(item_flag_team3) { - if(!g_ctf) { remove(self); return; } + if(!g_ctf) { remove(this); return; } - ctf_FlagSetup(NUM_TEAM_3, self); + ctf_FlagSetup(NUM_TEAM_3, this); } /*QUAKED spawnfunc_item_flag_team4 (0 0.5 0.8) (-48 -48 -37) (48 48 37) @@ -2661,9 +2485,9 @@ Keys: "noise5" sound played when flag touches the ground... */ spawnfunc(item_flag_team4) { - if(!g_ctf) { remove(self); return; } + if(!g_ctf) { remove(this); return; } - ctf_FlagSetup(NUM_TEAM_4, self); + ctf_FlagSetup(NUM_TEAM_4, this); } /*QUAKED spawnfunc_item_flag_neutral (0 0.5 0.8) (-48 -48 -37) (48 48 37) @@ -2679,10 +2503,10 @@ Keys: "noise5" sound played when flag touches the ground... */ spawnfunc(item_flag_neutral) { - if(!g_ctf) { remove(self); return; } - if(!cvar("g_ctf_oneflag")) { remove(self); return; } + if(!g_ctf) { remove(this); return; } + if(!cvar("g_ctf_oneflag")) { remove(this); return; } - ctf_FlagSetup(0, self); + ctf_FlagSetup(0, this); } /*QUAKED spawnfunc_ctf_team (0 .5 .8) (-16 -16 -24) (16 16 32) @@ -2693,10 +2517,10 @@ Keys: "cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */ spawnfunc(ctf_team) { - if(!g_ctf) { remove(self); return; } + if(!g_ctf) { remove(this); return; } - self.classname = "ctf_team"; - self.team = self.cnt + 1; + this.classname = "ctf_team"; + this.team = this.cnt + 1; } // compatibility for quake maps @@ -2709,8 +2533,8 @@ spawnfunc(info_player_team2); spawnfunc(team_CTF_blueplayer) { spawnfunc_info_player_team2(this); } spawnfunc(team_CTF_bluespawn) { spawnfunc_info_player_team2(this); } -void team_CTF_neutralflag() { SELFPARAM(); spawnfunc_item_flag_neutral(self); } -void team_neutralobelisk() { SELFPARAM(); spawnfunc_item_flag_neutral(self); } +spawnfunc(team_CTF_neutralflag) { spawnfunc_item_flag_neutral(this); } +spawnfunc(team_neutralobelisk) { spawnfunc_item_flag_neutral(this); } // ============== @@ -2735,14 +2559,14 @@ void ctf_ScoreRules(int teams) // code from here on is just to support maps that don't have flag and team entities void ctf_SpawnTeam (string teamname, int teamcolor) { - entity this = new(ctf_team); + entity this = new_pure(ctf_team); this.netname = teamname; this.cnt = teamcolor; this.spawnfunc_checked = true; - WITH(entity, self, this, spawnfunc_ctf_team(this)); + WITHSELF(this, spawnfunc_ctf_team(this)); } -void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to be set up. +void ctf_DelayedInit(entity this) // Do this check with a delay so we can wait for teams to be set up. { ctf_teams = 2;