]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Lyberta/GiveResourceWithLimit
authorLyberta <lyberta@lyberta.net>
Sat, 31 Mar 2018 05:29:03 +0000 (08:29 +0300)
committerLyberta <lyberta@lyberta.net>
Sat, 31 Mar 2018 05:29:03 +0000 (08:29 +0300)
27 files changed:
.gitlab-ci.yml
cmake/qcc.sh
qcsrc/client/mutators/events.qh
qcsrc/common/debug.qh
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/mutators/mutator/instagib/_mod.qh
qcsrc/common/mutators/mutator/instagib/sv_items.qc
qcsrc/common/mutators/mutator/instagib/sv_items.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/kick_teamkiller/_mod.qh
qcsrc/common/mutators/mutator/kick_teamkiller/sv_kick_teamkiller.qc
qcsrc/common/mutators/mutator/kick_teamkiller/sv_kick_teamkiller.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/offhand_blaster/_mod.qh
qcsrc/common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qc
qcsrc/common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qh [new file with mode: 0644]
qcsrc/common/t_items.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/lib/math.qh
qcsrc/lib/oo.qh
qcsrc/menu/mutators/events.qh
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/navigation.qc
qcsrc/server/g_damage.qc
qcsrc/server/mutators/events.qh
qcsrc/tools/qcc.sh

index 43e3df8554298cf6b6cb19e00bf0e6a1735eb503..4754425bf971689d6df0aaf9cfdad7f13dcd7595 100644 (file)
@@ -29,7 +29,7 @@ test_sv_game:
     - wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
     - wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
     - make
-    - EXPECT=422d5d8a0490e961463fda69da1975bc
+    - EXPECT=fb771b180a47f7acf09eb12dddd391f8
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index b7c77fd563a35a24ca2b4c1c1b5a4319861b5d52..78119a59615bf0dfdabf5473c4f374ce76519bda 100755 (executable)
@@ -3,7 +3,7 @@ CPP=${CPP:-cpp}
 QCC=${QCC:-$PWD/../../gmqcc/gmqcc${CMAKE_EXECUTABLE_SUFFIX}}
 case $1 in
     compile)
-        ${CPP} ${@:3} | sed 's/^#\(line\)\? \([[:digit:]]\+\) "\(.*\)".*/\n#pragma file(\3)\n#pragma line(\2)/g' > $2
+        ${CPP} ${@:3} | sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' > $2
     ;;
     link)
         ${QCC} \
index 24d634ce8213e05759f7afed13f2f0b011be5146..5edb84ae0ee7fc42245871e32c1752d02939493b 100644 (file)
@@ -2,6 +2,11 @@
 
 #include <common/mutators/base.qh>
 
