]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_ctf.qc
Merge branch 'master' into terencehill/tooltips_cleanup
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_ctf.qc
index 87bbb3b991afe114420f92646dc67e161b3f7dd5..0c68bbfd0ff122aae3bc048ce595556d8dcf7dc6 100644 (file)
@@ -1,14 +1,13 @@
 #include "gamemode_ctf.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
 #ifdef SVQC
 #include "../../common/vehicles/all.qh"
+#include "../teamplay.qh"
 #endif
 
-#include "../../warpzonelib/common.qh"
-#include "../../warpzonelib/mathlib.qh"
+#include "../../lib/warpzone/common.qh"
 
 void ctf_FakeTimeLimit(entity e, float t)
 {
@@ -53,9 +52,9 @@ void ctf_CaptureRecord(entity flag, entity player)
 
 void ctf_FlagcarrierWaypoints(entity player)
 {
-       WaypointSprite_Spawn("flagcarrier", 0, 0, player, FLAG_WAYPOINT_OFFSET, world, player.team, player, wps_flagcarrier, true, RADARICON_FLAG, WPCOLOR_FLAGCARRIER(player.team));
-       WaypointSprite_UpdateMaxHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON) * 2);
-       WaypointSprite_UpdateHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(player.health, player.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON));
+       WaypointSprite_Spawn(WP_FlagCarrier, 0, 0, player, FLAG_WAYPOINT_OFFSET, world, player.team, player, wps_flagcarrier, true, RADARICON_FLAG);
+       WaypointSprite_UpdateMaxHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id) * 2);
+       WaypointSprite_UpdateHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(player.health, player.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id));
        WaypointSprite_UpdateTeamRadar(player.wps_flagcarrier, RADARICON_FLAGCARRIER, WPCOLOR_FLAGCARRIER(player.team));
 }
 
@@ -180,7 +179,7 @@ void ctf_CaptureShield_Update(entity player, bool wanted_status)
 }
 
 bool ctf_CaptureShield_Customize()
-{
+{SELFPARAM();
        if(!other.ctf_captureshielded) { return false; }
        if(CTF_SAMETEAM(self, other)) { return false; }
 
@@ -188,19 +187,19 @@ bool ctf_CaptureShield_Customize()
 }
 
 void ctf_CaptureShield_Touch()
-{
+{SELFPARAM();
        if(!other.ctf_captureshielded) { return; }
        if(CTF_SAMETEAM(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);
+       Damage(other, self, self, 0, DEATH_HURTTRIGGER.m_id, mymid, normalize(othermid - mymid) * ctf_captureshield_force);
        if(IS_REAL_CLIENT(other)) { Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_CTF_CAPTURESHIELD_SHIELDED); }
 }
 
 void ctf_CaptureShield_Spawn(entity flag)
-{
+{SELFPARAM();
        entity shield = spawn();
 
        shield.enemy = self;
@@ -215,7 +214,7 @@ void ctf_CaptureShield_Spawn(entity flag)
        shield.scale = 0.5;
 
        setorigin(shield, self.origin);
-       setmodel(shield, "models/ctf/shield.md3");
+       setmodel(shield, MDL_CTF_SHIELD);
        setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
 }
 
@@ -240,7 +239,7 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype)
 
        // 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);
-       sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE);
+       _sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE);
        ctf_EventLog("dropped", player.team, player);
 
        // scoring
@@ -248,8 +247,10 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype)
        PlayerScore_Add(player, SP_CTF_DROPS, 1);
 
        // waypoints
-       if(autocvar_g_ctf_flag_dropped_waypoint)
-               WaypointSprite_Spawn("flagdropped", 0, 0, flag, FLAG_WAYPOINT_OFFSET, world, ((autocvar_g_ctf_flag_dropped_waypoint == 2) ? 0 : player.team), flag, wps_flagdropped, true, RADARICON_FLAG, WPCOLOR_DROPPEDFLAG(flag.team));
+       if(autocvar_g_ctf_flag_dropped_waypoint) {
+               entity wp = WaypointSprite_Spawn(WP_FlagDropped, 0, 0, flag, FLAG_WAYPOINT_OFFSET, world, ((autocvar_g_ctf_flag_dropped_waypoint == 2) ? 0 : player.team), flag, wps_flagdropped, true, RADARICON_FLAG);
+               wp.colormod = WPCOLOR_DROPPEDFLAG(flag.team);
+       }
 
        if(autocvar_g_ctf_flag_return_time || (autocvar_g_ctf_flag_return_damage && autocvar_g_ctf_flag_health))
        {
@@ -295,7 +296,7 @@ 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, ATTEN_NORM);
+       _sound(player, CH_TRIGGER, flag.snd_flag_pass, VOL_BASE, ATTEN_NORM);
        ctf_EventLog("receive", flag.team, player);
 
        FOR_EACH_REALPLAYER(tmp_player)
