]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'DefaultUser/more_damagetext' into 'master'
authorMario <zacjardine@y7mail.com>
Thu, 10 Nov 2016 15:58:10 +0000 (15:58 +0000)
committerMario <zacjardine@y7mail.com>
Thu, 10 Nov 2016 15:58:10 +0000 (15:58 +0000)
Add more options for damagetext

{potential} describes the full damage the target took without capping it when the target dies
{potential_health} describes the health damage the target took without capping it when the target dies

See merge request !382

85 files changed:
.gitlab-ci.yml
defaultXonotic.cfg
monsters.cfg
mutators.cfg
qcsrc/client/defs.qh
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/main.qc
qcsrc/client/progs.inc
qcsrc/client/shownames.qc
qcsrc/client/view.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/constants.qh
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/mutator/dodging/sv_dodging.qc
qcsrc/common/mutators/mutator/instagib/sv_instagib.qc
qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/overkill/rpc.qc
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc
qcsrc/common/net_linked.qh [new file with mode: 0644]
qcsrc/common/notifications/all.qc
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/triggers/func/train.qc
qcsrc/common/triggers/target/music.qc
qcsrc/common/turrets/turret/ewheel.qc
qcsrc/common/turrets/turret/walker.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hook.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/tuba.qc
qcsrc/common/weapons/weapon/tuba.qh
qcsrc/lib/_all.inc
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/lib/csqcmodel/sv_model.qc
qcsrc/lib/draw.qh
qcsrc/lib/matrix/_mod.inc
qcsrc/lib/matrix/_mod.qh
qcsrc/lib/net.qh
qcsrc/lib/warpzone/client.qc
qcsrc/lib/warpzone/common.qc
qcsrc/lib/warpzone/common.qh
qcsrc/lib/warpzone/server.qc
qcsrc/lib/warpzone/server.qh
qcsrc/menu/xonotic/dialog_settings_game_model.qc
qcsrc/menu/xonotic/dialog_uid2name.qh
qcsrc/menu/xonotic/serverlist.qh
qcsrc/server/_all.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/navigation.qc
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/client.qc
qcsrc/server/command/getreplies.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/defs.qh
qcsrc/server/g_hook.qc
qcsrc/server/g_models.qc
qcsrc/server/g_world.qc
qcsrc/server/mapvoting.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_assault.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/player.qc
qcsrc/server/progs.inc
qcsrc/server/race.qc
qcsrc/server/scores.qc
qcsrc/server/spawnpoints.qc
qcsrc/server/sv_main.qc
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/common.qc
qcsrc/server/weapons/csqcprojectile.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/weaponsystem.qc

index 3c251dccc6bab8b822b9bf94bd5fb2e2c1d54d9e..3c4126b01d23bcbf383052bdaaffb6592f85ef32 100644 (file)
@@ -30,7 +30,7 @@ test_sv_game:
     - wget -O data/maps/g-23.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.cache
     - wget -O data/maps/g-23.waypoints.hardwired https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.hardwired
     - make
-    - EXPECT=0a9ea83e32e148da989cbbadc7421ea0
+    - EXPECT=93decd0a82cf911f02fb5572197db7f3
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 0ae1e3dae708707bde38daea3d0cfbf6cb6a7590..bc346e94a7e6c66d1e10a0daadb4852a7a537c0d 100644 (file)
@@ -791,6 +791,7 @@ seta cl_damagetext_alpha_lifetime "3" "Damage text lifetime in seconds"
 seta cl_damagetext_velocity "0 0 20" "Damage text move direction"
 seta cl_damagetext_offset "0 -40 0" "Damage text offset"
 seta cl_damagetext_accumulate_range "30" "Damage text spawned within this range is accumulated"
+seta cl_damagetext_accumulate_alpha_rel "0.65" "Only update existing damage text when it's above this much percentage (0 to 1) of the starting alpha"
 seta cl_damagetext_friendlyfire "1" "Show damage text for friendlyfire too"
 seta cl_damagetext_friendlyfire_color "1 0 0" "Damage text color for friendlyfire"
 
index b5a97f87a52db532a16eea6cc85d5ac5d54eca34..1c87a716da1773d8dcbcac3a15e603464bcc59d7 100644 (file)
@@ -88,7 +88,7 @@ set g_monster_shambler_speed_walk 150
 // {{{ Misc
 set g_monsters 1
 set g_monsters_edit 0
-set g_monsters_think_delay 0.1
+set g_monsters_think_delay 0.03333
 set g_monsters_skill 1 "Monster skill (affecting some of their attributes). 1 - easy, 2 - medium, 3 - hard, 4 - insane, 5 - nightmare"
 set g_monsters_miniboss_chance 5
 set g_monsters_miniboss_healthboost 100
index 2188f80070834fc6b34ae7deef98256e6c73fda9..b5e9b76df68c7dcc9a962a191b19fe54b63a997e 100644 (file)
@@ -125,8 +125,9 @@ seta cl_spawn_near_teammate 1 "toggle for spawning near teammates (only effectiv
 set g_spawn_near_teammate 0 "if set, players prefer spawns near a team mate"
 set g_spawn_near_teammate_distance 640 "max distance to consider a spawn to be near a team mate"
 set g_spawn_near_teammate_ignore_spawnpoint 0 "ignore spawnpoints and spawn right at team mates, if 2, clients can ignore this option"
+set g_spawn_near_teammate_ignore_spawnpoint_max 10 "if set, test at most this many of the available teammates"
 set g_spawn_near_teammate_ignore_spawnpoint_delay 2.5 "how long to wait before its OK to spawn at a player after someone just spawned at this player"
-set g_spawn_near_teammate_ignore_spawnpoint_delay_death 0 "how long to wait before its OK to spawn at a player after death"
+set g_spawn_near_teammate_ignore_spawnpoint_delay_death 3 "how long to wait before its OK to spawn at a player after death"
 set g_spawn_near_teammate_ignore_spawnpoint_check_health 1 "only allow spawn at this player if their health is full"
 set g_spawn_near_teammate_ignore_spawnpoint_closetodeath 1 "spawn as close to death location as possible"
 
@@ -436,4 +437,4 @@ set g_walljump 0 "Enable wall jumping mutator"
 set g_walljump_delay 1 "Minimum delay between wall jumps"
 set g_walljump_force 300 "How far to bounce/jump off the wall"
 set g_walljump_velocity_xy_factor 1.15 "How much to slow down along horizontal axis, higher value = higher deceleration, if factor is < 1, you accelerate by wall jumping"
-set g_walljump_velocity_z_factor 0.5 "Upwards velocity factor, multiplied by normal jump velocity"
\ No newline at end of file
+set g_walljump_velocity_z_factor 0.5 "Upwards velocity factor, multiplied by normal jump velocity"
index 182f6ace743c71437f9a9f6fb6d323abf6bf21cc..437e1dd75bab5538dc80c311102adcb7719a8ebd 100644 (file)
@@ -27,7 +27,7 @@ float         dmg_take;
 .int team;
 .int team_size;
 
-float vid_conwidth, vid_conheight;
+float vid_conheight;
 int binddb;
 
 // QUALIFYING
@@ -88,7 +88,7 @@ vector lightning_shotorigin[4];
 float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
 #endif
 
-float servertime, serverprevtime, serverdeltatime;
+float serverprevtime, serverdeltatime;
 
 float ticrate;
 
index 117badbec4e1baf80aca961ff8d22042534d8dd2..994ff12aa59e4c6ca25a63591638d1e30397b458 100644 (file)
@@ -3,6 +3,7 @@
 #include "quickmenu.qh"
 #include <common/ent_cs.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/mapinfo.qh>
 #include <common/minigames/cl_minigames.qh>
 #include <common/stats.qh>
@@ -1120,11 +1121,11 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                int weapon_stats = weapon_accuracy[i - WEP_FIRST];
 
                WepSet set = it.m_wepset;
-               if (weapon_stats < 0)
+               if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
                {
-                       if (!(weapons_stat & set) && (it.spawnflags & WEP_FLAG_HIDDEN || it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
-                               nHidden += 1;
-                       else if (!(weapons_stat & set || weapons_inmap & set))
+                       if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)))
+                               ++nHidden;
+                       else
                                ++disownedcnt;
                }
        });
@@ -1198,7 +1199,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                int weapon_stats = weapon_accuracy[i - WEP_FIRST];
 
                WepSet set = it.m_wepset;
-               if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
+               if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
                        continue;
 
                float weapon_alpha;
index 9bcfd4e7a9c58571bbafdba76dfb5b247a1ba230..36ca217240f0ba0e8a6966fcb25b06829df43491 100644 (file)
@@ -15,6 +15,7 @@
 #include <common/mapinfo.qh>
 #include <common/minigames/cl_minigames.qh>
 #include <common/minigames/cl_minigames_hud.qh>
+#include <common/net_linked.qh>
 #include <common/net_notice.qh>
 #include <common/triggers/include.qh>
 #include <common/vehicles/all.qh>
index 327df77c25fd6583f6fe7365bf931f61cc52400d..738831a5d020daf1d093806332ea290c6b8bce79 100644 (file)
@@ -2,9 +2,9 @@
 
 #if XONOTIC
 #include <client/_all.inc>
-#endif
 
 #include <ecs/_mod.inc>
+#endif
 
 #ifdef BUILD_MOD
 #include <mod/client/progs.inc>
index 75ef40521ea443504048bb7669c161db0f671fda..6a4515ac14f128f4b20eba195a090b849a0a138c 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <common/ent_cs.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/mapinfo.qh>
 #include <common/teams.qh>
 
index 3134a24ed28fed2c9b917d4d279b31053dee9b46..12f4c6a1d0e68e5b72ebb0a475d31c5dee265045 100644 (file)
@@ -13,6 +13,7 @@
 #include <common/ent_cs.qh>
 #include <common/anim.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/debug.qh>
 #include <common/mapinfo.qh>
 #include <common/gamemodes/_mod.qh>
