]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Lyberta/TeamplayOverhaul
authorLyberta <lyberta@lyberta.net>
Wed, 4 Apr 2018 16:44:14 +0000 (19:44 +0300)
committerLyberta <lyberta@lyberta.net>
Wed, 4 Apr 2018 16:44:14 +0000 (19:44 +0300)
55 files changed:
bal-wep-mario.cfg
bal-wep-nexuiz25.cfg
bal-wep-overkill.cfg
bal-wep-samual.cfg
bal-wep-xdf.cfg
bal-wep-xonotic.cfg
bal-wep-xpm.cfg
cmake/qcc.sh
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/mutators/events.qh
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/debug.qh
qcsrc/common/items/item.qh
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/monsters/sv_monsters.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/melee_only/sv_melee_only.qc
qcsrc/common/mutators/mutator/nix/sv_nix.qc
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/mutators/mutator/random_items/sv_random_items.qc
qcsrc/common/mutators/mutator/random_items/sv_random_items.qh
qcsrc/common/notifications/all.qh
qcsrc/common/physics/player.qh
qcsrc/common/t_items.qc
qcsrc/common/turrets/turret/plasma_dual.qh
qcsrc/common/viewloc.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/common/weapons/weapon/vaporizer.qh
qcsrc/lib/math.qh
qcsrc/lib/oo.qh
qcsrc/lib/registry.qh
qcsrc/menu/mutators/events.qh
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/navigation.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/items.qc
qcsrc/server/items.qh
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_assault.qc
qcsrc/server/mutators/mutator/gamemode_invasion.qc
qcsrc/server/mutators/mutator/gamemode_lms.qc
qcsrc/server/weapons/spawning.qc
qcsrc/tools/qcc.sh

index 57d5d745df29da9d5b3dfc3cd8f0a7611bbeeeb5..4c0eebfaec10477bb9453657b376beb88efa0376 100644 (file)
@@ -436,6 +436,7 @@ set g_balance_porto_weaponthrowable 1
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
 set g_balance_vaporizer_primary_refire 1
 set g_balance_vaporizer_reload_ammo 0
 set g_balance_vaporizer_reload_time 0
index f7d912ca773649743831610ab52209ee3704dee3..f10275919ea0e7b31fe5378fbaedb7b549775b04 100644 (file)
@@ -436,6 +436,7 @@ set g_balance_porto_weaponthrowable 1
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage -1
+set g_balance_vaporizer_primary_force 800
 set g_balance_vaporizer_primary_refire 1
 set g_balance_vaporizer_reload_ammo 0
 set g_balance_vaporizer_reload_time 0
index 9cfffed10b02114e478653d4ea7ea117ad744c0e..317c8a9f8a870f65ad07a3221f7d4a6a63cc7ec9 100644 (file)
@@ -436,6 +436,7 @@ set g_balance_porto_weaponthrowable 1
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
 set g_balance_vaporizer_primary_refire 1
 set g_balance_vaporizer_reload_ammo 0
 set g_balance_vaporizer_reload_time 0
index b3ec457a8af5ae1f8b4a62c3656d146d3af33fda..295756779b58dc5875e3ae8cb685c1264441e5cb 100644 (file)
@@ -502,6 +502,7 @@ set g_balance_porto_weaponthrowable 1
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
 set g_balance_vaporizer_primary_refire 1
 set g_balance_vaporizer_reload_ammo 0
 set g_balance_vaporizer_reload_time 0
index cc8936c3381c9a3a0f1c1eb055071a558525227c..fc9a1ddf83775c9144a93251589083a022c96363 100644 (file)
@@ -436,6 +436,7 @@ set g_balance_porto_weaponthrowable 1
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
 set g_balance_vaporizer_primary_refire 1
 set g_balance_vaporizer_reload_ammo 0
 set g_balance_vaporizer_reload_time 0
index 6d81b309f0821d3f2cfce7633c2b6a725d28a3c6..9048f383d739951b288bcf314a6c744d06a26eb6 100644 (file)
@@ -436,6 +436,7 @@ set g_balance_porto_weaponthrowable 1
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
 set g_balance_vaporizer_primary_refire 1
 set g_balance_vaporizer_reload_ammo 0
 set g_balance_vaporizer_reload_time 0