@@ -362,8 +363,8 @@ void ctf_Handle_Throw(entity player, entity receiver, int droptype)
                        flag.ctf_status = FLAG_PASSING;
 
                        // other
-                       sound(player, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTEN_NORM);
-                       WarpZone_TrailParticles(world, particleeffectnum(flag.passeffect), player.origin, targ_origin);
+                       _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;
                }
@@ -435,7 +436,7 @@ void ctf_Handle_Capture(entity flag, entity toucher, int capturetype)
        // 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));
        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);
+       _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);
 
        switch(capturetype)
        {
@@ -454,7 +455,7 @@ void ctf_Handle_Capture(entity flag, entity toucher, int capturetype)
                PlayerScore_Add(player, SP_CTF_CAPTIME, new_time - old_time);
 
        // effects
-       Send_Effect(flag.capeffect, flag.origin, '0 0 0', 1);
+       Send_Effect_(flag.capeffect, flag.origin, '0 0 0', 1);
        //shockwave_spawn("models/ctf/shockwavetransring.md3", flag.origin - '0 0 15', -0.8, 0, 1);
 
        // other
@@ -484,7 +485,7 @@ void ctf_Handle_Return(entity flag, entity player)
                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);
        }
-       sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
+       _sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
        ctf_EventLog("return", flag.team, player);
 
        // scoring
@@ -572,7 +573,7 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype)
        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);
 
-       sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE);
+       _sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE);
 
        // scoring
        PlayerScore_Add(player, SP_CTF_PICKUPS, 1);
@@ -590,7 +591,7 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype)
                {
                        pickup_dropped_score = (autocvar_g_ctf_flag_return_time ? bound(0, ((flag.ctf_droptime + autocvar_g_ctf_flag_return_time) - time) / autocvar_g_ctf_flag_return_time, 1) : 1);
                        pickup_dropped_score = floor((autocvar_g_ctf_score_pickup_dropped_late * (1 - pickup_dropped_score) + autocvar_g_ctf_score_pickup_dropped_early * pickup_dropped_score) + 0.5);
-                       dprint("pickup_dropped_score is ", ftos(pickup_dropped_score), "\n");
+                       LOG_TRACE("pickup_dropped_score is ", ftos(pickup_dropped_score), "\n");
                        PlayerTeamScore_AddScore(player, pickup_dropped_score);
                        ctf_EventLog("pickup", flag.team, player);
                        break;
@@ -608,7 +609,7 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype)
        }
 
        // effects
-       Send_Effect(flag.toucheffect, player.origin, '0 0 0', 1);
+       Send_Effect_(flag.toucheffect, player.origin, '0 0 0', 1);
 
        // waypoints
        if(pickuptype == PICKUP_DROPPED) { WaypointSprite_Kill(flag.wps_flagdropped); }
@@ -640,7 +641,7 @@ void ctf_CheckFlagReturn(entity flag, int returntype)
                                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; }
                        }
-                       sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE);
+                       _sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE);
                        ctf_EventLog("returned", flag.team, world);
                        ctf_RespawnFlag(flag);
                }
@@ -648,7 +649,7 @@ void ctf_CheckFlagReturn(entity flag, int returntype)
 }
 
 bool ctf_Stalemate_Customize()
