]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
various small bug fixes and improvements for battle royale
authorJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Mon, 31 Jan 2022 06:30:34 +0000 (07:30 +0100)
committerJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Mon, 31 Jan 2022 06:30:34 +0000 (07:30 +0100)
qcsrc/common/gamemodes/gamemode/br/cl_br.qc
qcsrc/common/gamemodes/gamemode/br/sv_br.qc
qcsrc/common/gamemodes/gamemode/br/sv_br.qh
qcsrc/common/gamemodes/gamemode/br/sv_squad.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/server/client.qc
qcsrc/server/impulse.qc

index 2310cdfd484a13c0abaaa75bbe31dfb86cf2c38b..d873de9ae6634a83737c6120d77a19b4891d8b7f 100644 (file)
@@ -4,8 +4,6 @@
 
 REGISTER_MUTATOR(cl_br, true);
 
-// FIXME: some of these hooks don't work when spectating
-
 MUTATOR_HOOKFUNCTION(cl_br, WantEventchase)
 {
     return (STAT(DROP) == DROP_FALLING);
index 0baad0f1bf4fdd756a7b12896e15c7d57ea8c4b9..d02c40f277cbb5f0fa5d2ab130965760506dbe60 100644 (file)
@@ -8,7 +8,8 @@
 
 #define BR_KILLS_INSTANTLY(pl, dt) \
     (!IN_SQUAD((pl)) || (br_SquadFindLastAlive((pl).br_squad, true) == (pl)) || ((dt) == DEATH_HURTTRIGGER.m_id) \
-    || ((dt) == DEATH_KILL.m_id) || ((dt) == DEATH_TEAMCHANGE.m_id) || ((dt) == DEATH_AUTOTEAMCHANGE.m_id))
+    || ((dt) == DEATH_KILL.m_id) || ((dt) == DEATH_TEAMCHANGE.m_id) || ((dt) == DEATH_AUTOTEAMCHANGE.m_id) \
+    || DEATH_ISWEAPON(dt, WEP_VAPORIZER))
 
 float br_CalculatePlayerDropAngle(entity this);
 void br_LastPlayerForSquad_Notify(entity squad);
@@ -18,7 +19,6 @@ void br_Start();
 bool br_CheckPlayers();
 int br_WinningCondition();
 
-entity ring;
 entity dropship;
 
 bool squads_colored = false;
@@ -32,6 +32,7 @@ bool br_started = false;
 .int br_drop_launch;
 .int br_drop_detached;
 .bool br_drop_instructions;
+.float br_ring_damage_time;
 
 .entity br_bleeding_inflictor;
 .entity br_bleeding_attacker;
@@ -54,7 +55,6 @@ bool autocvar_g_br_squad_colors = true;
 float autocvar_g_br_drop_accel_dive = 50;
 float autocvar_g_br_drop_accel_turn = 600;
 bool autocvar_g_br_startweapons = false;
-bool autocvar_g_br_ring_exitvehicle = false;
 float autocvar_g_br_squad_waypoint_distance = 1500;
 
 MUTATOR_HOOKFUNCTION(br, reset_map_global)
@@ -62,7 +62,8 @@ MUTATOR_HOOKFUNCTION(br, reset_map_global)
     dropship_path_length = 0; // this should kill the dropship
     dropship_path_direction = '0 0 0';
 
-    delete(ring);
+    if(ring)
+        delete(ring);
     ring = dropship = NULL;
 }
 
@@ -73,9 +74,12 @@ MUTATOR_HOOKFUNCTION(br, reset_map_players)
         GameRules_scoring_add(it, BR_SQUAD, -GameRules_scoring_add(it, BR_SQUAD, 0));
         GameRules_scoring_add(it, BR_REVIVALS, -GameRules_scoring_add(it, BR_REVIVALS, 0));
 
+        STAT(DROP, it) = DROP_LANDED;
+        STAT(BLEEDING, it) = false;
+
         br_RemovePlayer(it);
 