index ac5be34f3783b822759d7b26922629c1adedd52b..2a391a202dd703a1e9eb6c66607037769a728f91 100644 (file)
@@ -436,6 +436,7 @@ set g_balance_porto_weaponthrowable 1
 set g_balance_vaporizer_primary_ammo 10
 set g_balance_vaporizer_primary_animtime 0.3
 set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
 set g_balance_vaporizer_primary_refire 1
 set g_balance_vaporizer_reload_ammo 0
 set g_balance_vaporizer_reload_time 0
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 cebd8f5d65c162b6e3d15d90a5e7a496bbbc0858..70c4c10131303153faad8ec0fc2bfacb0474265b 100644 (file)
@@ -30,7 +30,7 @@ int weaponorder_cmp(int i, int j, entity pass)
        int nHidden = 0; \
        FOREACH(Weapons, it != WEP_Null, { \
                if (weapons_stat & WepSet_FromWeapon(it)) continue; \
-               if (it.spawnflags & WEP_FLAG_HIDDEN || it.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1; \
+               if ((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) nHidden += 1; \
        }); \
        vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, panel_size, aspect); \
        columns = table_size.x; \
@@ -407,7 +407,7 @@ void HUD_Weapons()
                }
                else
                {
-                       if (it.spawnflags & WEP_FLAG_MUTATORBLOCKED && !(weapons_stat & WepSet_FromWeapon(it)))
+                       if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) && !(weapons_stat & WepSet_FromWeapon(it)))
                                continue;
                }
 
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 836c3983ccb0581703d2ff9a0de2df119a28a5c8..7c5a218b21f15e34ba6ba43ee0d13b4a2b0a801f 100644 (file)
@@ -56,7 +56,7 @@
        CSQCMODEL_ENDIF \
        CSQCMODEL_PROPERTY(BIT(10), float, ReadAngle, WriteAngle, v_angle_x) \
        CSQCMODEL_PROPERTY(BIT(11), int, ReadByte, WriteByte, traileffect) \
-       CSQCMODEL_PROPERTY_SCALED(BIT(12), float, ReadByte, WriteByte, scale, 16, 0, 255) \
+       CSQCMODEL_PROPERTY(BIT(12), float, ReadCoord, WriteCoord, scale) \
        CSQCMODEL_PROPERTY(BIT(13), int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
        CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
        CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, multijump_count) \
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 b7fc933e8b5dbaf35dde8a37fca1762c51a4e08a..e59152076b754552eb266411710fdbab1e4efcbb 100644 (file)
@@ -7,6 +7,10 @@
 #include <common/stats.qh>
 #endif
 
+#ifdef SVQC
+#include <server/items.qh>
+#endif
+
 const int IT_UNLIMITED_WEAPON_AMMO             =  BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
 const int IT_UNLIMITED_SUPERWEAPONS            =  BIT(1); // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
 
@@ -48,7 +52,16 @@ const int IT_PICKUPMASK                      = IT_UNLIMITED_AMMO | IT_JETPACK | IT_FU
 .float  invincible_finished = _STAT(INVINCIBLE_FINISHED);
 
 #define SPAWNFUNC_ITEM(name, item) \
-    spawnfunc(name) { StartItem(this, item); }
+    spawnfunc(name) \
+       { \
+               if (!Item_IsDefinitionAllowed(item)) \
+               { \
+                       startitem_failed = true; \
+                       delete(this); \
+                       return; \
+               } \
+               StartItem(this, item); \
+       }
 
 #else
 
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 1197c261346eae99235f85e5c33580a0f5835f04..bf019b9cf1771e1a2c1450b00c0a44b015b0c664 100644 (file)
@@ -82,6 +82,7 @@ bool Monster_ValidTarget(entity this, entity targ)
        || (IS_VEHICLE(targ) && !((Monsters_from(this.monsterid)).spawnflags & MON_FLAG_RANGED)) // melee vs vehicle is useless
        || (time < game_starttime) // monsters do nothing before match has started
        || (targ.takedamage == DAMAGE_NO)