@@ -21,6 +22,8 @@
 #include <common/triggers/target/music.qh>
 #include <common/teams.qh>
 
+#include <common/weapons/weapon/tuba.qh>
+
 #include <common/vehicles/all.qh>
 #include <common/weapons/_all.qh>
 #include <common/viewloc.qh>
@@ -311,6 +314,12 @@ void viewmodel_draw(entity this)
        {
                static string name_last;
                string name = wep.mdl;
+               if(wep == WEP_TUBA)
+               {
+                       name = (this.tuba_instrument == 0) ? "tuba" :
+                          (this.tuba_instrument == 1) ? "akordeon" :
+                                                    "kleinbottle";
+               }
                bool swap = name != name_last;
                // if (swap)
                {
index 6d58ac77a2d1a01f72688513ecc2708750d93622..1f88bc8d60ae01519f0f13774d0f81191e35e279 100644 (file)
@@ -6,6 +6,7 @@
 #include "../mutators/events.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/physics/movetypes/movetypes.qh>
 
 #include <lib/csqcmodel/interpolate.qh>
index 29f96aa4490b527ecab33592689534fb358c16ec..f3acfed4e160eacdc64aa85a4a4dd469aa7bd833 100644 (file)
@@ -1,60 +1,7 @@
 #pragma once
 
-REGISTER_NET_TEMP(TE_CSQC_PICTURE)
-REGISTER_NET_TEMP(TE_CSQC_RACE)
-REGISTER_NET_TEMP(TE_CSQC_TEAMNAGGER)
-REGISTER_NET_TEMP(TE_CSQC_PINGPLREPORT)
-REGISTER_NET_TEMP(TE_CSQC_WEAPONCOMPLAIN)
-REGISTER_NET_TEMP(TE_CSQC_VEHICLESETUP)
-
-const int RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
-const int RACE_NET_CHECKPOINT_CLEAR = 1;
-const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING = 2; // byte nextcheckpoint, short recordtime, string recordholder
-const int RACE_NET_CHECKPOINT_HIT_RACE = 3; // byte checkpoint, short delta, byte lapsdelta, string opponent
-const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT = 4; // byte checkpoint, short delta, byte lapsdelta, string opponent
-const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING = 5; // byte nextcheckpoint, float laptime, short recordtime, string recordholder
-const int RACE_NET_PENALTY_RACE = 6; // byte penaltytime, string reason
-const int RACE_NET_PENALTY_QUALIFYING = 7; // byte penaltytime, string reason
-const int RACE_NET_SERVER_RECORD = 8; // server record, sent to client
-const int RACE_NET_SPEED_AWARD = 9; // speed award, sent to client
-const int RACE_NET_SPEED_AWARD_BEST = 10; // all time best speed award, sent to client
-const int RACE_NET_SERVER_RANKINGS = 11;
-const int RACE_NET_SERVER_STATUS = 12;
 const int RANKINGS_CNT = 15;
 
-REGISTER_NET_LINKED(_ENT_CLIENT_INIT)
-#ifdef CSQC
-NET_HANDLE(_ENT_CLIENT_INIT, bool isnew) { make_pure(this); return true; }
-#endif
-/** Sent as a temp entity from a persistent linked entity */
-REGISTER_NET_TEMP(ENT_CLIENT_INIT)
-
-REGISTER_NET_LINKED(ENT_CLIENT_SCORES_INFO)
-REGISTER_NET_LINKED(ENT_CLIENT_SCORES)
-REGISTER_NET_LINKED(ENT_CLIENT_TEAMSCORES)
-REGISTER_NET_LINKED(ENT_CLIENT_NAGGER) // flags [votecalledvote]
-REGISTER_NET_LINKED(ENT_CLIENT_RADARLINK) // flags [startorigin] [endorigin] [startcolor+16*endcolor]
-REGISTER_NET_LINKED(ENT_CLIENT_PROJECTILE)
-REGISTER_NET_LINKED(ENT_CLIENT_MAPVOTE)
-REGISTER_NET_LINKED(ENT_CLIENT_CLIENTDATA)
-REGISTER_NET_LINKED(ENT_CLIENT_RANDOMSEED)
-REGISTER_NET_LINKED(ENT_CLIENT_ACCURACY)
-REGISTER_NET_LINKED(ENT_CLIENT_ELIMINATEDPLAYERS)
-
-REGISTER_NET_LINKED(ENT_CLIENT_MODEL)
-
-REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE)
-REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_CAMERA)
-REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_TELEPORTED)
-
-REGISTER_NET_LINKED(ENT_CLIENT_ARC_BEAM)
-REGISTER_NET_LINKED(ENT_CLIENT_HOOK)
-REGISTER_NET_LINKED(ENT_CLIENT_TUBANOTE)
-
-REGISTER_NET_LINKED(ENT_CLIENT_SPAWNPOINT)
-REGISTER_NET_LINKED(ENT_CLIENT_SPAWNEVENT)
-REGISTER_NET_LINKED(ENT_CLIENT_WALL)
-
 const int SPRITERULE_DEFAULT = 0;
 const int SPRITERULE_TEAMPLAY = 1;
 const int SPRITERULE_SPECTATOR = 2;
index bbaf2e4696cf85949282cad609ee7e0f24a47b95..aae268666f1e72d501150f8e0fff59fa9c786272 100644 (file)
@@ -142,6 +142,7 @@ void M_Shambler_Attack_Lightning(entity this)
        gren.damageforcescale = 0;
        gren.event_damage = M_Shambler_Attack_Lightning_Damage;
        gren.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, gren);
        gren.missile_flags = MIF_SPLASH | MIF_ARC;
        W_SetupProjVelocity_Explicit(gren, v_forward, v_up, (autocvar_g_monster_shambler_attack_lightning_speed), (autocvar_g_monster_shambler_attack_lightning_speed_up), 0, 0, false);
 
index 51122dfcf57d73a5575aff79dab4e8f25b31fdef..a122865321f0a5a69897245c38f69b9df00a4b11 100644 (file)
@@ -161,6 +161,7 @@ void M_Spider_Attack_Web(entity this)
        IL_PUSH(g_projectiles, proj);
        IL_PUSH(g_bot_dodge, proj);
        proj.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, proj);
 
        proj.bouncefactor = 0.3;
        proj.bouncestop = 0.05;
index f680f118b3dd5acbe8a14093c03556173cf3cc21..b8c3bab21e77240e82dcef113826ab1b5b96c751 100644 (file)
@@ -1324,6 +1324,8 @@ bool Monster_Spawn(entity this, bool check_appear, int mon_id)
        this.bot_attack                 = true;
        this.iscreature                 = true;
        this.teleportable               = true;
+       if(!this.damagedbycontents)
+               IL_PUSH(g_damagedbycontents, this);
        this.damagedbycontents  = true;
        this.monsterid                  = mon_id;
        this.event_damage               = Monster_Damage;
index f9cee61f1ee81e374d745a10bf3afae0b60f3013..d20814ce7c045f04390645e8b156842b5236338e 100644 (file)
@@ -93,7 +93,7 @@ bool check_close_to_wall(entity this, float threshold)
 
 #define X(OFFSET) \
        tracebox(this.origin, this.mins, this.maxs, this.origin + OFFSET, true, this); \
-       if(trace_fraction < 1 && vdist(this.origin - trace_endpos, <, threshold)) \
+       if(trace_fraction < 1 && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) && vdist(this.origin - trace_endpos, <, threshold)) \
                return true;
        X(1000*v_right);
        X(-1000*v_right);
index 6135e72b556a1aa3d7934fdbc4d631b161981df4..4c6dc15a3c0bff02b9dcaa75435e5789b2c9673f 100644 (file)
@@ -360,6 +360,12 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, SetStartItems)
        start_items |= IT_UNLIMITED_SUPERWEAPONS;
 }
 
+MUTATOR_HOOKFUNCTION(mutator_instagib, SetWeaponArena)
+{
+       // turn weapon arena off
+       M_ARGV(0, string) = "off";
+}
+
 void replace_with_insta_cells(entity item)
 {
        entity e = spawn();
index a8347499841b77d034adb39efac4853400343f29..5bd896ea279fc3178b1f5c3a7c1cdbda94441bbe 100644 (file)
@@ -8,6 +8,12 @@ MUTATOR_HOOKFUNCTION(melee_only, SetStartItems, CBC_ORDER_LAST)
        start_weapons = warmup_start_weapons = WEPSET(SHOTGUN);
 }
 
+MUTATOR_HOOKFUNCTION(melee_only, SetWeaponArena)
+{
+       // turn weapon arena off
+       M_ARGV(0, string) = "off";
+}
+
 MUTATOR_HOOKFUNCTION(melee_only, ForbidThrowCurrentWeapon)
 {
        return true;
index d2094049438414112aab676a98ee430ffbd22cd8..6ec9c23213f132f95e95993202b74494422f3ce2 100644 (file)
@@ -941,6 +941,7 @@ void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
        _nade.gravity = 1;
        _nade.missile_flags = MIF_SPLASH | MIF_ARC;
        _nade.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, _nade);
        _nade.angles = vectoangles(_nade.velocity);
        _nade.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, _nade);