+// register all possible hooks here
+// to use a hook, first register your mutator using REGISTER_MUTATOR
+// then create your function using MUTATOR_HOOKFUNCTION
+
 /**
  * Called when a client command is parsed
  * NOTE: hooks MUST start with if (MUTATOR_RETURNVALUE) return false;
index 7144bf3da5ed6bb4166c3cc5b3f8f4895d416a7f..936f1e028857e121d97fcdc985af76011bde90e3 100644 (file)
@@ -459,13 +459,13 @@ NET_HANDLE(debug_text_3d, bool is_new) {
 #define debug_text_3d_5(pos, msg, align, dur, vel) debug_text_3d_fn(pos, msg, align, dur, vel)
 
 ERASEABLE
-void debug_text_3d_fn(vector pos, string msg, float align, float duration, vector velocity) {
+void debug_text_3d_fn(vector pos, string msg, float align, float duration, vector vel) {
        WriteHeader(MSG_BROADCAST, debug_text_3d);
        WriteVector(MSG_BROADCAST, pos);
        WriteString(MSG_BROADCAST, msg);
        WriteFloat(MSG_BROADCAST, align);
        WriteFloat(MSG_BROADCAST, duration);
-       WriteVector(MSG_BROADCAST, velocity);
+       WriteVector(MSG_BROADCAST, vel);
 }
 
 #endif // SVQC
index beab98f0ac157a65f65a42898180f8226d4d9033..82b7d273c23458fb9f333e7bf090c5949f99a453 100644 (file)
@@ -118,7 +118,7 @@ void M_Mage_Attack_Spike_Explode(entity this, entity directhitentity)
        this.realowner.mage_spike = NULL;
 
        Send_Effect(EFFECT_EXPLOSION_SMALL, this.origin, '0 0 0', 1);
-       RadiusDamage (this, this.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius), 
+       RadiusDamage (this, this.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius),
                                                NULL, NULL, 0, DEATH_MONSTER_MAGE.m_id, DMG_NOWEP, directhitentity);
 
        delete(this);
@@ -272,7 +272,7 @@ void M_Mage_Defend_Heal(entity this)
 void M_Mage_Attack_Push(entity this)
 {
        sound(this, CH_SHOTS, SND_TAGEXP1, 1, ATTEN_NORM);
-       RadiusDamage (this, this, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius), 
+       RadiusDamage (this, this, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius),
                                                NULL, NULL, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE.m_id, DMG_NOWEP, this.enemy);
        Send_Effect(EFFECT_TE_EXPLOSION, this.origin, '0 0 0', 1);
 
index d596d7d33bf29cda76bc76d72cf855a75d70bc88..0a52e61090e553a140817abc3536a9429a0fd425 100644 (file)
@@ -71,7 +71,7 @@ void M_Wyvern_Attack_Fireball_Explode(entity this)
 
        entity own = this.realowner;
 
-       RadiusDamage(this, own, autocvar_g_monster_wyvern_attack_fireball_damage, autocvar_g_monster_wyvern_attack_fireball_edgedamage, autocvar_g_monster_wyvern_attack_fireball_force, 
+       RadiusDamage(this, own, autocvar_g_monster_wyvern_attack_fireball_damage, autocvar_g_monster_wyvern_attack_fireball_edgedamage, autocvar_g_monster_wyvern_attack_fireball_force,
                                                NULL, NULL, autocvar_g_monster_wyvern_attack_fireball_radius, this.projectiledeathtype, DMG_NOWEP, NULL);
 
        FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_monster_wyvern_attack_fireball_radius, it.takedamage == DAMAGE_AIM,
index 7097eaf390dac022c2840f7db4d9dc6ee7028368..9989d8e3f3313193763276e3652ea16ed013c6e2 100644 (file)
@@ -1,5 +1,8 @@
 // generated file; do not modify
 #include <common/mutators/mutator/instagib/items.qh>
+#ifdef SVQC
+    #include <common/mutators/mutator/instagib/sv_items.qh>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/instagib/sv_instagib.qh>
 #endif
index ffd9bfb0ca1fd2c7ac37b5fc72e55249a233da1d..5c0d29dd321327c73ba6452bee95598065e3a3c1 100644 (file)
@@ -1,3 +1,5 @@
+#include "sv_items.qh"
+
 #include "items.qh"
 
 /// \brief Time of ivisibility powerup in seconds.
diff --git a/qcsrc/common/mutators/mutator/instagib/sv_items.qh b/qcsrc/common/mutators/mutator/instagib/sv_items.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index 98fb4815c1ce28cc699a429537ea75c2643b4487..0144c3147c85433ceb1d005e7188a83b62c9208b 100644 (file)
@@ -1 +1,4 @@
 // generated file; do not modify
+#ifdef SVQC
+    #include <common/mutators/mutator/kick_teamkiller/sv_kick_teamkiller.qh>
+#endif
index a3b028f1c6c0c9573b8eb7b10765a34a4db9b71c..d91546af5711fcfa9b9848202cc7c775c3aca151 100644 (file)
@@ -1,3 +1,4 @@
+#include "sv_kick_teamkiller.qh"
 
 float autocvar_g_kick_teamkiller_rate;
 float autocvar_g_kick_teamkiller_lower_limit;
@@ -24,7 +25,7 @@ MUTATOR_HOOKFUNCTION(kick_teamkiller, PlayerDies)
        // use the players actual playtime
        float playtime = time - CS(attacker).startplaytime;
        // rate is in teamkills/minutes, playtime in seconds
-       if (teamkills >= autocvar_g_kick_teamkiller_lower_limit && 
+       if (teamkills >= autocvar_g_kick_teamkiller_lower_limit &&
            teamkills >= autocvar_g_kick_teamkiller_rate*playtime/60.0)
        {
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_TEAMKILL, attacker.netname);
diff --git a/qcsrc/common/mutators/mutator/kick_teamkiller/sv_kick_teamkiller.qh b/qcsrc/common/mutators/mutator/kick_teamkiller/sv_kick_teamkiller.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index 98fb4815c1ce28cc699a429537ea75c2643b4487..5e11096a532644d671eb7bd409b0519e08d3c3bd 100644 (file)
@@ -1 +1,4 @@
 // generated file; do not modify
+#ifdef SVQC
+    #include <common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qh>
+#endif
index b25175aea5ad9055355fd508b0ba238fad97673a..3a10055fe5419e0f52c855f91edb0066ba170718 100644 (file)
@@ -1,3 +1,5 @@
+#include "sv_offhand_blaster.qh"
+
 string autocvar_g_offhand_blaster = "0";
 
 REGISTER_MUTATOR(offhand_blaster, expr_evaluate(autocvar_g_offhand_blaster));
diff --git a/qcsrc/common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qh b/qcsrc/common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index 249615d2d392b8b5fe828e531c11586921ca3737..02a0dc171cc34723e95e7671fde5504b80da47e0 100644 (file)
@@ -663,8 +663,6 @@ void Item_ScheduleRespawn(entity e)
 AUTOCVAR(g_pickup_respawntime_initial_random, int, 1,
        "For items that don't start spawned: 0: spawn after their normal respawntime; 1: spawn after `random * respawntime` with the *same* random; 2: same as 1 but each item has separate random");
 
-float shared_random;
-STATIC_INIT(shared_random) { shared_random = random(); }
 void Item_ScheduleInitialRespawn(entity e)
 {
        Item_Show(e, 0);
@@ -675,18 +673,26 @@ void Item_ScheduleInitialRespawn(entity e)
                // range: respawntime .. respawntime + respawntimejitter
                spawn_in = e.respawntime + random() * e.respawntimejitter;
        }
-       else if (autocvar_g_pickup_respawntime_initial_random == 1)
+       else
        {
+               float rnd;
+               if (autocvar_g_pickup_respawntime_initial_random == 1)
+               {
+                       static float shared_random = 0;
+                       // NOTE this code works only if items are scheduled at the same time (normal case)
+                       // NOTE2 random() can't return exactly 1 so this check always work as intended
+                       if (!shared_random || floor(time) > shared_random)
+                               shared_random = floor(time) + random();
+                       rnd = shared_random - floor(time);
+               }
+               else
+                       rnd = random();
+
                // range:
                // if respawntime >= ITEM_RESPAWN_TICKS: ITEM_RESPAWN_TICKS .. respawntime + respawntimejitter
                // else: 0 .. ITEM_RESPAWN_TICKS
                // this is to prevent powerups spawning unexpectedly without waypoints
-               spawn_in = ITEM_RESPAWN_TICKS + shared_random * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
-       }
-       else
-       {
-               // range: same as 1
-               spawn_in = ITEM_RESPAWN_TICKS + random() * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
+               spawn_in = ITEM_RESPAWN_TICKS + rnd * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
        }
 
        Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : spawn_in));
index 2710768668bdf525eab03fede68542cb530b061f..5a41666bdb74ba1a58b4a09eae9adf341e2a7d8a 100644 (file)
@@ -247,7 +247,7 @@ void W_Crylink_Touch(entity this, entity toucher)
        if(a)
                f *= a;
 
-       float totaldamage = RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius), 
+       float totaldamage = RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius),
                                                                                NULL, NULL, WEP_CVAR_BOTH(crylink, isprimary, force) * f, this.projectiledeathtype, this.weaponentity_fld, toucher);
 
        if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(this, WEP_CVAR_BOTH(crylink, isprimary, radius)))))
index 49ad1c7394cc7e99d7b70cfc6b47e2b8c3477382..8f501653869caad8908a2723ad435dbfd70ff243 100644 (file)
@@ -12,7 +12,7 @@ void W_HLAC_Touch(entity this, entity toucher)
 
        isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
 
-       RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius), 
+       RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius),
                                                NULL, NULL, WEP_CVAR_BOTH(hlac, isprimary, force), this.projectiledeathtype, this.weaponentity_fld, toucher);
 
        delete(this);
index 25bad729fded903ae27d5b5ee86bd2faaaa997e5..d8075c9fe4d167cf127b4411252bb7cdd75f58db 100644 (file)
@@ -96,7 +96,7 @@ void W_MineLayer_DoRemoteExplode(entity this)
        if(this.move_movetype == MOVETYPE_NONE || this.move_movetype == MOVETYPE_FOLLOW)
                this.velocity = this.mine_orientation; // particle fx and decals need .velocity
 
-       RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius), 
+       RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius),
                                                NULL, NULL, WEP_CVAR(minelayer, remote_force), this.projectiledeathtype | HITTYPE_BOUNCE, this.weaponentity_fld, NULL);
 
        .entity weaponentity = this.weaponentity_fld;
index f20b1c66e5bf120be7748737dabe8b9e8dec9f88..d8f19906a3eb26b1d9003e74f4493450f4b018d8 100644 (file)
@@ -324,9 +324,9 @@ vector solve_quadratic(float a, float b, float c)
 }
 
 /// Maps values between the src and dest range: src_min to dest_min, src_max to dest_max, values between them
-/// to the curresponding values between and extrapolates for values outside the range.
+/// to the corresponding values between and extrapolates for values outside the range.
 ///
-/// src_min and src_max must not be the same or division by zero accurs.
+/// src_min and src_max must not be the same or division by zero occurs.
 ///
 /// dest_max can be smaller than dest_min if you want the resulting range to be inverted, all values can be negative.
 ERASEABLE
index f57bf8e909c4e7d1a594a0e36f2415b715483fda..bd1d34666be57589a5f8c54e4581e325c52dbe65 100644 (file)
@@ -237,7 +237,7 @@ STATIC_INIT(RegisterClasses)
 
 #define ATTRIB(...) EVAL_ATTRIB(OVERLOAD_(ATTRIB, __VA_ARGS__))
 #define EVAL_ATTRIB(...) __VA_ARGS__
-#define ATTRIB_3(cname, name, type) INIT(cname) {} class(cname) .type name
+#define ATTRIB_3(cname, name, type) class(cname) .type name
 #define ATTRIB_4(cname, name, type, val) \
        ATTRIB_3(cname, name, type); \
        INIT(cname) \
index 1df38f5af09c571df07e280b3c9691ec192f837b..0c5056b974673ce76b32958be25a4cb5e319611f 100644 (file)
@@ -2,6 +2,11 @@
 
 #include <common/mutators/base.qh>
 
+// register all possible hooks here
+// to use a hook, first register your mutator using REGISTER_MUTATOR
+// then create your function using MUTATOR_HOOKFUNCTION
+
 // globals
 
 string cmd_name;
index 2a0d0c8503f005c17d2156fd2871ebf216ac932d..7ce6efa45fc63af8e3bd50991b1bdac3dcf1336c 100644 (file)
@@ -885,17 +885,17 @@ void havocbot_movetogoal(entity this)
 
        diff = destorg - this.origin;
 
-       if (fabs(diff.x) < 10 && fabs(diff.y) < 10
-               && this.goalcurrent == this.goalentity && time < this.goalentity_lock_timeout)
+       // 1. stop if too close to target player (even if frozen)
+       // 2. stop if the locked goal has been reached
+       if ((IS_PLAYER(this.goalcurrent) && vdist(diff, <, 80))
+               || (this.goalcurrent == this.goalentity && time < this.goalentity_lock_timeout && vdist(diff, <, 10)))
        {
                destorg = this.origin;
-               diff.x = 0;
-               diff.y = 0;
+               diff = '0 0 0';
        }
 
        dir = normalize(diff);
-       flatdir = diff;flatdir.z = 0;
-       flatdir = normalize(flatdir);
+       flatdir = (diff.z == 0) ? dir : normalize(vec2(diff));
 
        //if (this.bot_dodgevector_time < time)
        {
index 7b80a1a6f27cfd790fb59f325f8eda9404dfbcf9..c79ed40a4304cac996f80b84b2917d94ec44ee0e 100644 (file)
@@ -1573,7 +1573,7 @@ void navigation_shortenpath(entity this)
                if (trace_ent == this || tracewalk(this, this.origin, this.mins, this.maxs,
                        tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
                {
-                       LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue"); 
+                       LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
                        navigation_poproute(this);
                }
        }
index 3fb000e708072a5af331a984f1d0563ef5afac99..b5ab77d419e02db58a9ac07cbc744bf998d84999 100644 (file)
@@ -907,7 +907,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
        }
 }
 
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, 
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
                                                                float inflictorselfdamage, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
        // Returns total damage applies to creatures
 {
index a93c7687856ee9ea899d6995f6e5c0e6c0b98eef..b781db24f4629860f28ac0cdc82bf40e1ec3bb58 100644 (file)
@@ -3,6 +3,9 @@
 #include <common/mutators/base.qh>
 
 // register all possible hooks here
+// to use a hook, first register your mutator using REGISTER_MUTATOR
+// then create your function using MUTATOR_HOOKFUNCTION
 
 /** called when a player becomes observer, after shared setup */
 #define EV_MakePlayerObserver(i, o) \
index 15cbfc4aab5a222f8a06da9091884057c5f84fe3..865e6e592ca48c037932fa643ec80e9dd1b20f83 100755 (executable)
@@ -32,7 +32,7 @@ function qpp() {
     err=$?
     set -e
     if [ ${err} -ne 0 ]; then return ${err}; fi
-    sed 's/^#\(line\)\? \([[:digit:]]\+\) "\(.*\)".*/\n#pragma file(\3)\n#pragma line(\2)/g' "${WORKDIR}/${MODE}.txt"
+    sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' "${WORKDIR}/${MODE}.txt"
 }
 
 function qcc() {