+       || (game_stopped)
        || (targ.items & IT_INVISIBILITY)
        || (IS_SPEC(targ) || IS_OBSERVER(targ)) // don't attack spectators
        || (!IS_VEHICLE(targ) && (IS_DEAD(targ) || IS_DEAD(this) || targ.health <= 0 || this.health <= 0))
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 d6796fc0590e0581be335989330a384934bee600..5603dd4901c0601cc8940320acbc1f87b6ab1f3e 100644 (file)
@@ -25,11 +25,11 @@ MUTATOR_HOOKFUNCTION(melee_only, ForbidThrowCurrentWeapon)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(melee_only, FilterItem)
+MUTATOR_HOOKFUNCTION(melee_only, FilterItemDefinition)
 {
-       entity item = M_ARGV(0, entity);
+       entity definition = M_ARGV(0, entity);
 
-       switch (item.itemdef)
+       switch (definition)
        {
                case ITEM_HealthSmall:
                case ITEM_ArmorSmall:
index c174b530f0a48e94cb20d6661fd069ecb0e2ecc4..953321cc0ba5a708bb30d73e0e218b8e4ad67cf0 100644 (file)
@@ -244,15 +244,15 @@ MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ", NIX");
 }
 
-MUTATOR_HOOKFUNCTION(nix, FilterItem)
+MUTATOR_HOOKFUNCTION(nix, FilterItemDefinition)
 {
-       entity item = M_ARGV(0, entity);
+       entity definition = M_ARGV(0, entity);
 
-       if(item.itemdef.instanceOfHealth || item.itemdef.instanceOfArmor)
+       if (definition.instanceOfHealth || definition.instanceOfArmor)
        {
                return !autocvar_g_nix_with_healtharmor;
        }
-       else if(item.itemdef.instanceOfPowerup)
+       else if (definition.instanceOfPowerup)
        {
                return !autocvar_g_nix_with_powerups;
        }
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 3d305746269e1a29cbfb718ceb536175d04693af..553dcf582ffccbd27d2ff23adc95e238d49bcb5d 100644 (file)
@@ -7,15 +7,6 @@
 
 //============================ Constants ======================================
 
-enum
-{
-       RANDOM_ITEM_TYPE_HEALTH = 1,
-       RANDOM_ITEM_TYPE_ARMOR,
-       RANDOM_ITEM_TYPE_RESOURCE,
-       RANDOM_ITEM_TYPE_WEAPON,
-       RANDOM_ITEM_TYPE_POWERUP
-};
-
 //======================= Global variables ====================================
 
 // Replace cvars
@@ -72,99 +63,137 @@ string RandomItems_GetRandomItemClassName(string prefix)
        {
                return RandomItems_GetRandomOverkillItemClassName(prefix);
        }
-       return RandomItems_GetRandomVanillaItemClassName(prefix);
+       return RandomItems_GetRandomVanillaItemClassName(prefix,
+               RANDOM_ITEM_TYPE_ALL);
 }
 
-string RandomItems_GetRandomVanillaItemClassName(string prefix)
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types)
 {
-       RandomSelection_Init();
-       string cvar_name = sprintf("g_%s_health_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_armor_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
+       if (types == 0)
        {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_resource_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_weapon_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_powerup_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+               return "";
        }
-       int item_type = RandomSelection_chosen_float;
-       switch (item_type)
+       while (types != 0)
        {
-               case RANDOM_ITEM_TYPE_HEALTH:
+               string cvar_name;
+               RandomSelection_Init();
+               if (types & RANDOM_ITEM_TYPE_HEALTH)
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfHealth);
+                       cvar_name = sprintf("g_%s_health_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH,
+                                       cvar(cvar_name), 1);
+                       }
                }
-               case RANDOM_ITEM_TYPE_ARMOR:
+               if (types & RANDOM_ITEM_TYPE_ARMOR)
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfArmor);
+                       cvar_name = sprintf("g_%s_armor_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR,
+                                       cvar(cvar_name), 1);
+                       }
                }
