X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fgamemode_ctf.qc;h=f95d956c0f671ca0efe6b642b7ee596978044e5e;hb=06ee57203283ee16b27a716619866d0a524b6505;hp=908d81cf3fe0a9d96b13a1c529a8db568f5008a9;hpb=373da6f709e05d4e1bf696da0b03ef2a880a2583;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/mutators/gamemode_ctf.qc b/qcsrc/server/mutators/gamemode_ctf.qc index 908d81cf3..f95d956c0 100644 --- a/qcsrc/server/mutators/gamemode_ctf.qc +++ b/qcsrc/server/mutators/gamemode_ctf.qc @@ -20,36 +20,25 @@ void ctf_EventLog(string mode, float flagteam, entity actor) // use an alias for GameLogEcho(strcat(":ctf:", mode, ":", ftos(flagteam), ((actor != world) ? (strcat(":", ftos(actor.playerid))) : ""))); } -string ctf_CaptureRecord(entity flag, entity player) +void ctf_CaptureRecord(entity flag, entity player) { - float cap_time, cap_record, success; - string cap_message = string_null, refername; + float cap_record = ctf_captimerecord; + float cap_time = (time - flag.ctf_pickuptime); + string refername = db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname")); - if((autocvar_g_ctf_captimerecord_always) || (player_count - currentbots)) - { - cap_record = ctf_captimerecord; - cap_time = (time - flag.ctf_pickuptime); - - refername = db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname")); - refername = ((refername == player.netname) ? "their" : strcat(refername, "^7's")); - - if(!ctf_captimerecord) - { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds"); success = TRUE; } - else if(cap_time < cap_record) - { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds, breaking ", refername, " previous record of ", ftos_decimals(cap_record, 2), " seconds"); success = TRUE; } - else - { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds, failing to break ", refername, " record of ", ftos_decimals(cap_record, 2), " seconds"); success = FALSE; } - - if(success) - { - ctf_captimerecord = cap_time; - db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(cap_time)); - db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), player.netname); - write_recordmarker(player, (time - cap_time), cap_time); - } - } + // notify about shit + if(!ctf_captimerecord) { Send_Notification(NOTIF_ALL, world, MSG_CHOICE, APP_TEAM_ENT_2(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_2(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_2(flag, CHOICE_CTF_CAPTURE_UNBROKEN_), player.netname, refername, (cap_time * 100), (cap_record * 100)); } - return cap_message; + // write that shit in the database + if((!ctf_captimerecord) || (cap_time < cap_record)) + { + ctf_captimerecord = cap_time; + db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(cap_time)); + db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), player.netname); + write_recordmarker(player, (time - cap_time), cap_time); + } } void ctf_FlagcarrierWaypoints(entity player) @@ -143,7 +132,7 @@ float ctf_CaptureShield_CheckStatus(entity p) players_total = players_worseeq = 0; FOR_EACH_PLAYER(e) { - if(IsDifferentTeam(e, p)) + if(DIFF_TEAM(e, p)) continue; se = PlayerScore_Add(e, SP_SCORE, 0); if(se <= s) @@ -165,11 +154,7 @@ void ctf_CaptureShield_Update(entity player, float wanted_status) float updated_status = ctf_CaptureShield_CheckStatus(player); if((wanted_status == player.ctf_captureshielded) && (updated_status != wanted_status)) // 0: shield only, 1: unshield only { - if(updated_status) // TODO csqc notifier for this // Samual: How? - Send_CSQC_Centerprint_Generic(player, CPID_CTF_CAPTURESHIELD, "^3You are now ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Make some defensive scores before trying again.", 5, 0); - else - Send_CSQC_Centerprint_Generic(player, CPID_CTF_CAPTURESHIELD, "^3You are now free.\n\n^3Feel free to ^1try to capture^3 the flag again\n^3if you think you will succeed.", 5, 0); - + Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((updated_status) ? CENTER_CTF_CAPTURESHIELD_SHIELDED : CENTER_CTF_CAPTURESHIELD_FREE)); player.ctf_captureshielded = updated_status; } } @@ -177,7 +162,7 @@ void ctf_CaptureShield_Update(entity player, float wanted_status) float ctf_CaptureShield_Customize() { if(!other.ctf_captureshielded) { return FALSE; } - if(!IsDifferentTeam(self, other)) { return FALSE; } + if(SAME_TEAM(self, other)) { return FALSE; } return TRUE; } @@ -185,13 +170,13 @@ float ctf_CaptureShield_Customize() void ctf_CaptureShield_Touch() { if(!other.ctf_captureshielded) { return; } - if(!IsDifferentTeam(self, other)) { return; } + if(SAME_TEAM(self, other)) { return; } vector mymid = (self.absmin + self.absmax) * 0.5; vector othermid = (other.absmin + other.absmax) * 0.5; Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * ctf_captureshield_force); - Send_CSQC_Centerprint_Generic(other, CPID_CTF_CAPTURESHIELD, "^3You are ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Get some defensive scores before trying again.", 5, 0); + Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_CTF_CAPTURESHIELD_SHIELDED); } void ctf_CaptureShield_Spawn(entity flag) @@ -234,8 +219,8 @@ void ctf_Handle_Drop(entity flag, entity player, float droptype) flag.ctf_status = FLAG_DROPPED; // messages and sounds - Send_KillNotification(player.netname, flag.netname, "", INFO_LOSTFLAG, MSG_INFO); - sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTN_NONE); + Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_LOST_), player.netname); + sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE); ctf_EventLog("dropped", player.team, player); // scoring @@ -281,17 +266,17 @@ void ctf_Handle_Retrieve(entity flag, entity player) flag.ctf_status = FLAG_CARRY; // messages and sounds - sound(player, CH_TRIGGER, flag.snd_flag_pass, VOL_BASE, ATTN_NORM); + 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) - centerprint(tmp_player, strcat("You passed the ", flag.netname, " to ", player.netname)); + Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_SENT_), player.netname); else if(tmp_player == player) - centerprint(tmp_player, strcat("You received the ", flag.netname, " from ", sender.netname)); - else if(!IsDifferentTeam(tmp_player, sender)) - centerprint(tmp_player, strcat(sender.netname, " passed the ", flag.netname, " to ", player.netname)); + Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_RECEIVED_), sender.netname); + else if(SAME_TEAM(tmp_player, sender)) + Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_OTHER_), sender.netname, player.netname); } // create new waypoint @@ -348,7 +333,7 @@ void ctf_Handle_Throw(entity player, entity receiver, float droptype) flag.ctf_status = FLAG_PASSING; // other - sound(player, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTN_NORM); + sound(player, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTEN_NORM); WarpZone_TrailParticles(world, particleeffectnum(flag.passeffect), player.origin, targ_origin); ctf_EventLog("pass", flag.team, player); break; @@ -404,8 +389,9 @@ void ctf_Handle_Capture(entity flag, entity toucher, float capturetype) if not(player) { return; } // without someone to give the reward to, we can't possibly cap // messages and sounds - Send_KillNotification(player.netname, enemy_flag.netname, ctf_CaptureRecord(enemy_flag, player), INFO_CAPTUREFLAG, MSG_INFO); - sound(player, CH_TRIGGER, flag.snd_flag_capture, VOL_BASE, ATTN_NONE); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_2(enemy_flag, CENTER_CTF_CAPTURE_)); + ctf_CaptureRecord(enemy_flag, player); + sound(player, CH_TRIGGER, flag.snd_flag_capture, VOL_BASE, ATTEN_NONE); switch(capturetype) { @@ -445,9 +431,9 @@ void ctf_Handle_Capture(entity flag, entity toucher, float capturetype) void ctf_Handle_Return(entity flag, entity player) { // messages and sounds - //centerprint(player, strcat("You returned the ", flag.netname)); - Send_KillNotification(player.netname, flag.netname, "", INFO_RETURNFLAG, MSG_INFO); - sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTN_NONE); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_RETURN_)); + Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_RETURN_), player.netname); + sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE); ctf_EventLog("return", flag.team, player); // scoring @@ -470,8 +456,6 @@ void ctf_Handle_Return(entity flag, entity player) void ctf_Handle_Pickup(entity flag, entity player, float pickuptype) { // declarations - entity tmp_player; // temporary entity which the FOR_EACH_PLAYER loop uses to scan players - string verbosename; // holds the name of the player OR no name at all for printing in the centerprints float pickup_dropped_score; // used to calculate dropped pickup score // attach the flag to the player @@ -495,22 +479,14 @@ void ctf_Handle_Pickup(entity flag, entity player, float pickuptype) } // messages and sounds - Send_KillNotification (player.netname, flag.netname, "", INFO_GOTFLAG, MSG_INFO); - sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTN_NONE); - verbosename = ((autocvar_g_ctf_flag_pickup_verbosename) ? strcat(Team_ColorCode(player.team), "(^7", player.netname, Team_ColorCode(player.team), ") ") : ""); + Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_PICKUP_), player.netname); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PICKUP_)); + if(ctf_stalemate) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER); } - FOR_EACH_REALPLAYER(tmp_player) - { - if(tmp_player == player) - { - centerprint(tmp_player, strcat("You got the ", flag.netname, "!")); - //if(ctf_stalemate) { centerprint(tmp_player, "Stalemate! Enemies can see you on radar!"); } - } - //else if(!IsDifferentTeam(tmp_player, player)) - // centerprint(tmp_player, strcat("Your ", Team_ColorCode(player.team), "team mate ", verbosename, "^7got the flag! Protect them!")); - else if(!IsDifferentTeam(tmp_player, flag)) - centerprint(tmp_player, strcat("The ", Team_ColorCode(player.team), "enemy ", verbosename, "^7got your flag! Retrieve it!")); - } + Send_Notification(NOTIF_TEAM_EXCEPT, player, MSG_CHOICE, CHOICE_CTF_PICKUP_TEAM, Team_ColorCode(player.team), player.netname); + Send_Notification(NOTIF_TEAM, flag, MSG_CHOICE, CHOICE_CTF_PICKUP_ENEMY, Team_ColorCode(player.team), player.netname); + + sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE); // scoring PlayerScore_Add(player, SP_CTF_PICKUPS, 1); @@ -568,16 +544,16 @@ void ctf_CheckFlagReturn(entity flag, float returntype) { switch(returntype) { - case RETURN_DROPPED: bprint("The ", flag.netname, " was dropped in the base and returned itself\n"); break; - case RETURN_DAMAGE: bprint("The ", flag.netname, " was destroyed and returned to base\n"); break; - case RETURN_SPEEDRUN: bprint("The ", flag.netname, " became impatient after ", ftos_decimals(ctf_captimerecord, 2), " seconds and returned itself\n"); break; - case RETURN_NEEDKILL: bprint("The ", flag.netname, " fell somewhere it couldn't be reached and returned to base\n"); break; + case RETURN_DROPPED: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_DROPPED_)); break; + case RETURN_DAMAGE: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_DAMAGED_)); break; + case RETURN_SPEEDRUN: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_SPEEDRUN_), ctf_captimerecord); break; + case RETURN_NEEDKILL: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_NEEDKILL_)); break; default: case RETURN_TIMEOUT: - { bprint("The ", flag.netname, " has returned to base\n"); break; } + { Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_TIMEOUT_)); break; } } - sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTN_NONE); + sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE); ctf_EventLog("returned", flag.team, world); ctf_RespawnFlag(flag); } @@ -604,8 +580,8 @@ void ctf_CheckStalemate(void) switch(tmp_entity.team) { - case COLOR_TEAM1: ++stale_red_flags; break; - case COLOR_TEAM2: ++stale_blue_flags; break; + case NUM_TEAM_1: ++stale_red_flags; break; + case NUM_TEAM_2: ++stale_blue_flags; break; } } } @@ -629,10 +605,7 @@ void ctf_CheckStalemate(void) if not(wpforenemy_announced) { FOR_EACH_REALPLAYER(tmp_entity) - if(tmp_entity.flagcarried) - centerprint(tmp_entity, "Stalemate! Enemies can now see you on radar!"); - else - centerprint(tmp_entity, "Stalemate! Flag carriers can now be seen by enemies on radar!"); + Send_Notification(NOTIF_ONE, tmp_entity, MSG_CENTER, ((tmp_entity.flagcarried) ? CENTER_CTF_STALEMATE_CARRIER : CENTER_CTF_STALEMATE_OTHER)); wpforenemy_announced = TRUE; } @@ -814,12 +787,12 @@ void ctf_FlagTouch() else return; // do nothing } - else if(toucher.classname != "player") // The flag just touched an object, most likely the world + else if not(IS_PLAYER(toucher)) // The flag just touched an object, most likely the world { if(time > self.wait) // if we haven't in a while, play a sound/effect { pointparticles(particleeffectnum(self.toucheffect), self.origin, '0 0 0', 1); - sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM); self.wait = time + FLAG_TOUCHRATE; } return; @@ -830,16 +803,16 @@ void ctf_FlagTouch() { case FLAG_BASE: { - if(!IsDifferentTeam(toucher, self) && (toucher.flagcarried) && IsDifferentTeam(toucher.flagcarried, self)) + if(SAME_TEAM(toucher, self) && (toucher.flagcarried) && DIFF_TEAM(toucher.flagcarried, self)) ctf_Handle_Capture(self, toucher, CAPTURE_NORMAL); // toucher just captured the enemies flag to his base - else if(IsDifferentTeam(toucher, self) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time)) + else if(DIFF_TEAM(toucher, self) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time)) ctf_Handle_Pickup(self, toucher, PICKUP_BASE); // toucher just stole the enemies flag break; } case FLAG_DROPPED: { - if(!IsDifferentTeam(toucher, self)) + if(SAME_TEAM(toucher, self)) ctf_Handle_Return(self, toucher); // toucher just returned his own flag else if((!toucher.flagcarried) && ((toucher != self.ctf_dropper) || (time > self.ctf_droptime + autocvar_g_ctf_flag_collect_delay))) ctf_Handle_Pickup(self, toucher, PICKUP_DROPPED); // toucher just picked up a dropped enemy flag @@ -854,9 +827,9 @@ void ctf_FlagTouch() case FLAG_PASSING: { - if((toucher.classname == "player") && (toucher.deadflag == DEAD_NO) && (toucher != self.pass_sender)) + if((IS_PLAYER(toucher)) && (toucher.deadflag == DEAD_NO) && (toucher != self.pass_sender)) { - if(IsDifferentTeam(toucher, self.pass_sender)) + if(DIFF_TEAM(toucher, self.pass_sender)) ctf_Handle_Return(self, toucher); else ctf_Handle_Retrieve(self, toucher); @@ -917,7 +890,7 @@ void ctf_RespawnFlag(entity flag) void ctf_Reset() { if(self.owner) - if(self.owner.classname == "player") + if(IS_PLAYER(self.owner)) ctf_Handle_Throw(self.owner, world, DROP_RESET); ctf_RespawnFlag(self); @@ -931,7 +904,7 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf self.bot_basewaypoint = self.nearestwaypoint; // waypointsprites - WaypointSprite_SpawnFixed(((self.team == COLOR_TEAM1) ? "redbase" : "bluebase"), self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE)); + WaypointSprite_SpawnFixed(((self.team == NUM_TEAM_1) ? "redbase" : "bluebase"), self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE)); WaypointSprite_UpdateTeamRadar(self.wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE)); // captureshield setup @@ -948,10 +921,10 @@ void ctf_FlagSetup(float teamnumber, entity flag) // called when spawning a flag flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist ctf_worldflaglist = flag; - setattachment(flag, world, ""); + setattachment(flag, world, ""); - flag.netname = ((teamnumber) ? "^1RED^7 flag" : "^4BLUE^7 flag"); - flag.team = ((teamnumber) ? COLOR_TEAM1 : COLOR_TEAM2); // COLOR_TEAM1: color 4 team (red) - COLOR_TEAM2: color 13 team (blue) + flag.netname = ((teamnumber) ? "^1RED^7 flag" : "^4BLUE^7 flag"); // Primarily only used for debugging or when showing nearby item name + flag.team = ((teamnumber) ? NUM_TEAM_1 : NUM_TEAM_2); // NUM_TEAM_1: color 4 team (red) - NUM_TEAM_2: color 13 team (blue) flag.items = ((teamnumber) ? IT_KEY2 : IT_KEY1); // IT_KEY2: gold key (redish enough) - IT_KEY1: silver key (bluish enough) flag.classname = "item_flag_team"; flag.target = "###item###"; // wut? @@ -973,22 +946,23 @@ void ctf_FlagSetup(float teamnumber, entity flag) // called when spawning a flag flag.think = ctf_FlagThink; flag.nextthink = time + FLAG_THINKRATE; flag.ctf_status = FLAG_BASE; - - if(!flag.model) { flag.model = ((teamnumber) ? autocvar_g_ctf_flag_red_model : autocvar_g_ctf_flag_blue_model); } - if(!flag.scale) { flag.scale = FLAG_SCALE; } - if(!flag.skin) { flag.skin = ((teamnumber) ? autocvar_g_ctf_flag_red_skin : autocvar_g_ctf_flag_blue_skin); } - if(!flag.toucheffect) { flag.toucheffect = ((teamnumber) ? "redflag_touch" : "blueflag_touch"); } - if(!flag.passeffect) { flag.passeffect = ((teamnumber) ? "red_pass" : "blue_pass"); } - if(!flag.capeffect) { flag.capeffect = ((teamnumber) ? "red_cap" : "blue_cap"); } + + // appearence + if(flag.model == "") { flag.model = ((teamnumber) ? autocvar_g_ctf_flag_red_model : autocvar_g_ctf_flag_blue_model); } + if(!flag.scale) { flag.scale = FLAG_SCALE; } + if(!flag.skin) { flag.skin = ((teamnumber) ? autocvar_g_ctf_flag_red_skin : autocvar_g_ctf_flag_blue_skin); } + if(flag.toucheffect == "") { flag.toucheffect = ((teamnumber) ? "redflag_touch" : "blueflag_touch"); } + if(flag.passeffect == "") { flag.passeffect = ((teamnumber) ? "red_pass" : "blue_pass"); } + if(flag.capeffect == "") { flag.capeffect = ((teamnumber) ? "red_cap" : "blue_cap"); } // sound - if(!flag.snd_flag_taken) { flag.snd_flag_taken = ((teamnumber) ? "ctf/red_taken.wav" : "ctf/blue_taken.wav"); } - if(!flag.snd_flag_returned) { flag.snd_flag_returned = ((teamnumber) ? "ctf/red_returned.wav" : "ctf/blue_returned.wav"); } - if(!flag.snd_flag_capture) { flag.snd_flag_capture = ((teamnumber) ? "ctf/red_capture.wav" : "ctf/blue_capture.wav"); } // blue team scores by capturing the red flag - if(!flag.snd_flag_respawn) { flag.snd_flag_respawn = "ctf/flag_respawn.wav"; } // if there is ever a team-based sound for this, update the code to match. - if(!flag.snd_flag_dropped) { flag.snd_flag_dropped = ((teamnumber) ? "ctf/red_dropped.wav" : "ctf/blue_dropped.wav"); } - if(!flag.snd_flag_touch) { flag.snd_flag_touch = "ctf/touch.wav"; } // again has no team-based sound - if(!flag.snd_flag_pass) { flag.snd_flag_pass = "ctf/pass.wav"; } // same story here + if(flag.snd_flag_taken == "") { flag.snd_flag_taken = ((teamnumber) ? "ctf/red_taken.wav" : "ctf/blue_taken.wav"); } + if(flag.snd_flag_returned == "") { flag.snd_flag_returned = ((teamnumber) ? "ctf/red_returned.wav" : "ctf/blue_returned.wav"); } + if(flag.snd_flag_capture == "") { flag.snd_flag_capture = ((teamnumber) ? "ctf/red_capture.wav" : "ctf/blue_capture.wav"); } // blue team scores by capturing the red flag + if(flag.snd_flag_respawn == "") { flag.snd_flag_respawn = "ctf/flag_respawn.wav"; } // if there is ever a team-based sound for this, update the code to match. + if(flag.snd_flag_dropped == "") { flag.snd_flag_dropped = ((teamnumber) ? "ctf/red_dropped.wav" : "ctf/blue_dropped.wav"); } + if(flag.snd_flag_touch == "") { flag.snd_flag_touch = "ctf/touch.wav"; } // again has no team-based sound + if(flag.snd_flag_pass == "") { flag.snd_flag_pass = "ctf/pass.wav"; } // same story here // precache precache_sound(flag.snd_flag_taken); @@ -1703,7 +1677,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerPreThink) entity flag; // initially clear items so they can be set as necessary later. - self.items &~= (IT_RED_FLAG_CARRYING | IT_RED_FLAG_TAKEN | IT_RED_FLAG_LOST + self.items &= ~(IT_RED_FLAG_CARRYING | IT_RED_FLAG_TAKEN | IT_RED_FLAG_LOST | IT_BLUE_FLAG_CARRYING | IT_BLUE_FLAG_TAKEN | IT_BLUE_FLAG_LOST | IT_CTF_SHIELDED); // scan through all the flags and notify the client about them @@ -1754,7 +1728,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerDamage) // for changing damage and force values t frag_force *= autocvar_g_ctf_flagcarrier_forcefactor; } } - else if(frag_target.flagcarried && (frag_target.deadflag == DEAD_NO) && IsDifferentTeam(frag_target, frag_attacker)) // if the target is a flagcarrier + else if(frag_target.flagcarried && (frag_target.deadflag == DEAD_NO) && DIFF_TEAM(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))) if(time > frag_target.wps_helpme_time + autocvar_g_ctf_flagcarrier_auto_helpme_time) @@ -1762,13 +1736,14 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerDamage) // for changing damage and force values t frag_target.wps_helpme_time = time; WaypointSprite_HelpMePing(frag_target.wps_flagcarrier); } + // todo: add notification for when flag carrier needs help? } return FALSE; } MUTATOR_HOOKFUNCTION(ctf_PlayerDies) { - if((frag_attacker != frag_target) && (frag_attacker.classname == "player") && (frag_target.flagcarried)) + if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)) && (frag_target.flagcarried)) { PlayerTeamScore_AddScore(frag_attacker, autocvar_g_ctf_score_kill); PlayerScore_Add(frag_attacker, SP_CTF_FCKILLS, 1); @@ -1828,8 +1803,8 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey) while(head) // find the closest acceptable target to pass to { - if(head.classname == "player" && head.deadflag == DEAD_NO) - if(head != player && !IsDifferentTeam(head, player)) + if(IS_PLAYER(head) && head.deadflag == DEAD_NO) + if(head != player && SAME_TEAM(head, player)) if(!head.speedrunning && !head.vehicle) { // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc) @@ -1840,15 +1815,15 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey) { if(autocvar_g_ctf_pass_request && !player.flagcarried && head.flagcarried) { - if(clienttype(head) == CLIENTTYPE_BOT) + if(IS_BOT_CLIENT(head)) { - centerprint(player, strcat("Requesting ", head.netname, " to pass you the ", head.flagcarried.netname)); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PASS_REQUESTING, head.netname); ctf_Handle_Throw(head, player, DROP_PASS); } else { - centerprint(head, strcat(player.netname, " requests you to pass the ", head.flagcarried.netname)); - centerprint(player, strcat("Requesting ", head.netname, " to pass you the ", head.flagcarried.netname)); + Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_CTF_PASS_REQUESTED, player.netname); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PASS_REQUESTING, head.netname); } player.throw_antispam = time + autocvar_g_ctf_pass_wait; return TRUE; @@ -1885,7 +1860,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey) } else { - centerprint(player, strcat("Too many flag throws, throwing disabled for ", ftos(rint((player.throw_prevtime + autocvar_g_ctf_throw_punish_delay) - time)), " seconds.")); + Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_FLAG_THROW_PUNISH, rint((player.throw_prevtime + autocvar_g_ctf_throw_punish_delay) - time)); return FALSE; } } @@ -1960,8 +1935,8 @@ MUTATOR_HOOKFUNCTION(ctf_AbortSpeedrun) { if(self.flagcarried) { - bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n"); - ctf_RespawnFlag(self); + Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(self.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN_)); + ctf_RespawnFlag(self.flagcarried); return TRUE; } @@ -2020,7 +1995,7 @@ void spawnfunc_info_player_team1() { if(g_assault) { remove(self); return; } - self.team = COLOR_TEAM1; // red + self.team = NUM_TEAM_1; // red spawnfunc_info_player_deathmatch(); } @@ -2032,7 +2007,7 @@ void spawnfunc_info_player_team2() { if(g_assault) { remove(self); return; } - self.team = COLOR_TEAM2; // blue + self.team = NUM_TEAM_2; // blue spawnfunc_info_player_deathmatch(); } @@ -2043,7 +2018,7 @@ void spawnfunc_info_player_team3() { if(g_assault) { remove(self); return; } - self.team = COLOR_TEAM3; // yellow + self.team = NUM_TEAM_3; // yellow spawnfunc_info_player_deathmatch(); } @@ -2055,7 +2030,7 @@ void spawnfunc_info_player_team4() { if(g_assault) { remove(self); return; } - self.team = COLOR_TEAM4; // purple + self.team = NUM_TEAM_4; // purple spawnfunc_info_player_deathmatch(); } @@ -2157,8 +2132,8 @@ void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to if(find(world, classname, "ctf_team") == world) { print("No ""ctf_team"" entities found on this map, creating them anyway.\n"); - ctf_SpawnTeam("Red", COLOR_TEAM1 - 1); - ctf_SpawnTeam("Blue", COLOR_TEAM2 - 1); + ctf_SpawnTeam("Red", NUM_TEAM_1 - 1); + ctf_SpawnTeam("Blue", NUM_TEAM_2 - 1); } ctf_ScoreRules(); @@ -2200,9 +2175,17 @@ MUTATOR_DEFINITION(gamemode_ctf) ctf_Initialize(); } + MUTATOR_ONROLLBACK_OR_REMOVE + { + // we actually cannot roll back ctf_Initialize here + // BUT: we don't need to! If this gets called, adding always + // succeeds. + } + MUTATOR_ONREMOVE { - error("This is a game type and it cannot be removed at runtime."); + print("This is a game type and it cannot be removed at runtime."); + return -1; } return 0;