@@ -1173,18 +1174,6 @@ CLASS(NadeOffhand, OffhandWeapon)
     METHOD(NadeOffhand, offhand_think, void(NadeOffhand this, entity player, bool key_pressed))
     {
        entity held_nade = player.nade;
-               if (held_nade)
-               {
-                       player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
-                       // LOG_TRACEF("%d %d", player.nade_timer, time - held_nade.nade_time_primed);
-                       makevectors(player.angles);
-                       held_nade.velocity = player.velocity;
-                       setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
-                       held_nade.angles_y = player.angles.y;
-
-                       if (time + 0.1 >= held_nade.wait)
-                               toss_nade(player, false, '0 0 0', time + 0.05);
-               }
 
         if (!CanThrowNade(player)) return;
         if (!(time > player.nade_refire)) return;
@@ -1226,6 +1215,20 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
 
        if (player.nade && (player.offhand != OFFHAND_NADE || (player.weapons & WEPSET(HOOK)))) OFFHAND_NADE.offhand_think(OFFHAND_NADE, player, player.nade_altbutton);
 
+       entity held_nade = player.nade;
+       if (held_nade)
+       {
+               player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
+               // LOG_TRACEF("%d %d", player.nade_timer, time - held_nade.nade_time_primed);
+               makevectors(player.angles);
+               held_nade.velocity = player.velocity;
+               setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
+               held_nade.angles_y = player.angles.y;
+
+               if (time + 0.1 >= held_nade.wait)
+                       toss_nade(player, false, '0 0 0', time + 0.05);
+       }
+
        if(IS_PLAYER(player))
        {
                if ( autocvar_g_nades_bonus && autocvar_g_nades )
index 122bdfc12c49bb43c89c6bb522352d18e1382b2e..ad2ee3f02994ca9e8098e794fcb7fa0d6c036f5c 100644 (file)
@@ -82,6 +82,7 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity wea
        missile.health = WEP_CVAR(rpc, health);
        missile.event_damage = W_RocketPropelledChainsaw_Damage;
        missile.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, missile);
        set_movetype(missile, MOVETYPE_FLY);
 
        missile.projectiledeathtype = WEP_RPC.m_id;
index d47da6c3c38ed43c3949eed8042f94941d8beef9..21a191a0e67c82b080d962ec034fa668fa997324 100644 (file)
@@ -341,6 +341,12 @@ MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST)
        start_weapons = warmup_start_weapons = ok_start_items;
 }
 
+MUTATOR_HOOKFUNCTION(ok, SetWeaponArena)
+{
+       // turn weapon arena off
+       M_ARGV(0, string) = "off";
+}
+
 MUTATOR_HOOKFUNCTION(ok, BuildMutatorsString)
 {
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ":OK");
index 123b8caa03fbd9876d16af1c140b0a59479504fe..e4b784371525776b05566d4cb521902701dcb8e0 100644 (file)
@@ -1,10 +1,13 @@
 #include "sv_spawn_near_teammate.qh"
 
+const float FLOAT_MAX = 340282346638528859811704183484516925440.0f;
+
 float autocvar_g_spawn_near_teammate_distance;
 int autocvar_g_spawn_near_teammate_ignore_spawnpoint;
+int autocvar_g_spawn_near_teammate_ignore_spawnpoint_max;
 float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
 float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
-int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
+bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
 bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
 
 REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
@@ -12,7 +15,6 @@ REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
 .entity msnt_lookat;
 
 .float msnt_timer;
-.vector msnt_deathloc;
 
 .float cvar_cl_spawn_near_teammate;
 
@@ -80,86 +82,124 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
                        player.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
 
                entity best_mate = NULL;
-               vector best_spot = '0 0 0';
-               float pc = 0, best_dist = 0, dist = 0;
-               FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
-                       if((autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health >= 0 && it.health >= autocvar_g_balance_health_regenstable) || autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health == 0)
-                       if(!IS_DEAD(it))
-                       if(it.msnt_timer < time)
-                       if(SAME_TEAM(player, it))
-                       if(time > it.spawnshieldtime) // spawn shielding
-                       if(!forbidWeaponUse(it))
-                       if(STAT(FROZEN, it) == 0)
-                       if(it != player)
+               vector best_pos = '0 0 0';
+               float best_dist2 = FLOAT_MAX;
+               int tested = 0;
+               FOREACH_CLIENT_RANDOM(IS_PLAYER(it), LAMBDA(
+                       if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_max && tested >= autocvar_g_spawn_near_teammate_ignore_spawnpoint_max) break;
+                       if (!SAME_TEAM(player, it)) continue;
+                       if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health && it.health < autocvar_g_balance_health_regenstable) continue;
+                       if (IS_DEAD(it)) continue;
+                       if (time < it.msnt_timer) continue;
+                       if (time < it.spawnshieldtime) continue;
+                       if (forbidWeaponUse(it)) continue;
+                       if (it == player) continue;
+
+                       tested++; // i consider a teammate to be available when he passes the checks above
+
+                       vector horiz_vel = vec2(it.velocity);
+                       // when walking slowly sideways, we assume the player wants a clear shot ahead - spawn behind him according to where he's looking
+                       // when running fast, spawn behind him according to his direction of movement to prevent colliding with the newly spawned player
+                       if (vdist(horiz_vel, >, autocvar_sv_maxspeed + 50))
+                               fixedmakevectors(vectoangles(horiz_vel));
+                       else
+                               fixedmakevectors(it.angles); // .angles is the angle of the model - usually/always 0 pitch
+
+                       // test different spots close to mate - trace upwards so it works on uneven surfaces
+                       // don't spawn in front of player or directly behind to avoid players shooting each other
+                       // test the potential spots in pairs (first pair is better than second and so on) but don't prefer one side
+                       RandomSelection_Init();
+                       for(int i = 0; i < 6; ++i)
                        {
-                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - '0 0 100', MOVE_NOMONSTERS, it);
-                               if(trace_fraction != 1.0)
-                               if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
+                               switch(i)
                                {
-                                       pc = pointcontents(trace_endpos + '0 0 1');
-                                       if(pc == CONTENT_EMPTY)
+                                       case 0:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 64 + v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 1:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 64 - v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 2:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 3:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 4:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128 + v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                                       case 5:
+                                               tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128 - v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+                                               break;
+                               }
+
+                               vector horizontal_trace_endpos = trace_endpos;
+                               //te_lightning1(NULL, it.origin, horizontal_trace_endpos);
+                               if (trace_fraction != 1.0) goto skip;
+
+                               // 400 is about the height of a typical laser jump (in overkill)
+                               // not traceline because we need space for the whole player, not just his origin
+                               tracebox(horizontal_trace_endpos, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), horizontal_trace_endpos - '0 0 400', MOVE_NORMAL, it);
+                               vector vectical_trace_endpos = trace_endpos;
+                               //te_lightning1(NULL, horizontal_trace_endpos, vectical_trace_endpos);
+                               if (trace_startsolid) goto skip; // inside another player
+                               if (trace_fraction == 1.0) goto skip; // above void or too high
+                               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) goto skip;
+                               if (pointcontents(vectical_trace_endpos) != CONTENT_EMPTY) goto skip; // no lava or slime (or water which i assume would be annoying anyway)
+                               if (tracebox_hits_trigger_hurt(horizontal_trace_endpos, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), vectical_trace_endpos)) goto skip;
+
+                               // make sure the spawned player will have floor ahead (or at least a wall - he shouldn't fall as soon as he starts moving)
+                               vector floor_test_start = vectical_trace_endpos + v_up * STAT(PL_MAX, NULL).z + v_forward * STAT(PL_MAX, NULL).x; // top front of player's bbox - highest point we know is not inside solid
+                               traceline(floor_test_start, floor_test_start + v_forward * 100 - v_up * 128, MOVE_NOMONSTERS, it);
+                               //te_beam(NULL, floor_test_start, trace_endpos);
+                               if (trace_fraction == 1.0) goto skip;
+
+                               if (autocvar_g_nades) {
+                                       bool nade_in_range = false;
+                                       IL_EACH(g_projectiles, it.classname == "nade",
                                        {
-                                               if(vdist(it.velocity, >, 5))
-                                                       fixedmakevectors(vectoangles(it.velocity));
-                                               else
-                                                       fixedmakevectors(it.angles);
+                                               if (vdist(it.origin - vectical_trace_endpos, <, autocvar_g_nades_nade_radius)) {
+                                                       nade_in_range = true;
+                                                       goto skip;
+                                               }
+                                       });
+                                       if (nade_in_range) goto skip;
+                               }
+
+                               // here, we know we found a good spot
+                               RandomSelection_Add(it, 0, string_null, vectical_trace_endpos, 1, 1);
+                               //te_lightning1(NULL, vectical_trace_endpos, vectical_trace_endpos + v_forward * 10);
 
-                                               for(pc = 0; pc < 4; ++pc) // test 4 diffrent spots close to mate
+LABEL(skip)
+                               if (i % 2 == 1 && RandomSelection_chosen_ent)
+                               {
+                                       if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
+                                       {
+                                               float dist2 = vlen2(RandomSelection_chosen_ent.origin - player.death_origin);
+                                               if (dist2 < best_dist2)
                                                {
-                                                       switch(pc)
-                                                       {
-                                                               case 0:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 128, MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               case 1:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 128 , MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               case 2:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 128 - v_forward * 64, MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               case 3:
-                                                                       tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 128 - v_forward * 64, MOVE_NOMONSTERS, it);
-                                                                       break;
-                                                               //case 4:
-                                                                       //tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128, MOVE_NOMONSTERS, it);
-                                                                       //break;
-                                                       }
-
-                                                       if(trace_fraction == 1.0)
-                                                       {
-                                                               traceline(trace_endpos + '0 0 4', trace_endpos - '0 0 100', MOVE_NOMONSTERS, it);
-                                                               if(trace_fraction != 1.0)
-                                                               {
-                                                                       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
-                                                                       {
-                                                                               dist = vlen(trace_endpos - player.msnt_deathloc);
-                                                                               if(dist < best_dist || best_dist == 0)
-                                                                               {
-                                                                                       best_dist = dist;
-                                                                                       best_spot = trace_endpos;
-                                                                                       best_mate = it;
-                                                                               }
-                                                                       }
-                                                                       else
-                                                                       {
-                                                                               setorigin(player, trace_endpos);
-                                                                               player.angles = it.angles;
-                                                                               player.angles_z = 0; // never spawn tilted even if the spot says to
-                                                                               it.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
-                                                                               return;
-                                                                       }
-                                                               }
-                                                       }
+                                                       best_dist2 = dist2;
+                                                       best_pos = RandomSelection_chosen_vec;
+                                                       best_mate = RandomSelection_chosen_ent;
                                                }
                                        }