-        it.br_wepset_old = '0 0 0';
+        it.br_wepset_old = start_weapons;
         for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
         {
             it.br_weapon_prev[slot] = WEP_Null;
@@ -84,6 +88,7 @@ MUTATOR_HOOKFUNCTION(br, reset_map_players)
     });
 
     br_SquadUpdateInfo();
+    return true;
 }
 
 MUTATOR_HOOKFUNCTION(br, CheckRules_World)
@@ -95,6 +100,12 @@ MUTATOR_HOOKFUNCTION(br, CheckRules_World)
     return true;
 }
 
+MUTATOR_HOOKFUNCTION(br, GiveFragsForKill, CBC_ORDER_FIRST)
+{
+    M_ARGV(2, float) = 0; // no frags counted in Battle Royale
+    return true;
+}
+
 MUTATOR_HOOKFUNCTION(br, ForbidPlayerScore_Clear)
 {
     // don't clear player score
@@ -132,7 +143,12 @@ MUTATOR_HOOKFUNCTION(br, PutClientInServer)
     entity player = M_ARGV(0, entity);
 
     if (!br_started)
+    {
+        br_CheckPlayers();
+        if(total_players >= autocvar_g_br_minplayers)
+            STAT(DROP, player) = DROP_TRANSPORT; // inhibits the spawn effect when the match is about to start
         return false;
+    }
 
     if (IN_SQUAD(player))
         Send_Notification(NOTIF_ONE_ONLY, player, MSG_CENTER, CENTER_BR_JOIN_DEAD);
@@ -162,6 +178,15 @@ MUTATOR_HOOKFUNCTION(br, MakePlayerObserver)
     return false;
 }
 