-               case RANDOM_ITEM_TYPE_RESOURCE:
+               if (types & RANDOM_ITEM_TYPE_RESOURCE)
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfAmmo);
+                       cvar_name = sprintf("g_%s_resource_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE,
+                                       cvar(cvar_name), 1);
+                       }
+               }
+               if (types & RANDOM_ITEM_TYPE_WEAPON)
+               {
+                       cvar_name = sprintf("g_%s_weapon_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
+                       }
+               }
+               if (types & RANDOM_ITEM_TYPE_POWERUP)
+               {
+                       cvar_name = sprintf("g_%s_powerup_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+                       }
                }
-               case RANDOM_ITEM_TYPE_WEAPON:
+               int item_type = RandomSelection_chosen_float;
+               string class_name = "";
+               switch (item_type)
                {
-                       RandomSelection_Init();
-                       FOREACH(Weapons, it != WEP_Null &&
-                               !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
+                       case RANDOM_ITEM_TYPE_HEALTH:
+                       {
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfHealth);
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_ARMOR:
+                       {
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfArmor);
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_RESOURCE:
                        {
-                               cvar_name = sprintf("g_%s_%s_probability", prefix,
-                                       it.m_canonical_spawnfunc);
-                               if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfAmmo);
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_WEAPON:
+                       {
+                               RandomSelection_Init();
+                               FOREACH(Weapons, it != WEP_Null &&
+                                       !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
                                {
-                                       LOG_WARNF("Random items: cvar %s doesn't exist.",
-                                               cvar_name);
-                                       continue;
-                               }
-                               RandomSelection_AddString(it.m_canonical_spawnfunc,
-                                       cvar(cvar_name), 1);
-                       });
-                       return RandomSelection_chosen_string;
+                                       cvar_name = sprintf("g_%s_%s_probability", prefix,
+                                               it.m_canonical_spawnfunc);
+                                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                                       {
+                                               LOG_WARNF("Random items: cvar %s doesn't exist.",
+                                                       cvar_name);
+                                               continue;
+                                       }
+                                       RandomSelection_AddString(it.m_canonical_spawnfunc,
+                                               cvar(cvar_name), 1);
+                               });
+                               class_name = RandomSelection_chosen_string;
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_POWERUP:
+                       {
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfPowerup);
+                               break;
+                       }
                }
-               case RANDOM_ITEM_TYPE_POWERUP:
+               if (class_name != "")
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfPowerup);
+                       return class_name;
                }
+               types &= ~item_type;
        }
        return "";
 }