+                                       else
+                                       {
+                                               setorigin(player, RandomSelection_chosen_vec);
+                                               player.angles = RandomSelection_chosen_ent.angles;
+                                               player.angles_z = 0; // never spawn tilted even if the spot says to
+                                               RandomSelection_chosen_ent.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
+                                               return;
+                                       }
+                                       break; // don't test the other spots near this teammate, go to the next one
                                }
                        }
                ));
 
                if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
-               if(best_dist)
+               if(best_mate)
                {
-                       setorigin(player, best_spot);
+                       setorigin(player, best_pos);
                        player.angles = best_mate.angles;
                        player.angles_z = 0; // never spawn tilted even if the spot says to
                        best_mate.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
@@ -178,11 +218,4 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
        }
 }
 
-MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerDies)
-{
-       entity frag_target = M_ARGV(0, entity);
-
-       frag_target.msnt_deathloc = frag_target.origin;
-}
-
 REPLICATE(cvar_cl_spawn_near_teammate, bool, "cl_spawn_near_teammate");
diff --git a/qcsrc/common/net_linked.qh b/qcsrc/common/net_linked.qh
new file mode 100644 (file)
index 0000000..9cd2094
--- /dev/null
@@ -0,0 +1,55 @@
+#pragma once
+
+REGISTER_NET_TEMP(TE_CSQC_PICTURE)
+REGISTER_NET_TEMP(TE_CSQC_RACE)
+REGISTER_NET_TEMP(TE_CSQC_TEAMNAGGER)
+REGISTER_NET_TEMP(TE_CSQC_PINGPLREPORT)
+REGISTER_NET_TEMP(TE_CSQC_WEAPONCOMPLAIN)
+REGISTER_NET_TEMP(TE_CSQC_VEHICLESETUP)
+
+const int RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
+const int RACE_NET_CHECKPOINT_CLEAR = 1;
+const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING = 2; // byte nextcheckpoint, short recordtime, string recordholder
+const int RACE_NET_CHECKPOINT_HIT_RACE = 3; // byte checkpoint, short delta, byte lapsdelta, string opponent
+const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT = 4; // byte checkpoint, short delta, byte lapsdelta, string opponent
+const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING = 5; // byte nextcheckpoint, float laptime, short recordtime, string recordholder
+const int RACE_NET_PENALTY_RACE = 6; // byte penaltytime, string reason
+const int RACE_NET_PENALTY_QUALIFYING = 7; // byte penaltytime, string reason
+const int RACE_NET_SERVER_RECORD = 8; // server record, sent to client
+const int RACE_NET_SPEED_AWARD = 9; // speed award, sent to client
+const int RACE_NET_SPEED_AWARD_BEST = 10; // all time best speed award, sent to client
+const int RACE_NET_SERVER_RANKINGS = 11;
+const int RACE_NET_SERVER_STATUS = 12;
+
+REGISTER_NET_LINKED(_ENT_CLIENT_INIT)
+#ifdef CSQC
+NET_HANDLE(_ENT_CLIENT_INIT, bool isnew) { make_pure(this); return true; }
+#endif
+/** Sent as a temp entity from a persistent linked entity */
+REGISTER_NET_TEMP(ENT_CLIENT_INIT)
+
+REGISTER_NET_LINKED(ENT_CLIENT_SCORES_INFO)
+REGISTER_NET_LINKED(ENT_CLIENT_SCORES)
+REGISTER_NET_LINKED(ENT_CLIENT_TEAMSCORES)
+REGISTER_NET_LINKED(ENT_CLIENT_NAGGER) // flags [votecalledvote]
+REGISTER_NET_LINKED(ENT_CLIENT_RADARLINK) // flags [startorigin] [endorigin] [startcolor+16*endcolor]
+REGISTER_NET_LINKED(ENT_CLIENT_PROJECTILE)
+REGISTER_NET_LINKED(ENT_CLIENT_MAPVOTE)
+REGISTER_NET_LINKED(ENT_CLIENT_CLIENTDATA)
+REGISTER_NET_LINKED(ENT_CLIENT_RANDOMSEED)
+REGISTER_NET_LINKED(ENT_CLIENT_ACCURACY)
+REGISTER_NET_LINKED(ENT_CLIENT_ELIMINATEDPLAYERS)
+
+REGISTER_NET_LINKED(ENT_CLIENT_MODEL)
+
+REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE)
+REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_CAMERA)
+REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_TELEPORTED)
+
+REGISTER_NET_LINKED(ENT_CLIENT_ARC_BEAM)
+REGISTER_NET_LINKED(ENT_CLIENT_HOOK)
+REGISTER_NET_LINKED(ENT_CLIENT_TUBANOTE)
+
+REGISTER_NET_LINKED(ENT_CLIENT_SPAWNPOINT)
+REGISTER_NET_LINKED(ENT_CLIENT_SPAWNEVENT)
+REGISTER_NET_LINKED(ENT_CLIENT_WALL)
index dd5f3a164b58502f1b9bdacab31c4f1789145bbf..5cf3e1c6b1493972428805f13f07535ecb3a163d 100644 (file)
@@ -4,6 +4,7 @@
 #elif defined(MENUQC)
 #elif defined(SVQC)
        #include <common/constants.qh>
+       #include <common/net_linked.qh>
        #include <common/teams.qh>
        #include <server/autocvars.qh>
        #include <server/constants.qh>
index b6dcd01f8843cc5f9310db9b93d213c4848e80ed..dc2e6f7dc0a062a2a19e8c2a611ee12b8cb14ea2 100644 (file)
@@ -89,8 +89,6 @@ void func_breakable_colormod(entity this)
                this.colormod = '1 0 0' + '0 1 0' * (2 * h - 0.5);
        else
                this.colormod = '1 1 1';
-
-       CSQCMODEL_AUTOUPDATE(this);
 }
 
 void func_breakable_look_destroyed(entity this)
@@ -113,8 +111,6 @@ void func_breakable_look_destroyed(entity this)
                this.effects &= ~EF_NODRAW;
        }
 
-       CSQCMODEL_AUTOUPDATE(this);
-
        this.solid = SOLID_NOT;
 }
 
@@ -127,8 +123,6 @@ void func_breakable_look_restore(entity this)
        if(this.mdl_dead != "") // only do this if we use mdl_dead, to behave better with misc_follow
                setorigin(this, this.dropped_origin);
 
-       CSQCMODEL_AUTOUPDATE(this);
-
        this.solid = SOLID_BSP;
 }
 
@@ -148,6 +142,12 @@ void func_breakable_behave_destroyed(entity this)
                stopsound (this, CH_TRIGGER_SINGLE);
 }
 
+void func_breakable_think(entity this)
+{
+       this.nextthink = time;
+       CSQCMODEL_AUTOUPDATE(this);
+}
+
 void func_breakable_destroy(entity this, entity actor, entity trigger);
 void func_breakable_behave_restore(entity this)
 {
@@ -168,7 +168,9 @@ void func_breakable_behave_restore(entity this)
        if(this.spawnflags & 4)
                this.use = func_breakable_destroy; // don't need to set it usually, as .use isn't reset
        this.state = 0;
-       this.nextthink = 0; // cancel auto respawn
+       //this.nextthink = 0; // cancel auto respawn
+       setthink(this, func_breakable_think);
+       this.nextthink = time + 0.1;
        func_breakable_colormod(this);
        if (this.noise1)
                _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
@@ -187,16 +189,12 @@ void func_breakable_destroyed(entity this)
 {
        func_breakable_look_destroyed(this);
        func_breakable_behave_destroyed(this);
-
-       CSQCMODEL_AUTOUPDATE(this);
 }
 
 void func_breakable_restore(entity this, entity actor, entity trigger)
 {
        func_breakable_look_restore(this);
        func_breakable_behave_restore(this);
-
-       CSQCMODEL_AUTOUPDATE(this);
 }
 
 void func_breakable_restore_self(entity this)
@@ -231,6 +229,7 @@ void func_breakable_destroy(entity this, entity actor, entity trigger)
 
        if(this.respawntime)
        {
+               CSQCMODEL_AUTOUPDATE(this);
                setthink(this, func_breakable_restore_self);
                this.nextthink = time + this.respawntime + crandom() * this.respawntimejitter;
        }
@@ -281,6 +280,7 @@ void func_breakable_damage(entity this, entity inflictor, entity attacker, float
                // do not explode NOW but in the NEXT FRAME!
                // because recursive calls to RadiusDamage are not allowed
                this.nextthink = time;
+               CSQCMODEL_AUTOUPDATE(this);
                setthink(this, func_breakable_destroy_self);
        }
 }
@@ -293,8 +293,6 @@ void func_breakable_reset(entity this)
                func_breakable_behave_destroyed(this);
        else
                func_breakable_behave_restore(this);
-
-       CSQCMODEL_AUTOUPDATE(this);
 }
 
 // destructible walls that can be used to trigger target_objective_decrease
index dd9eaac860a5efe24dc0f7d09b71569b356f5fc2..2e4356bab3214d5f124150e20975ee14056e0126 100644 (file)
@@ -1,5 +1,6 @@
 #include "train.qh"
 .float train_wait_turning;
+.entity future_target;
 void train_next(entity this);
 #ifdef SVQC
 void train_use(entity this, entity actor, entity trigger);
@@ -14,7 +15,7 @@ void train_wait(entity this)
        {
                entity targ, cp;
                vector ang;
-               targ = find(NULL, targetname, this.target);
+               targ = this.future_target;
                if((this.spawnflags & 1) && targ.curvetarget)
                        cp = find(NULL, targetname, targ.curvetarget);
                else
@@ -41,7 +42,7 @@ void train_wait(entity this)
 #endif
 
 #ifdef SVQC
-       entity tg = find(NULL, targetname, this.target);
+       entity tg = this.future_target;
        if(tg.spawnflags & 4)
        {
                this.use = train_use;
@@ -62,13 +63,34 @@ void train_wait(entity this)
        }
 }
 