+MUTATOR_HOOKFUNCTION(br, SpectateCopy)
+{
+    entity spectatee = M_ARGV(0, entity);
+    entity client = M_ARGV(1, entity);
+
+    STAT(DROP, client) = STAT(DROP, spectatee);
+    STAT(BLEEDING, client) = STAT(BLEEDING, spectatee);
+}
+
 MUTATOR_HOOKFUNCTION(br, SpectateSet)
 {
     entity client = M_ARGV(0, entity);
@@ -184,7 +209,7 @@ MUTATOR_HOOKFUNCTION(br, SpectateNext)
     else
         new_target = client.br_squad.br_squad_first;
 
-    while((new_target == client) || IS_DEAD(new_target) || IS_SPEC(new_target) || IS_OBSERVER(new_target))
+    while((new_target == client) || IS_DEAD(new_target) || !IS_PLAYER(new_target))
     {
         new_target = new_target.br_squad_next;
         if(!new_target)
@@ -209,7 +234,7 @@ MUTATOR_HOOKFUNCTION(br, SpectatePrev)
     else
         new_target = client.br_squad.br_squad_last;
 
-    while((new_target == client) || IS_DEAD(new_target) || IS_SPEC(new_target) || IS_OBSERVER(new_target))
+    while((new_target == client) || IS_DEAD(new_target) || !IS_PLAYER(new_target))
     {
         new_target = new_target.br_squad_prev;
         if(!new_target)
@@ -225,6 +250,15 @@ MUTATOR_HOOKFUNCTION(br, ForbidSpawn)
     return br_started;
 }
 
+MUTATOR_HOOKFUNCTION(br, WantWeapon)
+{
+    if(autocvar_g_br_startweapons)
+        return false;
+
+    M_ARGV(1, float) = 0;
+    return true;
+}
+
 MUTATOR_HOOKFUNCTION(br, SetStartItems)
 {
     start_items &= ~(IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS);
@@ -245,7 +279,7 @@ MUTATOR_HOOKFUNCTION(br, SetStartItems)
 #endif
 
 #define IN_REVIVING_RANGE(player, it, revive_extra_size) \
-    (it != player && !IS_DEAD(it) && !IS_SPEC(it) && !IS_OBSERVER(it) && SAME_SQUAD(it, player) \
+    (it != player && IS_PLAYER(it) && !IS_DEAD(it) && SAME_SQUAD(it, player) \
     && boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
 
 MUTATOR_HOOKFUNCTION(br, PlayerPreThink, CBC_ORDER_FIRST)
@@ -257,23 +291,34 @@ MUTATOR_HOOKFUNCTION(br, PlayerPreThink, CBC_ORDER_FIRST)
 
     if(ring)
     {
-        if(vlen((player.origin + player.view_ofs) - ring.origin) > ring_calculate_current_radius(ring))
+        const float ring_damage_interval = 0.75;
+        vector current_origin;
+        if(!player.vehicle)
+            current_origin = player.origin + player.view_ofs;
+        else
+            current_origin = player.vehicle.origin;
+        if(vlen(current_origin - ring.origin) > ring_calculate_current_radius(ring))
         {
             if(!player.br_ring_warned)
             {
                 player.br_ring_warned = true;
+                player.br_ring_damage_time = time + ring_damage_interval;
                 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_BR_RING_WARN);
             }
 
-            if(player.vehicle) // if the player is controlling a vehicle
+            // ring damage
+            if (player.br_ring_damage_time < time)
             {
-                if(autocvar_g_br_ring_exitvehicle)
-                    vehicles_exit(player.vehicle, VHEF_RELEASE); // begone!
-                else
-                    vehicles_damage(player.vehicle, ring, ring, 10 * ring.strength * frametime, DEATH_RING.m_id, DMG_NOWEP, player.vehicle.origin, '0 0 0');
+                if(player.vehicle) // if the player is controlling a vehicle
+                {
+                    if(autocvar_g_br_ring_exitvehicle)
+                        vehicles_exit(player.vehicle, VHEF_RELEASE); // begone!
+                    else
+                        vehicles_damage(player.vehicle, ring, ring, 10 * ring.strength * ring_damage_interval, DEATH_RING.m_id, DMG_NOWEP, player.vehicle.origin, '0 0 0');
+                }
+                Damage(player, ring, ring, ring.strength * ring_damage_interval, DEATH_RING.m_id, DMG_NOWEP, player.origin, '0 0 0');
+                player.br_ring_damage_time = time + ring_damage_interval;
             }
-
-            Damage(player, ring, ring, ring.strength * frametime, DEATH_RING.m_id, DMG_NOWEP, player.origin, '0 0 0'); // ring damage
         }
         else
         {
@@ -325,7 +370,10 @@ MUTATOR_HOOKFUNCTION(br, PlayerPreThink, CBC_ORDER_FIRST)
             if(!(IN_SQUAD(player) && player.br_squad.br_squad_drop_leader))
             {
                 player.effects &= ~EF_NODRAW;
-                player.flags &= ~FL_NOTARGET;
+                player.takedamage = DAMAGE_AIM;
+                player.solid = SOLID_SLIDEBOX;
+                if(!autocvar__notarget)
+                    player.flags &= ~FL_NOTARGET;
                 Kill_Notification(NOTIF_ONE_ONLY, player, MSG_CENTER, CPID_BR_DROP);
                 STAT(DROP, player) = DROP_FALLING;
                 player.br_drop_detached = 0;
@@ -362,7 +410,10 @@ MUTATOR_HOOKFUNCTION(br, PlayerPreThink, CBC_ORDER_FIRST)
 
                     FOREACH_CLIENT(IS_PLAYER(it) && (it != player) && SAME_SQUAD(it, player) && (STAT(DROP, it) == DROP_TRANSPORT), {
                         it.effects &= ~EF_NODRAW;
-                        it.flags &= ~FL_NOTARGET;
+                        it.takedamage = DAMAGE_AIM;
+                        it.solid = SOLID_SLIDEBOX;
+                        if(!autocvar__notarget)
+                            it.flags &= ~FL_NOTARGET;
                         Kill_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CPID_BR_DROP);
                         STAT(DROP, it) = DROP_FALLING;
                         it.br_drop_detached = 0;
@@ -600,12 +651,6 @@ MUTATOR_HOOKFUNCTION(br, PM_Physics)
             player.flags |= FL_PICKUPITEMS;
             player.dphitcontentsmask |= DPCONTENTS_BODY;
 
-            SetResource(player, RES_SHELLS, start_ammo_shells);
-            SetResource(player, RES_BULLETS, start_ammo_nails);
-            SetResource(player, RES_ROCKETS, start_ammo_rockets);
-            SetResource(player, RES_CELLS, start_ammo_cells);
-            SetResource(player, RES_PLASMA, start_ammo_plasma);
-            SetResource(player, RES_FUEL, start_ammo_fuel);
             STAT(WEAPONS, player) = player.br_wepset_old;
 
             .entity weaponentity = weaponentities[0];
@@ -626,19 +671,20 @@ MUTATOR_HOOKFUNCTION(br, PM_Physics)
 
 MUTATOR_HOOKFUNCTION(br, Damage_Calculate)
 {
-    entity target = M_ARGV(2, entity);
-    float deathtype = M_ARGV(3, float);
+    entity frag_target = M_ARGV(2, entity);
+    float frag_deathtype = M_ARGV(3, float);
 
-    if(STAT(DROP, target) != DROP_LANDED)
+    if(STAT(DROP, frag_target) != DROP_LANDED)
     {
         // weapon impact has no push force while dropping
         M_ARGV(6, vector) = '0 0 0';
 
-        if(STAT(DROP, target) == DROP_TRANSPORT)
+        if(STAT(DROP, frag_target) == DROP_TRANSPORT)
             M_ARGV(4, float) = M_ARGV(5, float) = 0; // can't take damage while on the dropship
+        else if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER)); // do not adjust vaporizer damage
         else
         {
-            switch(deathtype)
+            switch(frag_deathtype)
             {
                 case DEATH_FALL.m_id:
                 case DEATH_SHOOTING_STAR.m_id:
@@ -666,7 +712,10 @@ MUTATOR_HOOKFUNCTION(br, PlayerDies, CBC_ORDER_FIRST)
     if(STAT(DROP, frag_target) == DROP_TRANSPORT)
     {
         frag_target.effects &= ~EF_NODRAW;
-        frag_target.flags &= ~FL_NOTARGET;
+        frag_target.takedamage = DAMAGE_AIM;
+        frag_target.solid = SOLID_SLIDEBOX;
+        if(!autocvar__notarget)
+            frag_target.flags &= ~FL_NOTARGET;
         Kill_Notification(NOTIF_ONE_ONLY, frag_target, MSG_CENTER, CPID_BR_DROP);
     }
 
@@ -683,6 +732,7 @@ MUTATOR_HOOKFUNCTION(br, PlayerDies, CBC_ORDER_FIRST)
     {
         set_movetype(frag_target, MOVETYPE_WALK);
         frag_target.dphitcontentsmask |= DPCONTENTS_BODY;
+        STAT(WEAPONS, frag_target) = frag_target.br_wepset_old;
         STAT(DROP, frag_target) = DROP_LANDED;
     }
 
@@ -833,7 +883,7 @@ MUTATOR_HOOKFUNCTION(br, GetResourceLimit)
     }
 }
 
-MUTATOR_HOOKFUNCTION(br, PlayerRegen)
+MUTATOR_HOOKFUNCTION(br, PlayerRegen, CBC_ORDER_FIRST)
 {
     entity player = M_ARGV(0, entity);
 
@@ -841,9 +891,10 @@ MUTATOR_HOOKFUNCTION(br, PlayerRegen)
         M_ARGV(7, float) = max(autocvar_g_br_bleed, 0);
         M_ARGV(8, float) = max(autocvar_g_br_bleedlinear, 0);
         M_ARGV(2, float) = M_ARGV(10, float) = 0;
-        return false;
     }
-    return true;
+    else{
+        M_ARGV(2, float) = M_ARGV(3, float) = 0; // no regeneration or rot in battle royale
+    }
 }
 
 MUTATOR_HOOKFUNCTION(br, PlayerCanCrouch)
@@ -874,7 +925,7 @@ MUTATOR_HOOKFUNCTION(br, TurretValidateTarget)
     entity turret = M_ARGV(0, entity);
     entity target = M_ARGV(1, entity);
 
-    if(SAME_SQUAD(turret, target) || (STAT(DROP, target) == DROP_TRANSPORT))
+    if(!br_started || SAME_SQUAD(turret, target) || (STAT(DROP, target) == DROP_TRANSPORT))
     {
         M_ARGV(3, float) = -1;
         return true;
@@ -899,7 +950,7 @@ MUTATOR_HOOKFUNCTION(br, CustomizeWaypoint)
     entity player = M_ARGV(1, entity);
 
     if(wp.owner == NULL)
-        return false;
+        return true;
 
     if((wp == wp.owner.br_allywaypoint) && (vdist(wp.owner.origin - player.origin, <, autocvar_g_br_squad_waypoint_distance) || STAT(BLEEDING, wp.owner)))
         return true;
@@ -1007,12 +1058,15 @@ int br_WinningCondition()
         GameRules_scoring_add(member, BR_RANK, 1);
     }
 
+    delete(round_handler);
+    round_handler = NULL;
+
     return WINNING_YES;
 }
 
 bool br_isEliminated(entity e)
 {
-    return (IN_SQUAD(e) && (IS_DEAD(e) || IS_SPEC(e) || IS_OBSERVER(e)));
+    return (IN_SQUAD(e) && (IS_DEAD(e) || !IS_PLAYER(e)));
 }
 
 bool br_CheckPlayers()
@@ -1039,12 +1093,21 @@ bool br_CheckPlayers()
 }
 
 void br_Start(){
+    // battle royale does not need those, besides, the timelimit won't be visible anymore after the game started
+    cvar_set("timelimit", "0");
+    cvar_set("fraglimit", "0");
+    cvar_set("leadlimit", "0");
+
+    reset_map(true);
+
     ring = ring_initialize();
 
     dropship = dropship_initialize();
 
     if(!dropship)
     {
+        br_started = true;
+
         delete(ring);
         ring = NULL;
 
@@ -1058,27 +1121,11 @@ void br_Start(){
     int num_players = 0;
 
     FOREACH_CLIENT(IS_PLAYER(it), {
-        GameRules_scoring_add(it, BR_RANK, -GameRules_scoring_add(it, BR_RANK, 0));
-        GameRules_scoring_add(it, BR_SQUAD, -GameRules_scoring_add(it, BR_SQUAD, 0));
-        GameRules_scoring_add(it, BR_REVIVALS, -GameRules_scoring_add(it, BR_REVIVALS, 0));
+        STAT(DROP, it) = DROP_TRANSPORT;
+        PutPlayerInServer(it);
 
-        if(it.vehicle)
-            vehicles_exit(it.vehicle, VHEF_RELEASE);
-
-        RemoveGrapplingHooks(it);
-        StatusEffects_removeall(it, STATUSEFFECT_REMOVE_CLEAR);
-
-        // isn't there another way to initialize these?
-        SetResource(it, RES_HEALTH, start_health);
-        SetResource(it, RES_ARMOR, start_armorvalue);
-        SetResource(it, RES_SHELLS, 0);
-        SetResource(it, RES_BULLETS, 0);
-        SetResource(it, RES_ROCKETS, 0);
-        SetResource(it, RES_CELLS, 0);
-        SetResource(it, RES_PLASMA, 0);
-        SetResource(it, RES_FUEL, 0);
+        it.br_wepset_old = STAT(WEAPONS, it);
         STAT(WEAPONS, it) = '0 0 0';
-        it.br_wepset_old = autocvar_g_br_startweapons ? start_weapons : '0 0 0';
         for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
         {
             it.br_weapon_prev[slot] = WEP_Null;
@@ -1094,7 +1141,7 @@ void br_Start(){
 
     for(int num_squads = 0; (num_squads * max_squad_size) < num_players; ++num_squads)
     {
-        entity new_squad = spawn();
+        entity new_squad = new_pure(squad);
         new_squad.br_squad_drop_leader = NULL;
         new_squad.br_squad_id = num_squads + 1;
 
@@ -1115,8 +1162,9 @@ void br_Start(){
         it.flags |= FL_NOTARGET;
         it.dphitcontentsmask &= ~DPCONTENTS_BODY;
         it.effects |= EF_NODRAW;
+        it.takedamage = DAMAGE_NO;
+        it.solid = SOLID_NOT;
         it.br_drop_instructions = false;
-        STAT(DROP, it) = DROP_TRANSPORT;
         it.br_drop_launch = 0;
         UNSET_ONGROUND(it); // otherwise this isn't unset if the player drops in the same frame
 
@@ -1152,6 +1200,7 @@ void br_Start(){
             it.br_force_drop_distance = min_distance + random() * max(dropship_path_length - (min_distance + dropship_speed * br_drop_time_secs), 0);
     });
 
+    round_handler.cnt = 0; // emulate round handler round start
     br_started = true;
 }
 
@@ -1160,5 +1209,10 @@ void br_Initialize()
     br_started = false;
     squads_colored = autocvar_g_br_squad_colors;
 
+    // emulate the round handler, useful because this will cause a lot of code to correctly treat the stage before the match starts
+    round_handler = new_pure(round_handler);
+    round_handler.cnt = 1;
+    round_handler.wait = false;
+
     EliminatedPlayers_Init(br_isEliminated);
 }
index d14442783e73a652763fda406bb68c3673b01d61..8ec22c1ab12889934cce1bbbca3620ec4b7f766b 100644 (file)
@@ -3,6 +3,8 @@
 #include <common/mutators/base.qh>
 #include <common/scores.qh>
 
+entity ring;
+
 void br_Initialize();
 
 REGISTER_MUTATOR(br, false)
@@ -11,9 +13,10 @@ REGISTER_MUTATOR(br, false)
     MUTATOR_ONADD
     {
         GameRules_teams(false);
+        GameRules_score_enabled(false);
         GameRules_limit_score(0);
         GameRules_limit_lead(0);
-        GameRules_score_enabled(false);
+        GameRules_limit_time(0);
         GameRules_scoring(0, 0, 0, {
             field(SP_BR_RANK, "rank", SFL_LOWER_IS_BETTER | SFL_RANK | SFL_SORT_PRIO_PRIMARY);
             field(SP_BR_SQUAD, "squad", 0);
@@ -34,3 +37,4 @@ float autocvar_g_br_bleed = 0.02;
 float autocvar_g_br_bleedlinear = 1;
 int autocvar_g_br_squad_size = 3;
 int autocvar_g_br_minplayers = 2;
+bool autocvar_g_br_ring_exitvehicle = false;
index 60cc3277a11162fe985c1e73808ab517c99ee13b..6b9b1ffba926a86a024f21b1d71aaae652bc7e1d 100644 (file)
@@ -14,7 +14,7 @@ int br_SquadUpdateInfo()
 
         for(entity member = it.br_squad_first; member; member = member.br_squad_next)
         {
-            if (IS_DEAD(member) || IS_SPEC(member) || IS_OBSERVER(member))
+            if (IS_DEAD(member) || !IS_PLAYER(member))
                 continue;
             ++alive_players;
 
@@ -37,7 +37,7 @@ int br_SquadUpdateInfo()
             Send_Notification(NOTIF_ONE, member, MSG_CENTER, CENTER_BR_DEAD_SQUAD);
             GameRules_scoring_add(member, BR_RANK, alive_squads + 1);
 
-            if (IS_DEAD(member) || IS_SPEC(member) || IS_OBSERVER(member))
+            if (IS_DEAD(member) || !IS_PLAYER(member))
                 continue;
 
             // kill player
@@ -148,7 +148,7 @@ entity br_SquadFindLastAlive(entity squad, bool healthy_only)
     entity last_alive = NULL;
     for(entity member = squad.br_squad_first; member; member = member.br_squad_next)
     {
-        if (!IS_DEAD(member) && !IS_SPEC(member) && !IS_OBSERVER(member) && (!STAT(BLEEDING, member) || !healthy_only))
+        if (IS_PLAYER(member) && !IS_DEAD(member) && (!STAT(BLEEDING, member) || !healthy_only))
         {
             if(last_alive)
                 return NULL; // more than one squad member is alive
index 7b85e73841fab07f2063e676e6447531ed948881..7c5ef98f88abb27ce8176b1a4b4879b3459b6a7b 100644 (file)
@@ -818,7 +818,7 @@ MUTATOR_HOOKFUNCTION(buffs, ForbidThrowCurrentWeapon)
                float best_distance = autocvar_g_buffs_swapper_range;
                entity closest = NULL;
                FOREACH_CLIENT(IS_PLAYER(it), {
-                       if(!IS_DEAD(it) && !STAT(FROZEN, it) && !it.vehicle)
+                       if(!IS_DEAD(it) && !STAT(FROZEN, it) && !it.vehicle && (STAT(DROP, player) == DROP_LANDED))
                        if(DIFF_TEAM(it, player))
                        {
                                float test = vlen2(player.origin - it.origin);
index bbecb83da6efe8b9cb65641dc66e6f38977e3cab..87aa28410b3ec398c6634b304c59271426db5032 100644 (file)
@@ -942,11 +942,21 @@ void vehicles_enter(entity pl, entity veh)
        if((IS_BOT_CLIENT(pl) && !autocvar_g_vehicles_allow_bots))
                return;
 
+       bool veh_ring_no_enter = false;
+       if(ring && autocvar_g_br_ring_exitvehicle)
+       {
+               if(vlen(veh.origin - ring.origin) > ring_calculate_current_radius(ring))
+                       veh_ring_no_enter = true;
+       }
+
        if((!IS_PLAYER(pl))
        || (veh.phase >= time)
        || (pl.vehicle_enter_delay >= time)
        || (STAT(FROZEN, pl))
        || (IS_DEAD(pl))
+       || (STAT(BLEEDING, pl))
+       || (STAT(DROP, pl) != DROP_LANDED)
+       || (veh_ring_no_enter)
        || (pl.vehicle)
        ) { return; }
 
index 34a44cdc4b039a76e272c263c98b11e613a8a955..24f9ef00d7c3ae965481ac15c0b8de0a226b8453 100644 (file)
@@ -657,9 +657,12 @@ void PutPlayerInServer(entity this)
        this.waterlevel = WATERLEVEL_NONE;
        this.watertype = CONTENT_EMPTY;
 
-       entity spawnevent = new_pure(spawnevent);
-       spawnevent.owner = this;
-       Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
+       if(STAT(DROP, this) != DROP_TRANSPORT)
+       {
+               entity spawnevent = new_pure(spawnevent);
+               spawnevent.owner = this;
+               Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
+       }
 
        // Cut off any still running player sounds.
        stopsound(this, CH_PLAYER_SINGLE);
@@ -1212,7 +1215,7 @@ void ClientDisconnect(entity this)
        PlayerStats_GameReport_FinalizePlayer(this);
        if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
        if (CS(this).active_minigame) part_minigame(this);
-       if (IS_PLAYER(this)) Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
+       if (IS_PLAYER(this) && (STAT(DROP, this) != DROP_TRANSPORT)) Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
 
        if (autocvar_sv_eventlog)
                GameLogEcho(strcat(":part:", ftos(this.playerid)));
index 3fa3dc6c6fb263ee43874d7ab52a620ec2a7abee..de51d7f70d38cb38f2a138ce33fdac309fdd4fea 100644 (file)
@@ -508,7 +508,7 @@ IMPULSE(waypoint_personal_death)
 
 IMPULSE(waypoint_here_follow)
 {
-       if (!teamplay) return;
+       if (!teamplay && !IN_SQUAD(this)) return;
        if (IS_DEAD(this)) return;
        if (!MUTATOR_CALLHOOK(HelpMePing, this))
        {