-{
+{SELFPARAM();
        // make spectators see what the player would see
        entity e, wp_owner;
        e = WaypointSprite_getviewentity(other);
@@ -712,7 +713,8 @@ void ctf_CheckStalemate(void)
                {
                        if((tmp_entity.owner) && (!tmp_entity.owner.wps_enemyflagcarrier))
                        {
-                               WaypointSprite_Spawn(((ctf_oneflag) ? "flagcarrier" : "enemyflagcarrier"), 0, 0, tmp_entity.owner, FLAG_WAYPOINT_OFFSET, world, 0, tmp_entity.owner, wps_enemyflagcarrier, true, RADARICON_FLAG, WPCOLOR_ENEMYFC(tmp_entity.owner.team));
+                               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;
                        }
                }
@@ -728,7 +730,7 @@ void ctf_CheckStalemate(void)
 }
 
 void ctf_FlagDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
        {
                if(autocvar_g_ctf_flag_return_damage_delay)
@@ -752,7 +754,7 @@ void ctf_FlagDamage(entity inflictor, entity attacker, float damage, int deathty
 }
 
 void ctf_FlagThink()
-{
+{SELFPARAM();
        // declarations
        entity tmp_entity;
 
@@ -765,7 +767,7 @@ void ctf_FlagThink()
 
        // sanity checks
        if(self.mins != FLAG_MIN || self.maxs != FLAG_MAX) { // reset the flag boundaries in case it got squished
-               dprint("wtf the flag got squashed?\n");
+               LOG_TRACE("wtf the flag got squashed?\n");
                tracebox(self.origin, FLAG_MIN, FLAG_MAX, self.origin, MOVE_NOMONSTERS, self);
                if(!trace_startsolid || self.noalign) // can we resize it without getting stuck?
                        setsize(self, FLAG_MIN, FLAG_MAX); }
@@ -844,11 +846,10 @@ void ctf_FlagThink()
                                self.health = 0;
                                ctf_CheckFlagReturn(self, RETURN_SPEEDRUN);
 
-                               tmp_entity = self;
-                               self = self.owner;
+                               setself(self.owner);
                                self.impulse = CHIMPULSE_SPEEDRUN; // move the player back to the waypoint they set
                                ImpulseCommands();
-                               self = tmp_entity;
+                               setself(this);
                        }
                        if(autocvar_g_ctf_stalemate)
                        {
@@ -894,14 +895,14 @@ void ctf_FlagThink()
 
                default: // this should never happen
                {
-                       dprint("ctf_FlagThink(): Flag exists with no status?\n");
+                       LOG_TRACE("ctf_FlagThink(): Flag exists with no status?\n");
                        return;
                }
        }
 }
 
 void ctf_FlagTouch()
-{
+{SELFPARAM();
        if(gameover) { return; }
        if(trace_dphitcontents & (DPCONTENTS_PLAYERCLIP | DPCONTENTS_MONSTERCLIP)) { return; }
 
@@ -939,8 +940,8 @@ void ctf_FlagTouch()
        {
                if(time > self.wait) // if we haven't in a while, play a sound/effect
                {
-                       Send_Effect(self.toucheffect, self.origin, '0 0 0', 1);
-                       sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM);
+                       Send_Effect_(self.toucheffect, self.origin, '0 0 0', 1);
+                       _sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM);
                        self.wait = time + FLAG_TOUCHRATE;
                }
                return;
@@ -976,7 +977,7 @@ void ctf_FlagTouch()
 
                case FLAG_CARRY:
                {
-                       dprint("Someone touched a flag even though it was being carried?\n");
+                       LOG_TRACE("Someone touched a flag even though it was being carried?\n");
                        break;
                }
 
@@ -1047,7 +1048,7 @@ void ctf_RespawnFlag(entity flag)
 }
 
 void ctf_Reset()
-{
+{SELFPARAM();
        if(self.owner)
                if(IS_PLAYER(self.owner))
                        ctf_Handle_Throw(self.owner, world, DROP_RESET);
@@ -1056,25 +1057,25 @@ void ctf_Reset()
 }
 
 void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf_FlagSetup()
-{
+{SELFPARAM();
        // bot waypoints
        waypoint_spawnforitem_force(self, self.origin);
        self.nearestwaypointtimeout = 0; // activate waypointing again
        self.bot_basewaypoint = self.nearestwaypoint;
 
        // waypointsprites
-       string basename = "base";
-
-       switch(self.team)
+       entity basename;
+       switch (self.team)
        {
-               case NUM_TEAM_1: basename = "redbase"; break;
-               case NUM_TEAM_2: basename = "bluebase"; break;
-               case NUM_TEAM_3: basename = "yellowbase"; break;
-               case NUM_TEAM_4: basename = "pinkbase"; break;
-               default: basename = "neutralbase"; break;
+               case NUM_TEAM_1: basename = WP_FlagBaseRed; break;
+               case NUM_TEAM_2: basename = WP_FlagBaseBlue; break;
+               case NUM_TEAM_3: basename = WP_FlagBaseYellow; break;
+               case NUM_TEAM_4: basename = WP_FlagBasePink; break;
+               default: basename = WP_FlagBaseNeutral; break;
        }
 
-       WaypointSprite_SpawnFixed(basename, self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, ((self.team) ? Team_ColorRGB(self.team) : '1 1 1'));
+       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'));
 
        // captureshield setup
@@ -1083,15 +1084,14 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf
 
 void set_flag_string(entity flag, .string field, string value, string teamname)
 {
-       if(flag.field == "")
-               flag.field = strzone(sprintf(value,teamname));
+       if(flag.(field) == "")
+               flag.(field) = strzone(sprintf(value,teamname));
 }
 
 void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag entity on the map as a spawnfunc
-{
+{SELFPARAM();
        // declarations
-       string teamname = Static_Team_ColorName_Lower(teamnumber);
-       self = flag; // for later usage with droptofloor()
+       setself(flag); // for later usage with droptofloor()
 
        // main setup
        flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist
@@ -1123,6 +1123,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        flag.nextthink = time + FLAG_THINKRATE;
        flag.ctf_status = FLAG_BASE;
 
+       string teamname = Static_Team_ColorName_Lower(teamnumber);
        // appearence
        if(!flag.scale)                         { flag.scale = FLAG_SCALE; }
        if(flag.skin == 0)                      { flag.skin = cvar(sprintf("g_ctf_flag_%s_skin", teamname)); }
@@ -1132,28 +1133,22 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        set_flag_string(flag, capeffect,        "%s_cap",               teamname);
 
        // sounds
-       set_flag_string(flag, snd_flag_taken,           "ctf/%s_taken.wav",     teamname);
-       set_flag_string(flag, snd_flag_returned,        "ctf/%s_returned.wav",  teamname);
-       set_flag_string(flag, snd_flag_capture,         "ctf/%s_capture.wav",   teamname);
-       set_flag_string(flag, snd_flag_dropped,         "ctf/%s_dropped.wav",   teamname);
-       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_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);
-       precache_sound(flag.snd_flag_returned);
-       precache_sound(flag.snd_flag_capture);
+       flag.snd_flag_taken = SND(CTF_TAKEN(teamnumber));
+       flag.snd_flag_returned = SND(CTF_RETURNED(teamnumber));
+       flag.snd_flag_capture = SND(CTF_CAPTURE(teamnumber));
+       flag.snd_flag_dropped = SND(CTF_DROPPED(teamnumber));
+       if (flag.snd_flag_respawn == "") flag.snd_flag_respawn = SND(CTF_RESPAWN); // if there is ever a team-based sound for this, update the code to match.
        precache_sound(flag.snd_flag_respawn);
-       precache_sound(flag.snd_flag_dropped);
+       if (flag.snd_flag_touch == "") flag.snd_flag_touch = SND(CTF_TOUCH); // again has no team-based sound
        precache_sound(flag.snd_flag_touch);
+       if (flag.snd_flag_pass == "") flag.snd_flag_pass = SND(CTF_PASS); // same story here
        precache_sound(flag.snd_flag_pass);
+
+       // precache
        precache_model(flag.model);
-       precache_model("models/ctf/shield.md3");
-       precache_model("models/ctf/shockwavetransring.md3");
 
        // appearence
-       setmodel(flag, flag.model); // precision set below
+       _setmodel(flag, flag.model); // precision set below
        setsize(flag, FLAG_MIN, FLAG_MAX);
        setorigin(flag, (flag.origin + FLAG_SPAWN_OFFSET));
 
@@ -1195,7 +1190,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;
-               self = flag;
+               setself(flag);
                droptofloor();
                flag.movetype = MOVETYPE_TOSS;
        }
@@ -1291,7 +1286,7 @@ int havocbot_ctf_teamcount(entity bot, vector org, float tc_radius)
 }
 
 void havocbot_goalrating_ctf_ourflag(float ratingscale)
-{
+{SELFPARAM();
        entity head;
        head = ctf_worldflaglist;
        while (head)
@@ -1305,7 +1300,7 @@ void havocbot_goalrating_ctf_ourflag(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_ourbase(float ratingscale)
-{
+{SELFPARAM();
        entity head;
        head = ctf_worldflaglist;
        while (head)
@@ -1321,7 +1316,7 @@ void havocbot_goalrating_ctf_ourbase(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_enemyflag(float ratingscale)
-{
+{SELFPARAM();
        entity head;
        head = ctf_worldflaglist;
        while (head)
@@ -1348,7 +1343,7 @@ void havocbot_goalrating_ctf_enemyflag(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_enemybase(float ratingscale)
-{
+{SELFPARAM();
        if (!bot_waypoints_for_items)
        {
                havocbot_goalrating_ctf_enemyflag(ratingscale);
@@ -1366,7 +1361,7 @@ void havocbot_goalrating_ctf_enemybase(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_ourstolenflag(float ratingscale)
-{
+{SELFPARAM();
        entity mf;
 
        mf = havocbot_ctf_find_flag(self);
@@ -1402,7 +1397,7 @@ void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float d
 }
 
 void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
        entity head;
        float t;
        head = findchainfloat(bot_pickup, true);
@@ -1489,7 +1484,7 @@ void havocbot_ctf_reset_role(entity bot)
 }
 
 void havocbot_role_ctf_carrier()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
        {
                havocbot_ctf_reset_role(self);
@@ -1523,14 +1518,14 @@ void havocbot_role_ctf_carrier()
                {
                        // Can't navigate to my own base, suicide!
                        // TODO: drop it and wander around
-                       Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
+                       Damage(self, self, self, 100000, DEATH_KILL.m_id, self.origin, '0 0 0');
                        return;
                }
        }
 }
 
 void havocbot_role_ctf_escort()
-{
+{SELFPARAM();
        entity mf, ef;
 
        if(self.deadflag != DEAD_NO)
@@ -1590,7 +1585,7 @@ void havocbot_role_ctf_escort()
 }
 
 void havocbot_role_ctf_offense()
-{
+{SELFPARAM();
        entity mf, ef;
        vector pos;
 
@@ -1672,7 +1667,7 @@ void havocbot_role_ctf_offense()
 
 // Retriever (temporary role):
 void havocbot_role_ctf_retriever()
-{
+{SELFPARAM();
        entity mf;
 
        if(self.deadflag != DEAD_NO)
@@ -1720,7 +1715,7 @@ void havocbot_role_ctf_retriever()
 }
 
 void havocbot_role_ctf_middle()
-{
+{SELFPARAM();
        entity mf;
 
        if(self.deadflag != DEAD_NO)
@@ -1771,7 +1766,7 @@ void havocbot_role_ctf_middle()
 }
 
 void havocbot_role_ctf_defense()
-{
+{SELFPARAM();
        entity mf;
 
        if(self.deadflag != DEAD_NO)
@@ -1846,47 +1841,47 @@ void havocbot_role_ctf_defense()
 
 void havocbot_role_ctf_setrole(entity bot, int role)
 {
-       dprint(strcat(bot.netname," switched to "));
+       LOG_TRACE(strcat(bot.netname," switched to "));
        switch(role)
        {
                case HAVOCBOT_CTF_ROLE_CARRIER:
-                       dprint("carrier");
+                       LOG_TRACE("carrier");
                        bot.havocbot_role = havocbot_role_ctf_carrier;
                        bot.havocbot_role_timeout = 0;
                        bot.havocbot_cantfindflag = time + 10;
                        bot.bot_strategytime = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_DEFENSE:
-                       dprint("defense");
+                       LOG_TRACE("defense");
                        bot.havocbot_role = havocbot_role_ctf_defense;
                        bot.havocbot_role_timeout = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_MIDDLE:
-                       dprint("middle");
+                       LOG_TRACE("middle");
                        bot.havocbot_role = havocbot_role_ctf_middle;
                        bot.havocbot_role_timeout = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_OFFENSE:
-                       dprint("offense");
+                       LOG_TRACE("offense");
                        bot.havocbot_role = havocbot_role_ctf_offense;
                        bot.havocbot_role_timeout = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_RETRIEVER:
-                       dprint("retriever");
+                       LOG_TRACE("retriever");
                        bot.havocbot_previous_role = bot.havocbot_role;
                        bot.havocbot_role = havocbot_role_ctf_retriever;
                        bot.havocbot_role_timeout = time + 10;
                        bot.bot_strategytime = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_ESCORT:
-                       dprint("escort");
+                       LOG_TRACE("escort");
                        bot.havocbot_previous_role = bot.havocbot_role;
                        bot.havocbot_role = havocbot_role_ctf_escort;
                        bot.havocbot_role_timeout = time + 30;
                        bot.bot_strategytime = 0;
                        break;
        }
-       dprint("\n");
+       LOG_TRACE("\n");
 }
 
 
@@ -1895,7 +1890,7 @@ void havocbot_role_ctf_setrole(entity bot, int role)
 // ==============
 
 MUTATOR_HOOKFUNCTION(ctf_PlayerPreThink)
-{
+{SELFPARAM();
        entity flag;
        int t = 0, t2 = 0, t3 = 0;
 
@@ -1941,7 +1936,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerPreThink)
 
        // 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));
+               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;
 }
@@ -1963,7 +1958,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerDamage) // for changing damage and force values t
        }
        else if(frag_target.flagcarried && (frag_target.deadflag == DEAD_NO) && 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)))
+               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)
                {
                        frag_target.wps_helpme_time = time;
@@ -1999,7 +1994,7 @@ MUTATOR_HOOKFUNCTION(ctf_GiveFragsForKill)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_RemovePlayer)
-{
+{SELFPARAM();
        entity flag; // temporary entity for the search method
 
        if(self.flagcarried)
@@ -2016,7 +2011,7 @@ MUTATOR_HOOKFUNCTION(ctf_RemovePlayer)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_PortalTeleport)
-{
+{SELFPARAM();
        if(self.flagcarried)
        if(!autocvar_g_ctf_portalteleport)
                { ctf_Handle_Throw(self, world, DROP_NORMAL); }
@@ -2025,7 +2020,7 @@ MUTATOR_HOOKFUNCTION(ctf_PortalTeleport)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE || gameover) { return false; }
 
        entity player = self;
@@ -2118,7 +2113,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_HelpMePing)
-{
+{SELFPARAM();
        if(self.wps_flagcarrier) // update the flagcarrier waypointsprite with "NEEDING HELP" notification
        {
                self.wps_helpme_time = time;
@@ -2126,7 +2121,7 @@ MUTATOR_HOOKFUNCTION(ctf_HelpMePing)
        }
        else // create a normal help me waypointsprite
        {
-               WaypointSprite_Spawn("helpme", waypointsprite_deployed_lifetime, waypointsprite_limitedrange, self, FLAG_WAYPOINT_OFFSET, world, self.team, self, wps_helpme, false, RADARICON_HELPME, '1 0.5 0');
+               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);
        }
 
@@ -2172,7 +2167,7 @@ MUTATOR_HOOKFUNCTION(ctf_VehicleExit)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_AbortSpeedrun)
-{
+{SELFPARAM();
        if(self.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));
@@ -2218,7 +2213,7 @@ MUTATOR_HOOKFUNCTION(ctf_MatchEnd)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_BotRoles)
-{
+{SELFPARAM();
        havocbot_ctf_reset_role(self);
        return true;
 }
@@ -2231,7 +2226,7 @@ MUTATOR_HOOKFUNCTION(ctf_GetTeamCount)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_SpectateCopy)
-{
+{SELFPARAM();
        self.ctf_flagstatus = other.ctf_flagstatus;
        return false;
 }
@@ -2241,52 +2236,6 @@ MUTATOR_HOOKFUNCTION(ctf_SpectateCopy)
 // Spawnfuncs
 // ==========
 
-/*QUAKED spawnfunc_info_player_team1 (1 0 0) (-16 -16 -24) (16 16 24)
-CTF Starting point for a player in team one (Red).
-Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team1()
-{
-       if(g_assault) { remove(self); return; }
-
-       self.team = NUM_TEAM_1; // red
-       spawnfunc_info_player_deathmatch();
-}
-
-
-/*QUAKED spawnfunc_info_player_team2 (1 0 0) (-16 -16 -24) (16 16 24)
-CTF Starting point for a player in team two (Blue).
-Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team2()
-{
-       if(g_assault) { remove(self); return; }
-
-       self.team = NUM_TEAM_2; // blue
-       spawnfunc_info_player_deathmatch();
-}
-
-/*QUAKED spawnfunc_info_player_team3 (1 0 0) (-16 -16 -24) (16 16 24)
-CTF Starting point for a player in team three (Yellow).
-Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team3()
-{
-       if(g_assault) { remove(self); return; }
-
-       self.team = NUM_TEAM_3; // yellow
-       spawnfunc_info_player_deathmatch();
-}
-
-
-/*QUAKED spawnfunc_info_player_team4 (1 0 0) (-16 -16 -24) (16 16 24)
-CTF Starting point for a player in team four (Purple).
-Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team4()
-{
-       if(g_assault) { remove(self); return; }
-
-       self.team = NUM_TEAM_4; // purple
-       spawnfunc_info_player_deathmatch();
-}
-
 /*QUAKED spawnfunc_item_flag_team1 (0 0.5 0.8) (-48 -48 -37) (48 48 37)
 CTF flag for team one (Red).
 Keys:
@@ -2298,7 +2247,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team1()
+spawnfunc(item_flag_team1)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2316,7 +2265,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team2()
+spawnfunc(item_flag_team2)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2334,7 +2283,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team3()
+spawnfunc(item_flag_team3)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2352,7 +2301,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team4()
+spawnfunc(item_flag_team4)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2370,7 +2319,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_neutral()
+spawnfunc(item_flag_neutral)
 {
        if(!g_ctf) { remove(self); return; }
        if(!cvar("g_ctf_oneflag")) { remove(self); return; }
@@ -2384,7 +2333,7 @@ Note: If you use spawnfunc_ctf_team entities you must define at least 2!  Howeve
 Keys:
 "netname" Name of the team (for example Red, Blue, Green, Yellow, Life, Death, Offense, Defense, etc)...
 "cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
-void spawnfunc_ctf_team()
+spawnfunc(ctf_team)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2393,15 +2342,17 @@ void spawnfunc_ctf_team()
 }
 
 // compatibility for quake maps
-void spawnfunc_team_CTF_redflag()    { spawnfunc_item_flag_team1();    }
-void spawnfunc_team_CTF_blueflag()   { spawnfunc_item_flag_team2();    }
-void spawnfunc_team_CTF_redplayer()  { spawnfunc_info_player_team1();  }
-void spawnfunc_team_CTF_blueplayer() { spawnfunc_info_player_team2();  }
-void spawnfunc_team_CTF_redspawn()   { spawnfunc_info_player_team1();  }
-void spawnfunc_team_CTF_bluespawn()  { spawnfunc_info_player_team2();  }
+spawnfunc(team_CTF_redflag)    { spawnfunc_item_flag_team1(this);    }
+spawnfunc(team_CTF_blueflag)   { spawnfunc_item_flag_team2(this);    }
+spawnfunc(info_player_team1);
+spawnfunc(team_CTF_redplayer)  { spawnfunc_info_player_team1(this);  }
+spawnfunc(team_CTF_redspawn)   { spawnfunc_info_player_team1(this);  }
+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()                     { spawnfunc_item_flag_neutral();  }
-void team_neutralobelisk()                      { spawnfunc_item_flag_neutral();  }
+void team_CTF_neutralflag()                     { SELFPARAM(); spawnfunc_item_flag_neutral(self);  }
+void team_neutralobelisk()                      { SELFPARAM(); spawnfunc_item_flag_neutral(self);  }
 
 
 // ==============
@@ -2426,16 +2377,11 @@ 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 oldself;
-       oldself = self;
-       self = spawn();
-       self.classname = "ctf_team";
-       self.netname = teamname;
-       self.cnt = teamcolor;
-
-       spawnfunc_ctf_team();
-
-       self = oldself;
+       entity this = new(ctf_team);
+       this.netname = teamname;
+       this.cnt = teamcolor;
+       this.spawnfunc_checked = true;
+       WITH(entity, self, this, spawnfunc_ctf_team(this));
 }
 
 void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to be set up.
@@ -2455,7 +2401,7 @@ void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to
        // if no teams are found, spawn defaults
        if(find(world, classname, "ctf_team") == world)
        {
-               print("No ""ctf_team"" entities found on this map, creating them anyway.\n");
+               LOG_INFO("No ""ctf_team"" entities found on this map, creating them anyway.\n");
                ctf_SpawnTeam("Red", NUM_TEAM_1 - 1);
                ctf_SpawnTeam("Blue", NUM_TEAM_2 - 1);
                if(ctf_teams >= 3)
@@ -2516,7 +2462,7 @@ MUTATOR_DEFINITION(gamemode_ctf)
 
        MUTATOR_ONREMOVE
        {
-               print("This is a game type and it cannot be removed at runtime.");
+               LOG_INFO("This is a game type and it cannot be removed at runtime.");
                return -1;
        }