]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_keyhunt.qc
Revert "Merge branch 'TimePath/bot_api' into 'master'\r"
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_keyhunt.qc
index 2a67316101f846261dc819f6476bf7ef23f539e7..be45c3db0c3785f51f9d5f62744961b7c09ec117 100644 (file)
@@ -1,4 +1,8 @@
-#define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
+#include "gamemode_keyhunt.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
 
 // #define KH_PLAYER_USE_ATTACHMENT
 // #define KH_PLAYER_USE_CARRIEDMODEL
@@ -59,12 +63,6 @@ float kh_interferemsg_time, kh_interferemsg_team;
 .float kh_previous_owner_playerid;
 .float kh_cp_duration;
 
-string kh_sound_capture = "kh/capture.wav";
-string kh_sound_destroy = "kh/destroy.wav";
-string kh_sound_drop = "kh/drop.wav";
-string kh_sound_collect = "kh/collect.wav";
-string kh_sound_alarm = "kh/alarm.wav";  // the new siren/alarm
-
 float kh_key_dropped, kh_key_carried;
 
 const float ST_KH_CAPS = 1;
@@ -88,7 +86,7 @@ void kh_ScoreRules(float teams)
 }
 
 float kh_KeyCarrier_waypointsprite_visible_for_player(entity e)  // runs all the time
-{
+{SELFPARAM();
        if(!IS_PLAYER(e) || self.team != e.team)
                if(!kh_tracking_enabled)
                        return false;
@@ -97,7 +95,7 @@ float kh_KeyCarrier_waypointsprite_visible_for_player(entity e)  // runs all the
 }
 
 float kh_Key_waypointsprite_visible_for_player(entity e) // ??
-{
+{SELFPARAM();
        if(!kh_tracking_enabled)
                return false;
        if(!self.owner)
@@ -150,7 +148,7 @@ void kh_Controller_SetThink(float t, kh_Think_t func)  // runs occasionaly
 }
 void kh_WaitForPlayers();
 void kh_Controller_Think()  // called a lot
-{
+{SELFPARAM();
        if(intermission_running)
                return;
        if(self.cnt > 0)
@@ -271,7 +269,7 @@ void kh_Key_Detach(entity key) // runs every time a key is dropped or lost. Runs
        }
        // in any case:
        setattachment(key, world, "");
-       setorigin(key, key.owner.origin + '0 0 1' * (PL_MIN_z - KH_KEY_MIN_z));
+       setorigin(key, key.owner.origin + '0 0 1' * (PL_MIN.z - KH_KEY_MIN_z));
        key.angles = key.owner.angles;
 #else
        setorigin(key, key.owner.origin + key.origin.z * '0 0 1');
@@ -347,17 +345,18 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                if(key.kh_next == world)
                {
                        // player is now a key carrier
-                       WaypointSprite_AttachCarrier("", player, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0));
+                       entity wp = WaypointSprite_AttachCarrier(WP_Null, player, RADARICON_FLAGCARRIER);
+                       wp.colormod = colormapPaletteColor(player.team - 1, 0);
                        player.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_KeyCarrier_waypointsprite_visible_for_player;
                        WaypointSprite_UpdateRule(player.waypointsprite_attachedforcarrier, player.team, SPRITERULE_TEAMPLAY);
                        if(player.team == NUM_TEAM_1)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "keycarrier-red");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierRed, WP_KeyCarrierFriend, WP_KeyCarrierRed);
                        else if(player.team == NUM_TEAM_2)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "keycarrier-blue");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierBlue, WP_KeyCarrierFriend, WP_KeyCarrierBlue);
                        else if(player.team == NUM_TEAM_3)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierYellow, WP_KeyCarrierFriend, WP_KeyCarrierYellow);
                        else if(player.team == NUM_TEAM_4)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierPink, WP_KeyCarrierFriend, WP_KeyCarrierPink);
                        if(!kh_no_radar_circles)
                                WaypointSprite_Ping(player.waypointsprite_attachedforcarrier);
                }
@@ -379,8 +378,12 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        // audit all key carrier sprites, update them to RUN HERE
                        FOR_EACH_KH_KEY(k)
                        {
-                               if(k.owner)
-                                       WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-finish", k.owner.waypointsprite_attachedforcarrier.model3);
+                               if (!k.owner) continue;
+                               entity first = WP_Null;
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+                               entity third = WP_Null;
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+                               WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFinish, third);
                        }
                }
                else