+entity train_next_find(entity this)
+{
+       if(this.target_random)
+       {
+               RandomSelection_Init();
+               for(entity t = NULL; (t = find(t, targetname, this.target));)
+               {
+                       RandomSelection_AddEnt(t, 1, 0);
+               }
+               return RandomSelection_chosen_ent;
+       }
+       else
+       {
+               return find(NULL, targetname, this.target);
+       }
+}
+
 void train_next(entity this)
 {
-       entity targ, cp = NULL;
+       entity targ = NULL, cp = NULL;
        vector cp_org = '0 0 0';
 
-       targ = find(NULL, targetname, this.target);
+       targ = this.future_target;
+
        this.target = targ.target;
+       this.target_random = targ.target_random;
+       this.future_target = train_next_find(targ);
+
        if (this.spawnflags & 1)
        {
                if(targ.curvetarget)
@@ -186,9 +208,11 @@ void train_use(entity this, entity actor, entity trigger)
 
 void func_train_find(entity this)
 {
-       entity targ;
-       targ = find(NULL, targetname, this.target);
+       entity targ = train_next_find(this);
        this.target = targ.target;
+       this.target_random = targ.target_random;
+       // save the future target for later
+       this.future_target = train_next_find(targ);
        if (this.target == "")
                objerror(this, "func_train_find: no next target");
        SUB_SETORIGIN(this, targ.origin - this.view_ofs);
index 0fde9e043904d00f4093fe74bcc45a9ce0a74b52..1f8cb00cb553a95623dec5d0eb10f3d0ca3c2e9f 100644 (file)
@@ -3,6 +3,7 @@
 #elif defined(MENUQC)
 #elif defined(SVQC)
     #include <common/constants.qh>
+    #include <common/net_linked.qh>
     #include <server/constants.qh>
     #include <server/defs.qh>
 #endif
index b5716f7a9867195973b98d95ffa254d883da85a6..0a633c78446431fdb0f0c841d67c5d70e49da369 100644 (file)
@@ -198,6 +198,7 @@ METHOD(EWheel, tr_setup, void(EWheel this, entity it))
     it.iscreature                              = true;
     it.teleportable                    = TELEPORT_NORMAL;
     it.damagedbycontents               = true;
+    IL_PUSH(g_damagedbycontents, it);
     set_movetype(it, MOVETYPE_WALK);
     it.solid                                   = SOLID_SLIDEBOX;
     it.takedamage                              = DAMAGE_AIM;
index ffba71439ab995198c760c69843a7bfbe1b3e3d7..de744a65d7a6c6109aa43736beb3df1c82d9eff3 100644 (file)
@@ -570,6 +570,7 @@ METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
     it.iscreature = true;
     it.teleportable = TELEPORT_NORMAL;
     it.damagedbycontents = true;
+    IL_PUSH(g_damagedbycontents, it);
     it.solid = SOLID_SLIDEBOX;
     it.takedamage = DAMAGE_AIM;
     if(it.move_movetype != MOVETYPE_WALK)
index cd62f0746b69f6b2dc892f42a1938807cf566d07..b165bb3e481551b5cf5261390832e2a50b55b764 100644 (file)
@@ -900,7 +900,7 @@ bool vehicle_impulse(entity this, int imp)
 
 void vehicles_enter(entity pl, entity veh)
 {
-       // Remove this when bots know how to use vehicles
+   // Remove this when bots know how to use vehicles
        if((IS_BOT_CLIENT(pl) && !autocvar_g_vehicles_allow_bots))
                return;
 
@@ -1167,6 +1167,7 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop)
        this.iscreature                         = true;
        this.teleportable                       = false; // no teleporting for vehicles, too buggy
        this.damagedbycontents          = true;
+       IL_PUSH(g_damagedbycontents, this);
        this.vehicleid                          = info.vehicleid;
        this.PlayerPhysplug                     = info.PlayerPhysplug;
        this.event_damage                       = func_null;
@@ -1224,7 +1225,7 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop)
        else
                this.nextthink = time + game_starttime;
 
-       if(!MUTATOR_CALLHOOK(VehicleInit, this))
+       if(MUTATOR_CALLHOOK(VehicleInit, this))
                return false;
 
        return true;
index 57697635791cd7b229ba5bf6639717a61a21c3c1..4c9415305ab64b5fa68b765df55ca547ed734c3f 100644 (file)
@@ -290,6 +290,7 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
        missile.damageforcescale = WEP_CVAR(arc, bolt_damageforcescale);
        missile.event_damage = W_Arc_Bolt_Damage;
        missile.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, missile);
 
        settouch(missile, W_Arc_Bolt_Touch);
        missile.use = W_Arc_Bolt_Explode_use;
index df9bd470a31b9fe70caaf68cde8a2d4ff6aebf7f..7e63e760ec96d4d879a6813e6e436232aef965f2 100644 (file)
@@ -391,6 +391,7 @@ void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        missile.health = WEP_CVAR(devastator, health);
        missile.event_damage = W_Devastator_Damage;
        missile.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, missile);
 
        set_movetype(missile, MOVETYPE_FLY);
        PROJECTILE_MAKETRIGGER(missile);
index 7e05241a490873f200bbd1ecbeb5cbd8ec43e0ab..319f0d1d701ca936491e65d271e248ebedaf8202 100644 (file)
@@ -332,6 +332,7 @@ void W_Electro_Orb_Stick(entity this, entity to)
        newproj.event_damage = this.event_damage;
        newproj.spawnshieldtime = this.spawnshieldtime;
        newproj.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, newproj);
 
        set_movetype(newproj, MOVETYPE_NONE); // lock the orb in place
        newproj.projectiledeathtype = this.projectiledeathtype;
@@ -453,6 +454,8 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
        IL_PUSH(g_projectiles, proj);
        IL_PUSH(g_bot_dodge, proj);
        proj.damagedbycontents = (WEP_CVAR_SEC(electro, damagedbycontents));
+       if(proj.damagedbycontents)
+               IL_PUSH(g_damagedbycontents, proj);
 
        proj.bouncefactor = WEP_CVAR_SEC(electro, bouncefactor);
        proj.bouncestop = WEP_CVAR_SEC(electro, bouncestop);
index 097f2bfdcccdc06fb4df27b6e486d47260a77ab9..684ee75d377540a15de2911269dbf6ccf078d982 100644 (file)
@@ -155,6 +155,7 @@ void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        missile.damageforcescale = WEP_CVAR_PRI(hagar, damageforcescale);
        missile.event_damage = W_Hagar_Damage;
        missile.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, missile);
 
        settouch(missile, W_Hagar_Touch);
        missile.use = W_Hagar_Explode_use;
@@ -199,6 +200,7 @@ void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
        missile.event_damage = W_Hagar_Damage;
        missile.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, missile);
 
        settouch(missile, W_Hagar_Touch2);
        missile.cnt = 0;
@@ -260,6 +262,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
                missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
                missile.event_damage = W_Hagar_Damage;
                missile.damagedbycontents = true;
+               IL_PUSH(g_damagedbycontents, missile);
 
                settouch(missile, W_Hagar_Touch); // not bouncy
                missile.use = W_Hagar_Explode2_use;
@@ -310,7 +313,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
 {
        // loadable hagar secondary attack, must always run each frame
 
-       if(time < game_starttime || PS(actor).m_switchweapon != WEP_HAGAR)
+       if(time < game_starttime)
                return;
 
        bool loaded = actor.hagar_load >= WEP_CVAR_SEC(hagar, load_max);
index ba7efe6a31a33384e1c1b0cbcb0a535e6ca72b99..f5dd96e4c3c6b22ebf31c95f09a09f3b3e7fa03c 100644 (file)
@@ -169,6 +169,7 @@ void W_Hook_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        gren.damageforcescale = WEP_CVAR_SEC(hook, damageforcescale);
        gren.event_damage = W_Hook_Damage;
        gren.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, gren);
        gren.missile_flags = MIF_SPLASH | MIF_ARC;
 
        gren.velocity = '0 0 1' * WEP_CVAR_SEC(hook, speed);
index 5f5898aa41b78953872242278cfb5e3067a1cf54..7df6984baabb4b584570b7b7b39a958efae4c33f 100644 (file)
@@ -92,6 +92,7 @@ void W_MineLayer_Stick(entity this, entity to)
        newmine.event_damage = this.event_damage;
        newmine.spawnshieldtime = this.spawnshieldtime;
        newmine.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, newmine);
 
        set_movetype(newmine, MOVETYPE_NONE); // lock the mine in place
        newmine.projectiledeathtype = this.projectiledeathtype;
@@ -358,6 +359,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        mine.health = WEP_CVAR(minelayer, health);
        mine.event_damage = W_MineLayer_Damage;
        mine.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, mine);
 
        set_movetype(mine, MOVETYPE_TOSS);
        PROJECTILE_MAKETRIGGER(mine);
index 1428cc4fa9d8395b74522f6fc69f2e616d3f90ea..89ff5bbd8852eef69e0c497a679da28c5bde1293 100644 (file)
@@ -242,6 +242,7 @@ void W_Mortar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        gren.damageforcescale = WEP_CVAR_PRI(mortar, damageforcescale);
        gren.event_damage = W_Mortar_Grenade_Damage;
        gren.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, gren);
        gren.missile_flags = MIF_SPLASH | MIF_ARC;
        W_SetupProjVelocity_UP_PRI(gren, mortar);
 
@@ -291,6 +292,7 @@ void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        gren.damageforcescale = WEP_CVAR_SEC(mortar, damageforcescale);
        gren.event_damage = W_Mortar_Grenade_Damage;
        gren.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, gren);
        gren.missile_flags = MIF_SPLASH | MIF_ARC;
        W_SetupProjVelocity_UP_SEC(gren, mortar);
 