@@ -172,7 +201,8 @@ string RandomItems_GetRandomVanillaItemClassName(string prefix)
 string RandomItems_GetRandomInstagibItemClassName(string prefix)
 {
        RandomSelection_Init();
-       FOREACH(Items, it.spawnflags & ITEM_FLAG_INSTAGIB,
+       FOREACH(Items, it.spawnflags & ITEM_FLAG_INSTAGIB &&
+               Item_IsDefinitionAllowed(it),
        {
                string cvar_name = sprintf("g_%s_%s_probability", prefix,
                        it.m_canonical_spawnfunc);
@@ -190,7 +220,8 @@ string RandomItems_GetRandomOverkillItemClassName(string prefix)
 {
        RandomSelection_Init();
        FOREACH(Items, (it.spawnflags & ITEM_FLAG_OVERKILL) &&
-               !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED),
+               !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED) &&
+               Item_IsDefinitionAllowed(it),
        {
                string cvar_name = sprintf("g_%s_overkill_%s_probability", prefix,
                        it.m_canonical_spawnfunc);
@@ -242,7 +273,8 @@ string RandomItems_GetRandomItemClassNameWithProperty(string prefix,
        .bool item_property)
 {
        RandomSelection_Init();
-       FOREACH(Items, it.item_property && (it.spawnflags & ITEM_FLAG_NORMAL),
+       FOREACH(Items, it.item_property && (it.spawnflags & ITEM_FLAG_NORMAL) &&
+               Item_IsDefinitionAllowed(it),
        {
                string cvar_name = sprintf("g_%s_%s_probability", prefix,
                        it.m_canonical_spawnfunc);
index c9b4dbb9011ca91cd905d0c7221e3f089f4745b0..9ac738ca68ede11020c348c1a681d0b65a0eb7ca 100644 (file)
@@ -7,6 +7,16 @@
 
 bool autocvar_g_random_items; ///< Whether to enable random items.
 
+enum
+{
+       RANDOM_ITEM_TYPE_HEALTH = BIT(0),
+       RANDOM_ITEM_TYPE_ARMOR = BIT(1),
+       RANDOM_ITEM_TYPE_RESOURCE = BIT(2),
+       RANDOM_ITEM_TYPE_WEAPON = BIT(3),
+       RANDOM_ITEM_TYPE_POWERUP = BIT(4),
+       RANDOM_ITEM_TYPE_ALL = BITS(5)
+};
+
 /// \brief Returns a random classname of the item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
 /// \return Random classname of the item.
@@ -16,10 +26,11 @@ string RandomItems_GetRandomItemClassName(string prefix);
 
 /// \brief Returns a random classname of the vanilla item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \param[in] types Bitmask of the types. See RANDOM_ITEM_TYPE constants.
 /// \return Random classname of the vanilla item.
 /// \note This includes mutator items that don't change gameplay a lot such as
 /// jetpack and new toys.
-string RandomItems_GetRandomVanillaItemClassName(string prefix);
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types);
 
 /// \brief Returns a random classname of the instagib item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
index 1721303ab526a6d2fc93d5a406d99b5ad1973d43..12bd3b68395a519a2281d236fffb324e7a83e5e7 100644 (file)
@@ -676,7 +676,8 @@ string notif_arg_spree_inf(float type, string input, string player, float spree)
 
 REGISTRY(Notifications, BITS(11))
 REGISTER_REGISTRY(Notifications)
-REGISTRY_SORT(Notifications); STATIC_INIT(Notifications) { FOREACH(Notifications, true, it.m_id = i); }
+REGISTRY_SORT(Notifications);
+STATIC_INIT(Notifications) { FOREACH(Notifications, true, it.m_id = i); }
 REGISTRY_CHECK(Notifications)
 
 const int NOTIF_CHOICE_MAX = 50;
index 4b2ffc55f90595c9eb3efc3cbb65db7a5858da48..02a0126ad81c29a4dd9efcca7f6405db7bb8931a 100644 (file)
@@ -101,15 +101,6 @@ bool IsFlying(entity a);
 #define PHYS_INPUT_BUTTON_ZOOM(s)           PHYS_INPUT_BUTTON_BUTTON4(s)
 #define PHYS_INPUT_BUTTON_CROUCH(s)         PHYS_INPUT_BUTTON_BUTTON5(s)
 #define PHYS_INPUT_BUTTON_HOOK(s)           PHYS_INPUT_BUTTON_BUTTON6(s)
-
-#ifdef CSQC
-STATIC_INIT(PHYS_INPUT_BUTTON_HOOK)
-{
-       localcmd("alias +hook +button6\n");
-       localcmd("alias -hook -button6\n");
-}
-#endif
-
 #define PHYS_INPUT_BUTTON_INFO(s)           PHYS_INPUT_BUTTON_BUTTON7(s)
 #define PHYS_INPUT_BUTTON_DRAG(s)           PHYS_INPUT_BUTTON_BUTTON8(s)
 #define PHYS_INPUT_BUTTON_USE(s)            PHYS_INPUT_BUTTON_BUTTON_USE(s)
@@ -120,16 +111,16 @@ STATIC_INIT(PHYS_INPUT_BUTTON_HOOK)
 #define PHYS_INPUT_BUTTON_DODGE(s)                     PHYS_INPUT_BUTTON_BUTTON11(s)
 
 #ifdef CSQC
-STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
+STATIC_INIT(PHYS_INPUT_BUTTON)
 {
+       localcmd("alias +hook +button6\n");
+       localcmd("alias -hook -button6\n");
+
        localcmd("alias +jetpack +button10\n");
-    localcmd("alias -jetpack -button10\n");
-}
+       localcmd("alias -jetpack -button10\n");
 
-STATIC_INIT(PHYS_INPUT_BUTTON_DODGE)
-{
-    localcmd("alias +dodge +button11\n");
-    localcmd("alias -dodge -button11\n");
+       localcmd("alias +dodge +button11\n");
+       localcmd("alias -dodge -button11\n");
 }
 #endif
 
index 4ce8c8104bb11656586fad6332c26c3f6e00261d..9ab49e7fd0514b1d81c6e7818fc136e332918620 100644 (file)
@@ -667,8 +667,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);
@@ -679,18 +677,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 04436c47f8c728af20a160318ce5456999aa3b53..6fdfd32e70cd51c05a1fa6a8a067c7a9d60b8905 100644 (file)
@@ -3,6 +3,7 @@
 #include "plasma_weapon.qh"
 
 CLASS(PlasmaDualAttack, PlasmaAttack)
+/* flags     */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
 /* refname   */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual");
 /* wepname   */ ATTRIB(PlasmaDualAttack, m_name, string, _("Dual plasma"));
 ENDCLASS(PlasmaDualAttack)
index e4e5ba991bec4fafa3dfc4bfbe278d69f4e2214c..f2dab7bfd22cd7c8620f3b69e7c10d9f37ece242 100644 (file)
@@ -199,4 +199,10 @@ void viewloc_SetViewLocation()
        }
 }
 
+STATIC_INIT_LATE(viewloc_cursor)
+{
+       // fix the mouse position on init so it isn't in the corner
+       viewloc_mousepos = '0.5 0 0' * autocvar_vid_conwidth + '0 0.5 0' * autocvar_vid_conheight;
+}
+
 #endif
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 06562f68a8c5c5e071096d8490347449458ba47b..e46745c2acf4e971e0f0bcfa41a036d9381bfd04 100644 (file)
@@ -125,7 +125,7 @@ void W_Vaporizer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
        yoda = 0;
        damage_goodhits = 0;
-       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, vaporizer_damage, 800, 0, 0, 0, 0, WEP_VAPORIZER.m_id);
+       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, vaporizer_damage, WEP_CVAR_PRI(vaporizer, force), 0, 0, 0, 0, WEP_VAPORIZER.m_id);
 
        // do this now, as goodhits is disabled below
        SendCSQCVaporizerBeamParticle(actor, damage_goodhits);
index ea9f8dd2ba60db6a8452b088e424e5ed0d976046..9bbc5e9bdded6c4098a31020e9da6139b1795b07 100644 (file)
@@ -22,7 +22,8 @@ CLASS(Vaporizer, Weapon)
        BEGIN(class) \
                P(class, prefix, ammo, float, PRI) \
        P(class, prefix, animtime, float, PRI) \
-       P(class, prefix, damage, float, PRI) \
+        P(class, prefix, damage, float, PRI) \
+       P(class, prefix, force, float, PRI) \
        P(class, prefix, refire, float, PRI) \
        P(class, prefix, ammo, float, SEC) \
        P(class, prefix, animtime, float, SEC) \
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 2d41e5d431b3ba9c7b63ccbb87268a4b96615267..306a107d7e722bc4b6706bd447249d0588e1a694 100644 (file)
@@ -23,8 +23,8 @@
 #define REGISTRY(id, max) \
        void Register##id(); \
        [[accumulate]] void REGISTRY_DEPENDS_(id) {} \
-       [[accumulate]] REGISTRY_BEGIN(id) {} \
-       [[accumulate]] REGISTRY_END(id) {} \
+       REGISTRY_BEGIN(id) {} \
+       REGISTRY_END(id) {} \
        void _Register##id() {} \
        int id##_state = 0; \
        void Register##id() { if (id##_state) return; id##_state = 1; REGISTRY_DEPENDS_(id); REGISTRY_BEGIN_(id); _Register##id(); id##_state = 2; REGISTRY_END_(id); } \
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 5befffee4558164437c881ab0194d020adf6897b..03428b12b45ef00b67bf49a5090dae8958a68088 100644 (file)
@@ -180,8 +180,6 @@ float default_weapon_alpha;
 
 string gamemode_name;
 
-float startitem_failed;
-
 string W_Apply_Weaponreplace(string in);
 
 void FixIntermissionClient(entity e);
@@ -404,67 +402,43 @@ const int MIF_GUIDED_CONFUSABLE = MIF_GUIDED_HEAT | MIF_GUIDED_AI;
 .WepSet dual_weapons;
 
 IntrusiveList g_monsters;
-STATIC_INIT(g_monsters) { g_monsters = IL_NEW(); }
-
 IntrusiveList g_waypoints;
-STATIC_INIT(g_waypoints) { g_waypoints = IL_NEW(); }
-
 IntrusiveList g_vehicles;
-STATIC_INIT(g_vehicles) { g_vehicles = IL_NEW(); }
-
 IntrusiveList g_turrets;
-STATIC_INIT(g_turrets) { g_turrets = IL_NEW(); }
-
 IntrusiveList g_mines;
-STATIC_INIT(g_mines) { g_mines = IL_NEW(); }
-
 IntrusiveList g_projectiles;
-STATIC_INIT(g_projectiles) { g_projectiles = IL_NEW(); }
-
 IntrusiveList g_items;
-STATIC_INIT(g_items) { g_items = IL_NEW(); }
-
 IntrusiveList g_initforplayer;
-STATIC_INIT(g_initforplayer) { g_initforplayer = IL_NEW(); }
-
 IntrusiveList g_clones;
-STATIC_INIT(g_clones) { g_clones = IL_NEW(); }
-
-IntrusiveList g_assault_destructibles;
-STATIC_INIT(g_assault_destructibles) { g_assault_destructibles = IL_NEW(); }
-
-IntrusiveList g_assault_objectivedecreasers;
-STATIC_INIT(g_assault_objectivedecreasers) { g_assault_objectivedecreasers = IL_NEW(); }
-
-IntrusiveList g_assault_objectives;
-STATIC_INIT(g_assault_objectives) { g_assault_objectives = IL_NEW(); }
-
 IntrusiveList g_spawnpoints;
-STATIC_INIT(g_spawnpoints) { g_spawnpoints = IL_NEW(); }
-
 IntrusiveList g_bot_targets;
-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(); }
-
 IntrusiveList g_railgunhit;
-STATIC_INIT(g_railgunhit) { g_railgunhit = IL_NEW(); }
-
 IntrusiveList g_ladders;
-STATIC_INIT(g_ladders) { g_ladders = IL_NEW(); }
-
 IntrusiveList g_locations;
-STATIC_INIT(g_locations) { g_locations = IL_NEW(); }
-
 IntrusiveList g_saved_team;
-STATIC_INIT(g_saved_team) { g_saved_team = IL_NEW(); }
-
 IntrusiveList g_monster_targets;
-STATIC_INIT(g_monster_targets) { g_monster_targets = IL_NEW(); }
-
 IntrusiveList g_pathlib_nodes;
-STATIC_INIT(g_pathlib_nodes) { g_pathlib_nodes = IL_NEW(); }
+STATIC_INIT(defs)
+{
+       g_monsters = IL_NEW();
+       g_waypoints = IL_NEW();
+       g_vehicles = IL_NEW();
+       g_turrets = IL_NEW();
+       g_mines = IL_NEW();
+       g_projectiles = IL_NEW();
+       g_items = IL_NEW();
+       g_initforplayer = IL_NEW();
+       g_clones = IL_NEW();
+       g_spawnpoints = IL_NEW();
+       g_bot_targets = IL_NEW();
+       g_bot_dodge = IL_NEW();
+       g_damagedbycontents = IL_NEW();
+       g_railgunhit = IL_NEW();
+       g_ladders = IL_NEW();
+       g_locations = IL_NEW();
+       g_saved_team = IL_NEW();
+       g_monster_targets = IL_NEW();
+       g_pathlib_nodes = IL_NEW();
+}
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 7d248834f72566af97313317a42a3a50c226f637..04b0ba41d596e05d1c40addc88b06a3e8c2640c2 100644 (file)
@@ -6,6 +6,7 @@
 /// \copyright GNU GPLv2 or any later version.
 
 #include "g_subs.qh"
+#include "mutators/events.qh"
 #include <common/weapons/all.qh>
 
 .bool m_isloot; ///< Holds whether item is loot.
 /// this item is on the ground.
 .bool m_isexpiring;
 
+entity Item_FindDefinition(string class_name)
+{
+       FOREACH(Items, it.m_canonical_spawnfunc == class_name,
+       {
+               return it;
+       });
+       FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
+       {
+               return it.m_pickup;
+       });
+       return NULL;
+}
+
+bool Item_IsAllowed(string class_name)
+{
+       entity definition = Item_FindDefinition(class_name);
+       if (definition == NULL)
+       {
+               return false;
+       }
+       return Item_IsDefinitionAllowed(definition);
+}
+
+bool Item_IsDefinitionAllowed(entity definition)
+{
+       return !MUTATOR_CALLHOOK(FilterItemDefinition, definition);
+}
+
 entity Item_Create(string class_name, vector position, bool no_align)
 {
        entity item = spawn();
index 1abcf64e0879442a3b8ade446bc724ca8250e503..b52449e7158dffab62269d6b17d32a6a7cdcc439 100644 (file)
@@ -4,6 +4,28 @@
 /// \brief Header file that describes the functions related to game items.
 /// \copyright GNU GPLv2 or any later version.
 
+bool startitem_failed;
+
+/// \brief Returns the item definition corresponding to the given class name.
+/// \param[in] class_name Class name to search for.
+/// \return Item definition corresponding to the given class name or NULL is not
+/// found.
+entity Item_FindDefinition(string class_name);
+
+/// \brief Checks whether the items with the specified class name are allowed to
+/// spawn.
+/// \param[in] class_name Item class name to check.
+/// \return True items with the specified class name are allowed to spawn, false
+/// otherwise.
+bool Item_IsAllowed(string class_name);
+
+/// \brief Checks whether the items with the specified definition are allowed to
+/// spawn.
+/// \param[in] definition Item definition to check.
+/// \return True items with the specified definition are allowed to spawn, false
+/// otherwise.
+bool Item_IsDefinitionAllowed(entity definition);
+
 /// \brief Creates a new item.
 /// \param[in] class_name Class name of the item.
 /// \param[in] position Position of the item.
@@ -12,7 +34,7 @@
 /// \return Item on success, NULL otherwise.
 entity Item_Create(string class_name, vector position, bool no_align);
 
-/// \brief Initializes the item according to classname.
+/// \brief Initializes the item according to class name.
 /// \param[in,out] item Item to initialize.
 /// \param[in] class_name Class name to use.
 /// \return No return.
index 37910cd28ff5dcba8fe6287f6ace004e66a56804..df7113bd6749717e629467d124c248b98327ca7e 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) \
@@ -235,6 +238,14 @@ MUTATOR_HOOKABLE(SetStartItems, EV_NO_ARGS);
     /**/
 MUTATOR_HOOKABLE(CustomizeWaypoint, EV_CustomizeWaypoint);
 
+/** Check if items having the given definition are allowed to spawn.
+ *  Return true to disallow spawning.
+ */
+#define EV_FilterItemDefinition(i, o) \
+    /** item        */ i(entity, MUTATOR_ARGV_0_entity) \
+    /**/
+MUTATOR_HOOKABLE(FilterItemDefinition, EV_FilterItemDefinition);
+
 /**
  * checks if the current item may be spawned (.items and .weapons may be read and written to, as well as the ammo_ fields)
  * return error to request removal
index f3f104197efd744193dfc7a16d7335907784bd90..2e703d1a8c3320756d6edd1a2ab0366f8fd74e78 100644 (file)
@@ -5,6 +5,16 @@
 .entity sprite;
 #define AS_ROUND_DELAY 5
 
+IntrusiveList g_assault_destructibles;
+IntrusiveList g_assault_objectivedecreasers;
+IntrusiveList g_assault_objectives;
+STATIC_INIT(g_assault)
+{
+       g_assault_destructibles = IL_NEW();
+       g_assault_objectivedecreasers = IL_NEW();
+       g_assault_objectives = IL_NEW();
+}
+
 // random functions
 void assault_objective_use(entity this, entity actor, entity trigger)
 {
index 575fa308de182e3078e777187c9060fbf96fcb79..a69ad0fc4cd7043acb407469f2c9c73134000c19 100644 (file)
@@ -6,13 +6,14 @@
 #include <server/teamplay.qh>
 
 IntrusiveList g_invasion_roundends;
-STATIC_INIT(g_invasion_roundends) { g_invasion_roundends = IL_NEW(); }
-
 IntrusiveList g_invasion_waves;
-STATIC_INIT(g_invasion_waves) { g_invasion_waves = IL_NEW(); }
-
 IntrusiveList g_invasion_spawns;
-STATIC_INIT(g_invasion_spawns) { g_invasion_spawns = IL_NEW(); }
+STATIC_INIT(g_invasion)
+{
+       g_invasion_roundends = IL_NEW();
+       g_invasion_waves = IL_NEW();
+       g_invasion_spawns = IL_NEW();
+}
 
 float autocvar_g_invasion_round_timelimit;
 float autocvar_g_invasion_spawnpoint_spawn_delay;
index 94c4a998c2cc616b4d3f1f64487eb4b5fb98e42e..a57b2ae2d07ab150bfd494492935da44e421e221 100644 (file)
@@ -317,14 +317,14 @@ MUTATOR_HOOKFUNCTION(lms, ForbidPlayerScore_Clear)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(lms, FilterItem)
+MUTATOR_HOOKFUNCTION(lms, FilterItemDefinition)
 {
-       entity item = M_ARGV(0, entity);
+       entity definition = M_ARGV(0, entity);
 
-       if(autocvar_g_lms_extra_lives)
-       if(item.itemdef == ITEM_ExtraLife)
+       if (autocvar_g_lms_extra_lives && definition == ITEM_ExtraLife)
+       {
                return false;
-
+       }
        return true;
 }
 
index d47351cb37a727aab87f100d2ccb61ddd98a5824..17f2ddeeee2bb567271f1f689c8376494168a5a6 100644 (file)
@@ -88,6 +88,13 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                }
        }
 
+       if (!Item_IsDefinitionAllowed(wpn.m_pickup))
+       {
+               delete(this);
+               startitem_failed = true;
+               return;
+       }
+
        if (!this.respawntime)
        {
                if (wpn.spawnflags & WEP_FLAG_SUPERWEAPON)
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() {