@@ -390,15 +393,19 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        // audit all key carrier sprites, update them to RUN HERE
                        FOR_EACH_KH_KEY(k)
                        {
-                               if(k.owner)
-                                       WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-friend", k.owner.waypointsprite_attachedforcarrier.model3);
+                               if (!k.owner) continue;
+                               entity first = WP_Null;
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+                               entity third = WP_Null;
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+                               WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFriend, third);
                        }
                }
        }
 }
 
-void kh_Key_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
+void kh_Key_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{SELFPARAM();
        if(self.owner)
                return;
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
@@ -417,7 +424,7 @@ void kh_Key_Damage(entity inflictor, entity attacker, float damage, float deatht
 
 void kh_Key_Collect(entity key, entity player)  //a player picks up a dropped key
 {
-       sound(player, CH_TRIGGER, kh_sound_collect, VOL_BASE, ATTEN_NORM);
+       sound(player, CH_TRIGGER, SND_KH_COLLECT, VOL_BASE, ATTEN_NORM);
 
        if(key.kh_dropperteam != player.team)
        {
@@ -431,7 +438,7 @@ void kh_Key_Collect(entity key, entity player)  //a player picks up a dropped ke
 }
 
 void kh_Key_Touch()  // runs many, many times when a key has been dropped and can be picked up
-{
+{SELFPARAM();
        if(intermission_running)
                return;
 
@@ -562,7 +569,7 @@ void kh_WinnerTeam(float teem)  // runs when a team wins // Samual: Teem?.... TE
        midpoint = midpoint * (1 / kh_teams);
        te_customflash(midpoint, 1000, 1, Team_ColorRGB(teem) * 0.5 + '0.5 0.5 0.5');  // make the color >=0.5 in each component
 
-       play2all(kh_sound_capture);
+       play2all(SND(KH_CAPTURE));
        kh_FinishRound();
 }
 
@@ -651,14 +658,14 @@ void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a fl
 
        Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(lostkey, INFO_KEYHUNT_LOST_), lostkey.kh_previous_owner.netname);
 
-       play2all(kh_sound_destroy);
+       play2all(SND(KH_DESTROY));
        te_tarexplosion(lostkey.origin);
 
        kh_FinishRound();
 }
 
 void kh_Key_Think()  // runs all the time
-{
+{SELFPARAM();
        entity head;
        //entity player;  // needed by FOR_EACH_PLAYER
 
@@ -683,7 +690,7 @@ void kh_Key_Think()  // runs all the time
        {
                if(self.siren_time < time)
                {
-                       sound(self.owner, CH_TRIGGER, kh_sound_alarm, VOL_BASE, ATTEN_NORM);  // play a simple alarm
+                       sound(self.owner, CH_TRIGGER, SND_KH_ALARM, VOL_BASE, ATTEN_NORM);  // play a simple alarm
                        self.siren_time = time + 2.5;  // repeat every 2.5 seconds
                }
 
@@ -716,7 +723,7 @@ void kh_Key_Think()  // runs all the time
 }
 
 void key_reset()
-{
+{SELFPARAM();
        kh_Key_AssignTo(self, world);
        kh_Key_Remove(self);
 }
@@ -769,7 +776,7 @@ void kh_Key_Spawn(entity initial_owner, float angle, float i)  // runs every tim
 
        Send_Notification(NOTIF_ONE, initial_owner, MSG_CENTER, APP_TEAM_NUM_4(initial_owner.team, CENTER_KEYHUNT_START_));
 
-       WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, false, RADARICON_FLAG, '0 1 1');
+       WaypointSprite_Spawn(WP_KeyDropped, 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, false, RADARICON_FLAG);
        key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player;
 
        kh_Key_AssignTo(key, initial_owner);
@@ -819,7 +826,7 @@ void kh_Key_DropOne(entity key)
        key.pushltime = time + autocvar_g_balance_keyhunt_protecttime;
        key.kh_dropperteam = key.team;
 
-       sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTEN_NORM);
+       sound(player, CH_TRIGGER, SND_KH_DROP, VOL_BASE, ATTEN_NORM);
 }
 
 void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
@@ -845,7 +852,7 @@ void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
                        if(suicide)
                                key.kh_dropperteam = player.team;
                }
-               sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTEN_NORM);
+               sound(player, CH_TRIGGER, SND_KH_DROP, VOL_BASE, ATTEN_NORM);
        }
 }
 
@@ -867,6 +874,8 @@ float kh_CheckPlayers(float num)
        return 0;
 }
 
+#define KH_READY_TEAMS() (!p1 + !p2 + ((kh_teams >= 3) ? !p3 : p3) + ((kh_teams >= 4) ? !p4 : p4))
+#define KH_READY_TEAMS_OK() (KH_READY_TEAMS() == kh_teams)
 void kh_WaitForPlayers()  // delay start of the round until enough players are present
 {
        if(time < game_starttime)
@@ -875,15 +884,35 @@ void kh_WaitForPlayers()  // delay start of the round until enough players are p
                return;
        }
 