index ffdbfc0d7053e704c88e9152d691ede046aa6d14..0e73adf2d3bd23da383640b9b6f875851ddeb150 100644 (file)
@@ -282,6 +282,7 @@ void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, .entity weaponentity, v
        missile.health          = WEP_CVAR(seeker, missile_health);
        missile.damageforcescale = WEP_CVAR(seeker, missile_damageforcescale);
        missile.damagedbycontents = true;
+       IL_PUSH(g_damagedbycontents, missile);
        //missile.think           = W_Seeker_Missile_Animate; // csqc projectiles.
 
        if(missile.enemy != NULL)
index 7f1bce0ace2741c05340c025a1f49524ce4969e1..1f01ef0413c237e262752c59bd5daee816131968 100644 (file)
@@ -396,10 +396,12 @@ METHOD(Tuba, wr_think, void(Tuba this, entity actor, .entity weaponentity, int f
        }
 }
 
+void tuba_instrument_send(entity this, int instr);
 METHOD(Tuba, wr_setup, void(Tuba this, entity actor))
 {
        actor.ammo_field = ammo_none;
        actor.tuba_instrument = 0;
+       tuba_instrument_send(actor, actor.tuba_instrument);
 }
 #endif
 
@@ -412,6 +414,7 @@ NET_HANDLE(tuba_instrument, bool)
        string s = (i == 0) ? "tuba" :
                   (i == 1) ? "akordeon" :
                              "kleinbottle" ;
+    viewmodel.tuba_instrument = i;
        CL_WeaponEntity_SetModel(viewmodel, s, true);
 }
 #endif
@@ -494,13 +497,6 @@ const int TUBA_MIN = -18;
 const int TUBA_MAX = 27;
 const int TUBA_INSTRUMENTS = 3;
 
-entityclass(Tuba);
-class(Tuba) .int note;
-class(Tuba) .bool tuba_attenuate;
-class(Tuba) .float tuba_volume;
-class(Tuba) .float tuba_volume_initial;
-class(Tuba) .int tuba_instrument;
-
 int Tuba_PitchStep;
 
 void tubasound(entity e, bool restart)
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..ce6b6ede739c76fd2dd2eed274912ffce10228a2 100644 (file)
@@ -1 +1,10 @@
 #pragma once
+
+#ifdef CSQC
+entityclass(Tuba);
+class(Tuba) .int note;
+class(Tuba) .bool tuba_attenuate;
+class(Tuba) .float tuba_volume;
+class(Tuba) .float tuba_volume_initial;
+class(Tuba) .int tuba_instrument;
+#endif
index b6c3c9e01bea752c9d87f3d66685f3b9d596fedf..6408d6e3f2502aceebbe720c3151ccd8576dd9c2 100644 (file)
@@ -266,6 +266,8 @@ void make_safe_for_remove(entity this);
 #endif
 #undef ENGINE_EVENT
 
+#if XONOTIC
 #ifdef GAMEQC
        #include <ecs/_mod.qh>
 #endif
+#endif
index 4cc8458d51a4b0b359723f4f67b4db704bda544e..66613b53229ad6ef53d34a9ad43bc0b0ed413abd 100644 (file)
@@ -28,6 +28,7 @@
 #include <client/defs.qh>
 #include <client/main.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/physics/player.qh>
 #include <common/stats.qh>
 #include <common/triggers/trigger/viewloc.qh>
index 0f8ef06ac86a7fd890ca3a35bba045100b893050..dd8d5d33aaee2a8f479cd6edcc34f9047adf6730 100644 (file)
@@ -24,6 +24,7 @@
 #include "common.qh"
 #include <common/animdecide.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/util.qh>
 #include <server/constants.qh>
 #include <server/defs.qh>
index 698c9262370974781c1f0585caaba18103d19ff7..fbb4a09b5510705f71d43a0eb461ded50ece0d0d 100644 (file)
@@ -5,7 +5,7 @@
        #include "i18n.qh"
        #include "vector.qh"
 
-       #include <client/defs.qh>
+       float vid_conwidth;
 
        void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
        {
index 4854f092a0aba4d21b65675082913140dfb38d39..d68dc7d968ee14850297dc46b5ef744c76761a73 100644 (file)
@@ -1,3 +1,5 @@
 // generated file; do not modify
-#include <lib/matrix/command.qc>
+#if XONOTIC
+       #include <lib/matrix/command.qc>
+#endif
 #include <lib/matrix/matrix.qc>
index 965812297204137ccb73c865636c0784ca5002f3..c351afe8f7c91f41123a4d68effd731f7f79659a 100644 (file)
@@ -1,3 +1,5 @@
 // generated file; do not modify
-#include <lib/matrix/command.qh>
+#if XONOTIC
+       #include <lib/matrix/command.qh>
+#endif
 #include <lib/matrix/matrix.qh>
index 30ab014ec988f1a2fae062bbe36115b003257872..56c80e02d1b13ca5dcf66105aa597bb7c28d67f3 100644 (file)
@@ -298,6 +298,7 @@ USING(Stream, int);
        #define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
 
        #ifdef CSQC
+               float servertime;
                entity ReadCSQCEntity()
                {
                        int f = ReadShort();
@@ -313,7 +314,7 @@ USING(Stream, int);
                #define ReadInt48_t() vec3(ReadInt24_t(), ReadInt24_t(), 0)
                #define ReadInt72_t() vec3(ReadInt24_t(), ReadInt24_t(), ReadInt24_t())
 
-               int _ReadSByte;
+               noref int _ReadSByte;
                #define ReadSByte() (_ReadSByte = ReadByte(), (_ReadSByte & BIT(7) ? -128 : 0) + (_ReadSByte & BITS(7)))
                #define ReadFloat() ReadCoord()
                #define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat())
index bd0397f897330d876cdede80e284e1a2062ed0cf..15a3ca4c3ccc6e90870c72ab7bc74251777dd397 100644 (file)
@@ -35,6 +35,9 @@ NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew)
        }
        this.classname = "trigger_warpzone";
 
+       if(isnew)
+               IL_PUSH(g_warpzones, this);
+
        int f = ReadByte();
        this.warpzone_isboxy = (f & 1);
        if(f & 4)
index 90e3cd76c983a803a552b32ed7af220aaccb6b6e..5a3929e1e92d58ecd6520f0bbb05d68499e61f73 100644 (file)
@@ -154,31 +154,33 @@ float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
 entity WarpZone_Find(vector mi, vector ma)
 {
        // if we are near any warpzone planes - MOVE AWAY (work around nearclip)
-       entity e;
        if(!warpzone_warpzones_exist)
                return NULL;
-       for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
-               if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, NULL))
-                       return e;
+       IL_EACH(g_warpzones, WarpZoneLib_BoxTouchesBrush(mi, ma, it, NULL),
+       {
+               return it;
+       });
        return NULL;
 }
 
 void WarpZone_MakeAllSolid()
 {
-       entity e;
        if(!warpzone_warpzones_exist)
                return;
-       for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
-               e.solid = SOLID_BSP;
+       IL_EACH(g_warpzones, true,
+       {
+               it.solid = SOLID_BSP;
+       });
 }
 
 void WarpZone_MakeAllOther()
 {
-       entity e;
        if(!warpzone_warpzones_exist)
                return;
-       for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
-               e.solid = SOLID_TRIGGER;
+       IL_EACH(g_warpzones, true,
+       {
+               it.solid = SOLID_TRIGGER;
+       });
 }
 
 void WarpZone_Trace_InitTransform()
index 4bbbb853b00bad0266f2482cd5ef7efcccd738d3..26c0e80fe4623526ee12cecc05842fb92c4f5dd0 100644 (file)
@@ -3,6 +3,9 @@
 // uncomment this if your mod uses the roll angle in fixangle
 // #define KEEP_ROLL
 
+IntrusiveList g_warpzones;
+STATIC_INIT(g_warpzones) { g_warpzones = IL_NEW(); }
+
 float warpzone_warpzones_exist;
 float warpzone_cameras_exist;
 
index 34ea2610dedd7afa60e30ce6bab89f7df643940a..116ad00023ae98b1a4321c609698298a2dd46f0b 100644 (file)
@@ -5,9 +5,9 @@
 #elif defined(MENUQC)
 #elif defined(SVQC)
        #include <common/constants.qh>
+       #include <common/net_linked.qh>
        #include <common/triggers/subs.qh>
        #include <common/util.qh>
-       #include <server/command/_mod.qh>
        #include <server/constants.qh>
        #include <server/defs.qh>
 #endif
@@ -631,7 +631,6 @@ void WarpZone_InitStep_ClearTarget(entity this)
        this.enemy = NULL;
 }
 
-entity warpzone_first; .entity warpzone_next;
 void WarpZone_InitStep_FindTarget(entity this)
 {
        float i;
@@ -731,6 +730,8 @@ spawnfunc(trigger_warpzone)
        BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
        this.warpzone_next = warpzone_first;
        warpzone_first = this;
+
+       IL_PUSH(g_warpzones, this);
 }
 spawnfunc(func_camera)
 {
@@ -803,10 +804,19 @@ void WarpZone_StartFrame()
                WarpZone_PostInitialize_Callback();
        }
 