+       static float prev_missing_teams_mask;
        float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
-       if (!(p1 || p2 || p3 || p4))
+       if(KH_READY_TEAMS_OK())
        {
+               if(prev_missing_teams_mask > 0)
+                       Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_MISSING_TEAMS);
+               prev_missing_teams_mask = -1;
                Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEYHUNT_ROUNDSTART, autocvar_g_balance_keyhunt_delay_round);
                kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, kh_StartRound);
        }
        else
        {
-               Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEYHUNT_WAIT, p1, p2, p3, p4);
+               if(player_count == 0)
+               {
+                       if(prev_missing_teams_mask > 0)
+                               Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_MISSING_TEAMS);
+                       prev_missing_teams_mask = -1;
+               }
+               else
+               {
+                       float missing_teams_mask = (!!p1) + (!!p2) * 2;
+                       if(kh_teams >= 3) missing_teams_mask += (!!p3) * 4;
+                       if(kh_teams >= 4) missing_teams_mask += (!!p4) * 8;
+                       if(prev_missing_teams_mask != missing_teams_mask)
+                       {
+                               Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask);
+                               prev_missing_teams_mask = missing_teams_mask;
+                       }
+               }
                kh_Controller_SetThink(1, kh_WaitForPlayers);
        }
 }
@@ -908,10 +937,9 @@ void kh_StartRound()  // runs at the start of each round
        }
 
        float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
-       if(p1 || p2 || p3 || p4)
+       if(!KH_READY_TEAMS_OK())
        {
                kh_Controller_SetThink(1, kh_WaitForPlayers);
-               Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEYHUNT_WAIT, p1, p2, p3, p4);
                return;
        }
 
@@ -969,17 +997,6 @@ float kh_HandleFrags(entity attacker, entity targ, float f)  // adds to the play
 
 void kh_Initialize()  // sets up th KH environment
 {
-       precache_sound(kh_sound_capture);
-       precache_sound(kh_sound_destroy);
-       precache_sound(kh_sound_drop);
-       precache_sound(kh_sound_collect);
-       precache_sound(kh_sound_alarm);  // the new siren
-
-#ifdef KH_PLAYER_USE_CARRIEDMODEL
-       precache_model("models/keyhunt/key-carried.md3");
-#endif
-       precache_model("models/keyhunt/key.md3");
-
        // setup variables
        kh_teams = autocvar_g_keyhunt_teams_override;
        if(kh_teams < 2)
@@ -991,7 +1008,7 @@ void kh_Initialize()  // sets up th KH environment
        kh_controller.think = kh_Controller_Think;
        kh_Controller_SetThink(0, kh_WaitForPlayers);
 
-       setmodel(kh_controller, "models/keyhunt/key.md3");
+       setmodel(kh_controller, MDL_KH_KEY);
        kh_key_dropped = kh_controller.modelindex;
        /*
        dprint(vtos(kh_controller.mins));
@@ -999,7 +1016,7 @@ void kh_Initialize()  // sets up th KH environment
        dprint("\n");
        */
 #ifdef KH_PLAYER_USE_CARRIEDMODEL
-       setmodel(kh_controller, "models/keyhunt/key-carried.md3");
+       setmodel(kh_controller, MDL_KH_KEY_CARRIED);
        kh_key_carried = kh_controller.modelindex;
 #else
        kh_key_carried = kh_key_dropped;
@@ -1024,13 +1041,13 @@ void kh_finalize()
 // register this as a mutator
 
 MUTATOR_HOOKFUNCTION(kh_Key_DropAll)
-{
+{SELFPARAM();
        kh_Key_DropAll(self, true);
        return 0;
 }
 
 MUTATOR_HOOKFUNCTION(kh_PlayerDies)
-{
+{SELFPARAM();
        if(self == other)
                kh_Key_DropAll(self, true);
        else if(IS_PLAYER(other))
@@ -1059,13 +1076,13 @@ MUTATOR_HOOKFUNCTION(kh_GetTeamCount)
 }
 
 MUTATOR_HOOKFUNCTION(kh_SpectateCopy)
-{
+{SELFPARAM();
        self.kh_state = other.kh_state;
        return 0;
 }
 
 MUTATOR_HOOKFUNCTION(kh_PlayerUseKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE == 0)
        {
                entity k;
@@ -1106,7 +1123,7 @@ MUTATOR_DEFINITION(gamemode_keyhunt)
 
        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;
        }