-       FOREACH_ENTITY_FLOAT(pure_data, false,
+       if(warpzone_warpzones_exist)
        {
-               if(warpzone_warpzones_exist)
+               IL_EACH(g_projectiles, true,
+               {
                        WarpZone_StoreProjectileData(it);
+               });
+       }
+               
+
+       FOREACH_CLIENT(true,
+       {
+               if(warpzone_warpzones_exist)
+                       WarpZone_StoreProjectileData(it); // TODO: not actually needed
 
                if(IS_OBSERVER(it) || it.solid == SOLID_NOT)
                if(IS_CLIENT(it)) // we don't care about it being a bot
index b0c583d2dc7bf31728f28e0d53de23219f689c22..4287ef60de798195e0e963d93736a7348a88d175 100644 (file)
@@ -1,6 +1,8 @@
 #pragma once
 
 #ifdef SVQC
+entity warpzone_first; .entity warpzone_next;
+
 void WarpZone_StartFrame();
 float WarpZone_Projectile_Touch(entity this, entity toucher);
 
index f0f95d74b95963fb540c5e330a538dc891f58199..b57d7cae8a8f536a643b67d25c1c7275a61801b6 100644 (file)
@@ -50,7 +50,12 @@ void XonoticGameModelSettingsTab_fill(entity me)
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayermodels", _("Force player models to mine")));
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayercolors", _("Force player colors to mine")));
+               me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Force player colors to mine")));
+               me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_forceplayercolors"));
+                       e.addValue(e, _("Never"), "0");
+                       e.addValue(e, _("In non teamplay modes only"), "1");
+                       e.addValue(e, _("Always"), "2");
+                       e.configureXonoticTextSliderValues(e);
        me.TR(me);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Body fading:")));
                me.TD(me, 1, 2, e = makeXonoticSlider(0, 2, 0.2, "cl_deathglow"));
index 7b5f23b694ba6991ebf52b1512376d227345188e..187d08068e9342bd5471fb81a3e04a1e1b0f35d6 100644 (file)
@@ -3,7 +3,7 @@
 #include "rootdialog.qh"
 CLASS(XonoticUid2NameDialog, XonoticRootDialog)
        METHOD(XonoticUid2NameDialog, fill, void(entity));
-       ATTRIB(XonoticUid2NameDialog, title, string);
+       ATTRIB(XonoticUid2NameDialog, title, string, "");
        ATTRIB(XonoticUid2NameDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
        ATTRIB(XonoticUid2NameDialog, intendedWidth, float, 0.5);
        ATTRIB(XonoticUid2NameDialog, rows, float, 4);
index 50c766e69051527be55929f7b4524c22ab228f14..e45abfda33b528cce9e9e72035dd4ab1807d47c5 100644 (file)
@@ -154,8 +154,8 @@ int category_draw_count;
        SLIST_CATEGORY(CAT_SERVERS,      "CAT_NORMAL",  "CAT_SERVERS",  CTX(_("SLCAT^Servers"))) \
        SLIST_CATEGORY(CAT_XPM,          "CAT_NORMAL",  "CAT_SERVERS",  CTX(_("SLCAT^Competitive Mode"))) \
        SLIST_CATEGORY(CAT_MODIFIED,     "",            "CAT_SERVERS",  CTX(_("SLCAT^Modified Servers"))) \
-       SLIST_CATEGORY(CAT_OVERKILL,     "",            "CAT_SERVERS",  CTX(_("SLCAT^Overkill Mode"))) \
-       SLIST_CATEGORY(CAT_INSTAGIB,     "",            "CAT_SERVERS",  CTX(_("SLCAT^InstaGib Mode"))) \
+       SLIST_CATEGORY(CAT_OVERKILL,     "",            "CAT_SERVERS",  CTX(_("SLCAT^Overkill"))) \
+       SLIST_CATEGORY(CAT_INSTAGIB,     "",            "CAT_SERVERS",  CTX(_("SLCAT^InstaGib"))) \
        SLIST_CATEGORY(CAT_DEFRAG,       "",            "CAT_SERVERS",  CTX(_("SLCAT^Defrag Mode")))
 
 #define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
index ed3083a1203fd94c69943efb17341c80c45127d1..1fabe4d0f965aa9abd6b564b180ad4e83637a96d 100644 (file)
@@ -43,6 +43,37 @@ const string STR_OBSERVER = "observer";
 
 #define FOREACH_CLIENT(cond, body) FOREACH_CLIENTSLOT(IS_CLIENT(it) && (cond), body)
 
+// using the "inside out" version of knuth-fisher-yates shuffle
+// https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
+entity _FCR_clients[255];
+bool _FCR_entered = false;
+#define FOREACH_CLIENT_RANDOM(cond, body) \
+       MACRO_BEGIN { \
+               if (_FCR_entered) LOG_FATAL("FOREACH_CLIENT_RANDOM must not be nested"); \
+               _FCR_entered = true; \
+               int _cnt = 0; \
+               FOREACH_CLIENT(cond, LAMBDA( \
+                       int _j = floor(random() * (_cnt + 1)); \
+                       if (_j == _cnt) \
+                       { \
+                               _FCR_clients[_cnt] = it; \
+                       } \
+                       else \
+                       { \
+                               _FCR_clients[_cnt] = _FCR_clients[_j]; \
+                               _FCR_clients[_j] = it; \
+                       } \
+                       _cnt++; \
+               )); \
+               for (int _i = 0; _i < _cnt; ++_i) \
+               { \
+                       const noref int i = _i; \
+                       ITER_CONST noref entity it = _FCR_clients[i]; \
+                       if (cond) { LAMBDA(body) } \
+               } \
+               _FCR_entered = false; \
+       } MACRO_END
+
 // NOTE: FOR_EACH_MONSTER deprecated! Use the following instead: IL_EACH(g_monsters, true, { code; });
 
 #include <common/effects/all.qh>
index bdde55b9aa94683b7ffb0901229203fb1ff59116..2a7478dee2d7688322dfa3006b4534957159bcd3 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <common/physics/player.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/mapinfo.qh>
 #include <common/teams.qh>
 #include <common/util.qh>
index 45051b6c270f1e738aa05786b3fbc9f54f1ecc34..56c36c0745a759e4236f3893ce08e327c12ee50f 100644 (file)
@@ -9,6 +9,7 @@
 #include "../waypoints.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/physics/player.qh>
 #include <common/state.qh>
 #include <common/items/_mod.qh>
index 17f61af141ff7c8b08a3d736011ae9a77043c705..7c71720c4c80ee49dfc2538093297ea65a8109d0 100644 (file)
@@ -10,6 +10,7 @@
 #include <common/items/_mod.qh>
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/triggers/trigger/jumppads.qh>
 
 .float speed;
index 5fb923799acfa41f863414a7ed96d33253874acd..c83d0f63c58dc2c4e3ebae76e9c50593ce85bd8c 100644 (file)
@@ -10,6 +10,7 @@
 #include "../../antilag.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 
 #include <lib/warpzone/common.qh>
 #include <lib/warpzone/util_server.qh>
index 554ef656b41dd15774f8966e004d600e1b3e13a3..da66ece3bb813fa6776d5c9ad183311ba63218af 100644 (file)
@@ -36,6 +36,7 @@
 #include "weapons/weaponsystem.qh"
 
 #include "../common/net_notice.qh"
+#include "../common/net_linked.qh"
 #include "../common/physics/player.qh"
 
 #include "../common/items/_mod.qh"
@@ -303,6 +304,8 @@ void PutObserverInServer(entity this)
        TRANSMUTE(Observer, this);
        this.iscreature = false;
        this.teleportable = TELEPORT_SIMPLE;
+       if(this.damagedbycontents)
+               IL_REMOVE(g_damagedbycontents, this);
        this.damagedbycontents = false;
        this.health = FRAGS_SPECTATOR;
        SetSpectatee_status(this, etof(this));
@@ -524,6 +527,8 @@ void PutClientInServer(entity this)
                this.wasplayer = true;
                this.iscreature = true;
                this.teleportable = TELEPORT_NORMAL;
+               if(!this.damagedbycontents)
+                       IL_PUSH(g_damagedbycontents, this);
                this.damagedbycontents = true;
                set_movetype(this, MOVETYPE_WALK);
                this.solid = SOLID_SLIDEBOX;
@@ -1272,6 +1277,8 @@ void ClientDisconnect(entity this)
        this.playerid = 0;
        ReadyCount();
        if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false);
+
+       ONREMOVE(this);
 }
 
 void ChatBubbleThink(entity this)
index 9380fc4cde280f0cd9fda57a24cd6bddbd41da56..5017e81aba03014d4d325c3ddbb56fe0b9e36e2e 100644 (file)
@@ -5,6 +5,7 @@
 #include "../race.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/mapinfo.qh>
 #include <common/util.qh>
 
index a329ac9965efe463b052d92a24ac64b6ccddea1a..cbc65680a0aed6dcf309bd88ebd5069c61f87b5e 100644 (file)
@@ -21,6 +21,7 @@
 #include "../mutators/_mod.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/mapinfo.qh>
 #include <common/notifications/all.qh>
 #include <common/teams.qh>
index 361f1284436f9f85520c4902d80dfae92ea58203..d1cdb7e59db5a2c766aeb76ef907c7a5a198f64b 100644 (file)
@@ -13,6 +13,7 @@
 #include "../mutators/_mod.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/mapinfo.qh>
 #include <common/notifications/all.qh>
 #include <common/playerstats.qh>
index 4574b23490f3147447772eb754d41f1b6a750d08..52153fcd7edeedaf2b7c3aec557103786fcca343 100644 (file)
@@ -465,3 +465,6 @@ STATIC_INIT(g_bot_targets) { g_bot_targets = IL_NEW(); }
 
 IntrusiveList g_bot_dodge;
 STATIC_INIT(g_bot_dodge) { g_bot_dodge = IL_NEW(); }
+
+IntrusiveList g_damagedbycontents;
+STATIC_INIT(g_damagedbycontents) { g_damagedbycontents = IL_NEW(); }
index 90266189b83c1adf5f4ea6f7db111c9780e3c24c..fd725ad35e8b128a3e78521e0d46913e64f6134e 100644 (file)
@@ -13,6 +13,7 @@
 #include "../common/vehicles/all.qh"
 #include "../common/constants.qh"
 #include "../common/util.qh"
+#include <common/net_linked.qh>
 #include <common/weapons/_all.qh>
 #include "../lib/warpzone/common.qh"
 #include "../lib/warpzone/server.qh"
@@ -398,6 +399,8 @@ void FireGrapplingHook(entity actor)
        missile.takedamage = DAMAGE_AIM;
        missile.damageforcescale = 0;
        missile.damagedbycontents = (autocvar_g_balance_grapplehook_damagedbycontents);
+       if(missile.damagedbycontents)
+               IL_PUSH(g_damagedbycontents, missile);
 
        missile.hook_start = missile.hook_end = missile.origin;
 
index 58fb26a4ed4a0acd1ed272252e3dbeac39bf7257..3ca062b78430e338f003d53f4f80b3496dbe42cb 100644 (file)
@@ -1,6 +1,7 @@
 #include "g_models.qh"
 
 #include "g_subs.qh"
+#include <common/net_linked.qh>
 #include "../common/triggers/subs.qh"
 #include "../common/triggers/triggers.qh"
 
index 48b587e5eb2de33312210f0eb139a3587cc6bc94..8edcf3b8f58f7b0010efffabd1279ab4c6d9ab9f 100644 (file)
@@ -19,6 +19,7 @@
 #include "teamplay.qh"
 #include "weapons/weaponstats.qh"
 #include "../common/constants.qh"
+#include <common/net_linked.qh>
 #include "../common/deathtypes/all.qh"
 #include "../common/mapinfo.qh"
 #include "../common/monsters/_mod.qh"
index 7c7c02018c2afb1f664cab59800734bdca75606b..2ea425692c1d5ead09c22889c91237190e8f1321 100644 (file)
@@ -4,6 +4,7 @@
 #include "command/cmd.qh"
 #include "command/getreplies.qh"
 #include "../common/constants.qh"
+#include <common/net_linked.qh>
 #include "../common/mapinfo.qh"
 #include "../common/playerstats.qh"
 #include "../common/util.qh"
index 4b3d404bf316907a579f6d246330d9f591b257c8..e90dbeb9669a81e00cc94cb6651094e015081c4d 100644 (file)
@@ -11,6 +11,7 @@
 #include "weapons/selection.qh"
 #include "../common/command/_mod.qh"
 #include "../common/constants.qh"
+#include <common/net_linked.qh>
 #include "../common/deathtypes/all.qh"
 #include "../common/mapinfo.qh"
 #include "../common/notifications/all.qh"
index 0a5b823fb5b6ac14f2c39690385ca77b338c4804..21c8ef9a5c114e92b0650f4ca5b6ec251a14d3a5 100644 (file)
@@ -541,7 +541,7 @@ MUTATOR_HOOKABLE(HelpMePing, EV_HelpMePing);
 
 /**
  * called when a vehicle initializes
- * return false to remove the vehicle
+ * return true to remove the vehicle
  */
 #define EV_VehicleInit(i, o) \
     /** vehicle */ i(entity, MUTATOR_ARGV_0_entity) \
index b032ab01949db9c6453da64da4d96058e9a926ce..1a1d7959fd2799b4e3908d3e13736b314106aced 100644 (file)
@@ -179,8 +179,6 @@ void assault_wall_think(entity this)
 
 // trigger new round
 // reset objectives, toggle spawnpoints, reset triggers, ...
-void vehicles_clearreturn(entity veh);
-void vehicles_spawn(entity this);
 void assault_new_round(entity this)
 {
        //bprint("ASSAULT: new round\n");
@@ -535,9 +533,7 @@ MUTATOR_HOOKFUNCTION(as, VehicleInit)
 {
        entity veh = M_ARGV(0, entity);
 
-       if(veh.active != ACTIVE_NOT)
-               veh.nextthink = time + 0.5;
-       return true;
+       veh.nextthink = time + 0.5;
 }
 
 MUTATOR_HOOKFUNCTION(as, HavocBot_ChooseRole)
index 0a3c622a9b0a3575f2d73c570e2866505362ec60..8120e1cb348a77e35e545eaa2c78733f41a2ea02 100644 (file)
@@ -1257,6 +1257,8 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        flag.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP;
        flag.damagedbytriggers = autocvar_g_ctf_flag_return_when_unreachable;
        flag.damagedbycontents = autocvar_g_ctf_flag_return_when_unreachable;
+       if(flag.damagedbycontents)
+               IL_PUSH(g_damagedbycontents, flag);
        flag.velocity = '0 0 0';
        flag.mangle = flag.angles;
        flag.reset = ctf_Reset;
index 9df628860318b2a005b4a755f5c8e4d6ad64c759..904447c218418c936f5f933cce7cf13062813c61 100644 (file)
@@ -62,6 +62,8 @@ void CopyBody(entity this, float keepvelocity)
        clone.iscreature = this.iscreature;
        clone.teleportable = this.teleportable;
        clone.damagedbycontents = this.damagedbycontents;
+       if(clone.damagedbycontents)
+               IL_PUSH(g_damagedbycontents, clone);
        clone.angles = this.angles;
        clone.v_angle = this.v_angle;
        clone.avelocity = this.avelocity;
@@ -212,6 +214,8 @@ void PlayerCorpseDamage(entity this, entity inflictor, entity attacker, float da
                this.alpha = -1;
                this.solid = SOLID_NOT; // restore later
                this.takedamage = DAMAGE_NO; // restore later
+               if(this.damagedbycontents)
+                       IL_REMOVE(g_damagedbycontents, this);
                this.damagedbycontents = false;
        }
 }
index 1000a5105ba25da7332711ae91b3b6c3d0323f3e..1a8ada45fe306f9156bf74e789acf51de830f1bf 100644 (file)
@@ -2,9 +2,9 @@
 
 #if XONOTIC
 #include <server/_all.inc>
-#endif
 
 #include <ecs/_mod.inc>
+#endif
 
 #ifdef BUILD_MOD
 #include <mod/server/progs.inc>
index 8fc38aa2c5e028ed1d44f8cd5f3b7128454ddda9..545fb2a85949a1317e8d8cac910101f79dd7f32c 100644 (file)
@@ -9,6 +9,7 @@
 #include "../common/deathtypes/all.qh"
 #include "../common/notifications/all.qh"
 #include "../common/mapinfo.qh"
+#include <common/net_linked.qh>
 #include "../common/triggers/subs.qh"
 #include "../lib/warpzone/util_server.qh"
 #include "../lib/warpzone/common.qh"
index 94bea2b44a662428e8259e36a0b08941f18e91d3..e6264b8693b4b360b7e8ad7c4a3b8f6c61a67e6c 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "command/common.qh"
 #include "mutators/_mod.qh"
+#include <common/net_linked.qh>
 #include "../common/playerstats.qh"
 #include "../common/teams.qh"
 
index 18d32c2f06369b05dd5be39db868aca414a10d44..517bc1892ca8541c77f8b35d4bb9c969c6d6cd7a 100644 (file)
@@ -4,6 +4,7 @@
 #include "g_world.qh"
 #include "race.qh"
 #include "../common/constants.qh"
+#include <common/net_linked.qh>
 #include "../common/teams.qh"
 #include "../common/triggers/subs.qh"
 #include "../common/util.qh"
index ea11ea36a613f25ffb8c3f9915c8fa3dbf9c58f0..0c36a77c5b7689665d101e1d676efe67af567e21 100644 (file)
@@ -117,7 +117,8 @@ void CreatureFrame_FallDamage(entity this)
 
 void CreatureFrame_All()
 {
-       FOREACH_ENTITY_FLOAT(damagedbycontents, true, {
+       IL_EACH(g_damagedbycontents, it.damagedbycontents,
+       {
                if (it.move_movetype == MOVETYPE_NOCLIP) continue;
                CreatureFrame_Liquids(it);
                CreatureFrame_FallDamage(it);
@@ -402,8 +403,8 @@ LABEL(cvar_fail)
 void WarpZone_PostInitialize_Callback()
 {
        // create waypoint links for warpzones
-       entity e;
-       for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
+       //for(entity e = warpzone_first; e; e = e.warpzone_next)
+       for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); )
        {
                vector src, dst;
                src = (e.absmin + e.absmax) * 0.5;
index ed9006bb25eb493e2af8b5bfdb2dde217c5d0e70..7cc06da3e6dc05b32595b85556ff43d4ecb11225 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "../mutators/_mod.qh"
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/teams.qh>
 #include <common/util.qh>
 #include <common/weapons/_all.qh>
index 03031c1580ac20a1ea3765190e4a58feda89c88a..6d163755067def2224a973db9bc311f1dcb60770 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <common/t_items.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/deathtypes/all.qh>
 #include <common/notifications/all.qh>
 #include <common/util.qh>
index a8a893e217700750b4364106ba7fd6065ac3ae8f..9fcfd34c205b712ee1ff716693cd18415a860dbc 100644 (file)
@@ -5,6 +5,7 @@
 #include "../command/common.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/weapons/_all.qh>
 
 .float csqcprojectile_type;
index 56df6c3a2c47e615562c1bd190eba45241536c3f..539371a53cbe9c94b87e388deac95b290d1850cd 100644 (file)
@@ -3,6 +3,7 @@
 #include "weaponsystem.qh"
 #include <common/t_items.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/util.qh>
 #include <common/items/item.qh>
 #include <common/weapons/_all.qh>
index 3b7aa7bf893f7871bad4c5a2f54502c2a81aae8a..b49ed88f596ca00a7ef4e6b3467b7e5a3f36c2e2 100644 (file)
@@ -10,6 +10,7 @@
 #include "../antilag.qh"
 
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/util.qh>
 
 #include <common/weapons/_all.qh>
index 4968d3c31f4d2f813ac5cdddde94f167ec2b52e4..c0d302e2232123e9e3c049eed1965f27d750cf7b 100644 (file)
@@ -8,6 +8,7 @@
 #include <common/t_items.qh>
 #include <common/animdecide.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/monsters/_mod.qh>
 #include <common/notifications/all.qh>
 #include <common/util.qh>