]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into TimePath/global_self
authorTimePath <andrew.hardaker1995@gmail.com>
Wed, 2 Sep 2015 09:20:00 +0000 (19:20 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Wed, 2 Sep 2015 09:22:23 +0000 (19:22 +1000)
# Conflicts:
# qcsrc/server/mutators/gamemode_tdm.qc
# qcsrc/server/mutators/mutator_campcheck.qc
# qcsrc/server/mutators/mutator_instagib.qc
# qcsrc/server/mutators/mutator_multijump.qc
# qcsrc/server/mutators/mutator_nades.qc
# qcsrc/server/mutators/mutator_new_toys.qc
# qcsrc/server/mutators/mutator_spawn_near_teammate.qc
# qcsrc/server/t_items.qc

35 files changed:
defaultXonotic.cfg
gamemodes.cfg
mutators.cfg
qcsrc/client/autocvars.qh
qcsrc/client/main.qc
qcsrc/common/mutators/base.qh
qcsrc/common/mutators/events.qh
qcsrc/common/stats.qh
qcsrc/dpdefs/menudefs.qh
qcsrc/lib/Cvar.qh
qcsrc/lib/Registry.qh
qcsrc/lib/Static.qh [new file with mode: 0644]
qcsrc/lib/_all.inc
qcsrc/menu/menu.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/radiobutton.qc
qcsrc/server/autocvars.qh
qcsrc/server/cl_client.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/mutators/gamemode_lms.qc
qcsrc/server/mutators/gamemode_tdm.qc
qcsrc/server/mutators/mutator_bloodloss.qc
qcsrc/server/mutators/mutator_campcheck.qc
qcsrc/server/mutators/mutator_instagib.qc
qcsrc/server/mutators/mutator_multijump.qc
qcsrc/server/mutators/mutator_nades.qc
qcsrc/server/mutators/mutator_new_toys.qc
qcsrc/server/mutators/mutator_physical_items.qc
qcsrc/server/mutators/mutator_spawn_near_teammate.qc
qcsrc/server/mutators/mutator_superspec.qc
qcsrc/server/spawnpoints.qc
qcsrc/server/spawnpoints.qh
qcsrc/server/t_items.qc
qcsrc/server/t_items.qh
qcsrc/server/teamplay.qc

index 6a81e3507cc4558196eb7ec92bfbff97aa6ab438..ede4ffe1135b6ecfe9e3b3020d5cb70ac8daddc8 100644 (file)
@@ -439,6 +439,9 @@ seta g_maplist_shuffle 1    "new randomization method: like selectrandom, but avoid
 set g_maplist_check_waypoints 0        "when 1, maps are skipped if there currently are bots, but the map has no waypoints"
 set samelevel 0 "when 1, always play the same level over and over again"
 
+set g_items_mindist 0 "starting distance for the fading of items"
+set g_items_maxdist 0 "maximum distance at which an item can be viewed, after which it will be invisible"
+
 set g_grab_range 200 "distance at which dragable objects can be grabbed"
 
 set g_cloaked 0 "display all players mostly invisible"
@@ -510,10 +513,6 @@ set g_bloodloss 0   "amount of health below which blood loss occurs"
 
 set g_footsteps 1      "serverside footstep sounds"
 
-set g_multijump 0      "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
-set g_multijump_add 0  "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
-set g_multijump_speed -999999  "Minimum vertical speed a player must have in order to jump again"
-
 set g_throughfloor_debug 0 "enable debugging messages for throughfloor calculations"
 set g_throughfloor_damage_max_stddev 2 "Maximum standard deviation for splash damage"
 set g_throughfloor_force_max_stddev 10 "Maximum standard deviation for splash force"
index 340d01b9dcec368814affe8aaa70103b82945983..31a0f33d3b04116ccafc567b3e5bb0e8de509ab1 100644 (file)
@@ -438,6 +438,7 @@ set g_balance_keyhunt_protecttime 0.8
 set g_balance_keyhunt_damageforcescale 1
 seta g_keyhunt_teams_override 0
 set g_keyhunt_teams 0
+set g_keyhunt_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
 
 
 // ===================
index 311debc2c0aa19595eddf24cea5bd1e31f0b8820..6a8d5c6141a0e9bf2a1751132263c5a53e7de307 100644 (file)
@@ -31,6 +31,7 @@ set g_instagib_ammo_start 10 "starting ammo"
 set g_instagib_ammo_drop 5 "how much ammo you'll get for weapons or cells"
 set g_instagib_invis_alpha 0.15
 set g_instagib_speed_highspeed 1.5 "speed-multiplier that applies while you carry the invincibility powerup"
+set g_instagib_damagedbycontents 1 "allow damage from lava pits in instagib"
 
 
 // ==========
@@ -109,9 +110,10 @@ set g_rocket_flying 0 "set to 1 to enable rocket flying in all balance configs"
 // =====================
 //  spawn near teammate
 // =====================
+seta cl_spawn_near_teammate 1 "toggle for spawning near teammates (only effective if g_spawn_near_teammate_ignore_spawnpoint is 2)"
 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"
+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_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_check_health 1 "only allow spawn at this player if their health is full"
@@ -209,6 +211,7 @@ set g_nades_bonus_client_select 0 "Allow client side selection of bonus nade typ
 set g_nades_bonus_type 2 "Type of the bonus grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade"
 set g_nades_bonus_onstrength 1 "Always give bonus grenades to players that have the strength powerup"
 set g_nades_bonus_max 3 "Maximum number of bonus grenades"
+set g_nades_bonus_only 0 "Disallow regular nades, only bonus nades can be used"
 // Bonus score
 set g_nades_bonus_score_max   120 "Score value that will give a bonus nade"
 set g_nades_bonus_score_minor   5 "Score given for minor actions (pickups, regular frags etc.)"
@@ -271,6 +274,7 @@ set g_campcheck_distance 1800
 // ==========
 set g_new_toys 0 "Mutator 'New Toys': enable extra fun guns"
 set g_new_toys_autoreplace 2 "0: never replace, 1: always auto replace guns by available new toys, 2: randomly auto replace guns by available new toys"
+set g_new_toys_use_pickupsound 1 "play the 'new toys, new toys!' roflsound when picking up a new toys weapon"
 
 
 // =======
@@ -387,3 +391,12 @@ set g_rm_laser_force "400" "laser force, divided by laser count"
 // ================
 set g_breakablehook 0 "enable breakable hook mutator (hook can be damaged, and returns damage to the owner when broken)"
 set g_breakablehook_owner 0 "allow owner to break their own hook"
+
+
+// ===========
+//  multijump
+// ===========
+seta cl_multijump 1 "allow multijump mutator"
+set g_multijump 0      "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
+set g_multijump_add 0  "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
+set g_multijump_speed -999999  "Minimum vertical speed a player must have in order to jump again"
index 7a1d66450b06347a505f1ffa077399e1ae52302f..919cf031ebed7ab7b412eb2b54e623500d5ac7e9 100644 (file)
@@ -456,4 +456,5 @@ vector autocvar_crosshair_rpc_color = '0.2 1.0 0.2';
 float autocvar_crosshair_rpc_alpha = 1;
 float autocvar_crosshair_rpc_size = 1;
 int autocvar_cl_nade_timer;
+bool autocvar_cl_items_nofade;
 #endif
index 6fbef76ef60462eaa8ba555465b551c7834e7156..3603fab1e1042983929507f6ba6c208702230704 100644 (file)
@@ -125,6 +125,10 @@ void CSQC_Init(void)
        registercvar("cl_jumpspeedcap_min", "");
        registercvar("cl_jumpspeedcap_max", "");
 
+       registercvar("cl_multijump", "1");
+
+       registercvar("cl_spawn_near_teammate", "1");
+
        gametype = 0;
 
        // hud_fields uses strunzone on the titles!
index 4c39d6f7d5a4f32b46ef32e20fe90910a9b9eaee..d92bd5b57c90b43c60180a25c18a3af381a5c68b 100644 (file)
@@ -228,6 +228,9 @@ STATIC_INIT(Mutators) {
     RegisterHooks();
     RegisterCallbacks();
     RegisterMutators();
+}
+
+STATIC_INIT_LATE(Mutators) {
     FOREACH(MUTATORS, it.mutatorcheck(), LAMBDA(Mutator_Add(it)));
 }
 
index eb46486b6b8e6ca4a00ed7f4fedcd6fee7990c37..8a5c153ad7024f7eb1ae6c728b6243e4869438df 100644 (file)
@@ -39,4 +39,11 @@ MUTATOR_HOOKABLE(BuildMutatorsString, EV_BuildMutatorsString);
     /**/
 MUTATOR_HOOKABLE(BuildMutatorsPrettyString, EV_BuildMutatorsPrettyString);
 
+/** appends mutator string for displaying extra gameplay tips */
+#define EV_BuildGameplayTipsString(i, o) \
+    /**/ i(string, ret_string) \
+    /**/ o(string, ret_string) \
+    /**/
+MUTATOR_HOOKABLE(BuildGameplayTipsString, EV_BuildGameplayTipsString);
+
 #endif
index 74aa0e75fad498f4cb543430af2e119212fa93cd..eff0eff804ef1f07621f138f78f03266e8096a62 100644 (file)
@@ -217,8 +217,8 @@ const int STAT_CTF_FLAGSTATUS         = 124;
 // 163 empty?
 // 164 empty?
 // 165 empty?
-// 166 empty?
-// 167 empty?
+const int STAT_MULTIJUMP_DODGING                      = 166;
+const int STAT_MULTIJUMP_MAXSPEED                     = 167;
 const int STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND   = 168;
 const int STAT_BUGRIGS_REVERSE_STOPPING               = 169;
 const int STAT_BUGRIGS_REVERSE_SPINNING               = 170;
index 7d4dcc6af589598f1fa5abd72f5f29c4dee8790e..c0e6d3ba728e738b5cc7f431e2025501df0278e4 100644 (file)
@@ -19,6 +19,8 @@
 
 #undef spawn
 
+#define localcmd cmd
+
 int(string str, string sub, int startpos) _strstrofs = #221;
 #define strstrofs _strstrofs
 int(string str, int ofs) _str2chr = #222;
index 5eeafddce5dee77d4419240197cd379eed35d415..02016a251724f6468939e6adaba2a6f3f9e849d1 100644 (file)
@@ -1,15 +1,24 @@
 #ifndef CVAR_H
 #define CVAR_H
 
-#define CVAR_DESCRIBE(set, var, desc)    localcmd(sprintf("\n"set" %1$s \"$%1$s\" \"%2$s\"\n", #var, desc))
+#include "Static.qh"
 
-#define AUTOCVAR_4(set, var, type, desc) \
-    STATIC_INIT(autocvar_##var) { CVAR_DESCRIBE(set, var, desc); } \
+void RegisterCvars(void(string name, string desc, bool archive, string file) f) { }
+
+void RegisterCvars_Set(string name, string desc, bool archive, string file)
+{
+    localcmd(sprintf("\n%1$s %2$s \"$%2$s\" \"%3$s\"\n", (archive ? "seta" : "set"), name, desc));
+}
+
+STATIC_INIT_LATE(Cvars) { RegisterCvars(RegisterCvars_Set); }
+
+#define AUTOCVAR_5(file, archive, var, type, desc) \
+    [[accumulate]] void RegisterCvars(void(string, string, bool, string) f) { f(#var, desc, archive, file); } \
     type autocvar_##var
-#define AUTOCVAR_5(set, var, type, default, desc) \
-    AUTOCVAR_4(set, var, type, desc) = default
-#define _AUTOCVAR(...) OVERLOAD(AUTOCVAR, __VA_ARGS__)
-#define AUTOCVAR_SAVE(...) _AUTOCVAR("seta", __VA_ARGS__)
-#define AUTOCVAR(...) _AUTOCVAR("set", __VA_ARGS__)
+#define AUTOCVAR_6(file, archive, var, type, default, desc) \
+    AUTOCVAR_5(file, archive, var, type, desc) = default
+#define _AUTOCVAR(...) OVERLOAD(AUTOCVAR, __FILE__, __VA_ARGS__)
+#define AUTOCVAR_SAVE(...) _AUTOCVAR(true, __VA_ARGS__)
+#define AUTOCVAR(...) _AUTOCVAR(false, __VA_ARGS__)
 
 #endif
index 8a93146d50911284925c19d4e2a40531be8e07a5..ca0beae9def170f6d1f98b5424c55435ce68fadc 100644 (file)
     ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id)         \
     REGISTER_INIT(ns, id)
 
-void __static_init() { }
-#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init)
-#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init, func)
-
-#define STATIC_INIT(func) \
-    void _static_##func(); \
-    ACCUMULATE_FUNCTION(__static_init, _static_##func) \
-    void _static_##func()
-
 #endif
diff --git a/qcsrc/lib/Static.qh b/qcsrc/lib/Static.qh
new file mode 100644 (file)
index 0000000..d51a871
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef STATIC_H
+#define STATIC_H
+
+void __static_init_early() { }
+void __static_init() { CALL_ACCUMULATED_FUNCTION(__static_init_early); }
+#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init)
+#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init_early, func)
+
+#define _STATIC_INIT(where, func) \
+    void _static_##func(); \
+    ACCUMULATE_FUNCTION(where, _static_##func) \
+    void _static_##func()
+
+#define STATIC_INIT(func)       _STATIC_INIT(__static_init_early,   func##_early)
+#define STATIC_INIT_LATE(func)  _STATIC_INIT(__static_init,         func)
+
+#endif
index 4e0b12f255dbea477471c539aadd46dad8bdd648..1b7e61e9aa4cb125fd5e20f3b02e4420ee4cb78f 100644 (file)
@@ -20,6 +20,7 @@
 #include "Progname.qh"
 #include "Registry.qh"
 #include "sortlist.qc"
+#include "Static.qh"
 #include "String.qh"
 #include "Struct.qh"
 #include "test.qc"
index e4f594f71f68ad734a62beeda1aed79873506166..0ece40c88e4fe78f5d0c9bb14fec958fabb2ebf7 100644 (file)
@@ -11,8 +11,6 @@
 #include "../common/constants.qh"
 #include "../common/util.qh"
 
-#define localcmd cmd
-
 // constants
 
 const int GAME_ISSERVER        = 1;
index a1b299d9fc1f3cd674cdfd55eb941c08e164deea..8e7a37f8d6bc925eb08f57c50a0659b5bbf71769 100644 (file)
@@ -82,7 +82,7 @@ string XonoticMutatorsDialog_toString(entity me)
                s = strcat(s, ", ", _("Invincible Projectiles"));
        if(cvar_string("g_weaponarena") != "0")
                s = strcat(s, ", ", WeaponArenaString());
-       if(cvar("g_balance_blaster_weaponstart") == 0)
+       else if(cvar("g_balance_blaster_weaponstart") == 0)
                s = strcat(s, ", ", _("No start weapons"));
        if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
                s = strcat(s, ", ", _("Low gravity"));
@@ -236,7 +236,7 @@ void XonoticMutatorsDialog_fill(entity me)
                me.TD(me, 1, 2, e = makeXonoticRadioButton(1, string_null, string_null, _("Regular (no arena)")));
        me.TR(me);
                me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_weaponarena", "menu_weaponarena", _("Weapon arenas:")));
-                       e.getCvarValueFromCvar = true;
+                       e.cvarValueIsAnotherCvar = true;
                        e.cvarOffValue = "0";
        for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i)
        {
index 1d2676f1f4db34924bbf1e1cedffc522435ebc37..65f2486f2111e57d749bc28ff73ac2aff1254afa 100644 (file)
@@ -15,7 +15,7 @@ CLASS(XonoticRadioButton, RadioButton)
        ATTRIB(XonoticRadioButton, cvarName, string, string_null)
        ATTRIB(XonoticRadioButton, cvarValue, string, string_null)
        ATTRIB(XonoticRadioButton, cvarOffValue, string, string_null)
-       ATTRIB(XonoticRadioButton, getCvarValueFromCvar, float, 0)
+       ATTRIB(XonoticRadioButton, cvarValueIsAnotherCvar, float, 0)
        METHOD(XonoticRadioButton, loadCvars, void(entity));
        METHOD(XonoticRadioButton, saveCvars, void(entity));
 
@@ -57,7 +57,12 @@ void XonoticRadioButton_loadCvars(entity me)
        if(me.cvarValue)
        {
                if(me.cvarName)
-                       me.checked = (cvar_string(me.cvarName) == me.cvarValue);
+               {
+                       if(me.cvarValueIsAnotherCvar)
+                               me.checked = (cvar_string(me.cvarName) == cvar_string(me.cvarValue));
+                       else
+                               me.checked = (cvar_string(me.cvarName) == me.cvarValue);
+               }
        }
        else
        {
@@ -102,7 +107,7 @@ void XonoticRadioButton_saveCvars(entity me)
                {
                        if(me.checked)
                        {
-                               if(me.getCvarValueFromCvar)
+                               if(me.cvarValueIsAnotherCvar)
                                        cvar_set(me.cvarName, cvar_string(me.cvarValue));
                                else
                                        cvar_set(me.cvarName, me.cvarValue);
index 3f4a11a7cefe2125d5b777e03cf5f3106f2bbecc..412ac1cd72da4c0c53309042bb398fd4a9a3f99c 100644 (file)
@@ -369,6 +369,7 @@ int autocvar_g_keepawayball_effects;
 float autocvar_g_keepawayball_respawntime;
 int autocvar_g_keepawayball_trail_color;
 int autocvar_g_keyhunt_point_leadlimit;
+bool autocvar_g_keyhunt_team_spawns;
 #define autocvar_g_keyhunt_point_limit cvar("g_keyhunt_point_limit")
 int autocvar_g_keyhunt_teams;
 int autocvar_g_keyhunt_teams_override;
@@ -402,6 +403,7 @@ int autocvar_g_instagib_ammo_drop;
 int autocvar_g_instagib_extralives;
 float autocvar_g_instagib_speed_highspeed;
 float autocvar_g_instagib_invis_alpha;
+bool autocvar_g_instagib_damagedbycontents = true;
 #define autocvar_g_mirrordamage cvar("g_mirrordamage")
 #define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
 
@@ -409,6 +411,8 @@ float autocvar_g_movement_highspeed = 1;
 int autocvar_g_multijump;
 float autocvar_g_multijump_add;
 float autocvar_g_multijump_speed;
+float autocvar_g_multijump_maxspeed;
+float autocvar_g_multijump_dodging = 1;
 string autocvar_g_mutatormsg;
 float autocvar_g_nexball_basketball_bouncefactor;
 float autocvar_g_nexball_basketball_bouncestop;
@@ -436,6 +440,8 @@ bool autocvar_g_nix_with_powerups;
 bool autocvar_g_nodepthtestitems;
 bool autocvar_g_nodepthtestplayers;
 bool autocvar_g_norecoil;
+float autocvar_g_items_mindist;
+float autocvar_g_items_maxdist;
 int autocvar_g_pickup_cells_max;
 int autocvar_g_pickup_plasma_max;
 int autocvar_g_pickup_fuel_max;
@@ -763,6 +769,7 @@ int autocvar_g_nades_bonus_type;
 bool autocvar_g_nades_bonus;
 bool autocvar_g_nades_bonus_onstrength;
 bool autocvar_g_nades_bonus_client_select;
+bool autocvar_g_nades_bonus_only;
 int autocvar_g_nades_bonus_max;
 int autocvar_g_nades_bonus_score_max;
 int autocvar_g_nades_bonus_score_time;
@@ -794,7 +801,7 @@ bool autocvar_g_overkill_ammo_charge;
 float autocvar_g_overkill_ammo_charge_notice;
 float autocvar_g_overkill_ammo_charge_limit;
 float autocvar_g_spawn_near_teammate_distance;
-bool autocvar_g_spawn_near_teammate_ignore_spawnpoint;
+int autocvar_g_spawn_near_teammate_ignore_spawnpoint;
 float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
 float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
 float autocvar_g_onslaught_debug;
index 5ba3d866720a1e093e0ac26ce1ea2d3e5403019d..fda43661c3f97daca227bad8bbe61d902fbaa6d0 100644 (file)
@@ -2653,6 +2653,7 @@ Called every frame for each client after the physics are run
 void PlayerPostThink (void)
 {SELFPARAM();
        if(sv_maxidle > 0 && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
+       if(IS_REAL_CLIENT(self))
        if(IS_PLAYER(self) || sv_maxidle_spectatorsareidle)
        {
                if (time - self.parm_idlesince < 1) // instead of (time == self.parm_idlesince) to support sv_maxidle <= 10
index 3b5767373629a3d61c87899565b37681e7614b30..f1f003820d1b8c736c48261847a34a83f4699164 100644 (file)
@@ -76,8 +76,6 @@ float DistributeEvenly_amount;
 float DistributeEvenly_totalweight;
 void objerror(string s);
 void droptofloor();
-void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
-void() spawnpoint_use;
 void() SUB_Remove;
 
 void attach_sameorigin(entity e, entity to, string tag);
index 9c6033e9a367758565fb2985063a2a35eaa32ea3..08a8ce4b6b7e302ec4f7c8e0eb66cc6f6ff0b9c7 100644 (file)
@@ -53,7 +53,10 @@ MUTATOR_HOOKFUNCTION(lms_PlayerPreSpawn)
        // player is dead and becomes observer
        // FIXME fix LMS scoring for new system
        if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0)
+       {
                self.classname = "observer";
+               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_LMS_NOLIVES);
+       }
 
        return false;
 }
index 996857db5817087e4e3958271b05fc14b309f8a4..27cc19b0ab8d029f17092ac75a8ad1e903263a84 100644 (file)
@@ -10,7 +10,7 @@ Keys:
 "cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
 void spawnfunc_tdm_team()
 {SELFPARAM();
-       if(!g_tdm) { remove(self); return; }
+       if(!g_tdm || !self.cnt) { remove(self); return; }
 
        self.classname = "tdm_team";
        self.team = self.cnt + 1;
@@ -36,7 +36,7 @@ void tdm_DelayedInit()
        {
                LOG_INFO("No ""tdm_team"" entities found on this map, creating them anyway.\n");
 
-               float numteams = min(4, autocvar_g_tdm_teams_override);
+               int numteams = min(4, autocvar_g_tdm_teams_override);
 
                if(numteams < 2) { numteams = autocvar_g_tdm_teams; }
                numteams = bound(2, numteams, 4);
index 03c9904081af4425f49ab66f994914eb0ac1dbc1..da9a608f0156a6bc047aebf8bf98886921673830 100644 (file)
@@ -13,7 +13,10 @@ MUTATOR_HOOKFUNCTION(bloodloss_PlayerThink)
 
                if(time >= self.bloodloss_timer)
                {
-                       self.event_damage(self, self, 1, DEATH_ROT, self.origin, '0 0 0');
+                       if(self.vehicle)
+                               vehicles_exit(VHEF_RELEASE);
+                       if(self.event_damage)
+                               self.event_damage(self, self, 1, DEATH_ROT, self.origin, '0 0 0');
                        self.bloodloss_timer = time + 0.5 + random() * 0.5;
                }
        }
index 960565d4253424bd0b60ece853bee36a3a67ecd3..e4ad5ba19854f13851fb987bca87c111f189e1cf 100644 (file)
@@ -9,7 +9,7 @@
 
 MUTATOR_HOOKFUNCTION(campcheck_PlayerDies)
 {SELFPARAM();
-       Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_CAMPCHECK);
+       Kill_Notification(NOTIF_ONE, self, MSG_CENTER_CPID, CPID_CAMPCHECK);
 
        return false;
 }
@@ -29,9 +29,14 @@ MUTATOR_HOOKFUNCTION(campcheck_PlayerDamage)
 
 MUTATOR_HOOKFUNCTION(campcheck_PlayerThink)
 {SELFPARAM();
+       if(!gameover)
+       if(!warmup_stage) // don't consider it camping during warmup?
+       if(time >= game_starttime)
        if(IS_PLAYER(self))
+       if(IS_REAL_CLIENT(self)) // bots may camp, but that's no reason to constantly kill them
        if(self.deadflag == DEAD_NO)
        if(!self.frozen)
+       if(!self.BUTTON_CHAT)
        if(autocvar_g_campcheck_interval)
        {
                vector dist;
@@ -60,8 +65,11 @@ MUTATOR_HOOKFUNCTION(campcheck_PlayerThink)
                        self.campcheck_nextcheck = time + autocvar_g_campcheck_interval;
                        self.campcheck_traveled_distance = 0;
                }
+
+               return false;
        }
 
+       self.campcheck_nextcheck = time + autocvar_g_campcheck_interval; // one of the above checks failed, so keep the timer up to date
        return false;
 }
 
index 30810c82e4c7f84f6ec99de7df65f07b6afc8036..384c297808aa29ea61d34f8bd5ed0fd57bb06ea7 100644 (file)
@@ -249,12 +249,17 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerDamage)
 
        if(IS_PLAYER(frag_target))
        {
-               if ((frag_deathtype == DEATH_FALL)  ||
-                       (frag_deathtype == DEATH_DROWN) ||
-                       (frag_deathtype == DEATH_SLIME) ||
-                       (frag_deathtype == DEATH_LAVA))
+               if(frag_deathtype == DEATH_FALL)
+                       frag_damage = 0; // never count fall damage
+
+               if(!autocvar_g_instagib_damagedbycontents)
+               switch(frag_deathtype)
                {
-                       frag_damage = 0;
+                       case DEATH_DROWN:
+                       case DEATH_SLIME:
+                       case DEATH_LAVA:
+                               frag_damage = 0;
+                               break;
                }
 
                if(IS_PLAYER(frag_attacker))
@@ -337,6 +342,9 @@ MUTATOR_HOOKFUNCTION(instagib_FilterItem)
        {
                entity e = spawn();
                setorigin(e, self.origin);
+               e.noalign = self.noalign;
+        e.cnt = self.cnt;
+        e.team = self.team;
                SELFCALL(e, spawnfunc_item_minst_cells());
                SELFCALL_DONE();
                return true;
index 265ebea424ac0d85c3ecc114f8728e55324bc799..04e60bb83ec490cc6ebad1483a0642dfefff4fef 100644 (file)
@@ -4,31 +4,40 @@
        #include "../antilag.qh"
 #endif
 
-.float multijump_count;
-.float multijump_ready;
+.int multijump_count;
+.bool multijump_ready;
+.bool cvar_cl_multijump;
 
 #ifdef CSQC
 
 #define PHYS_MULTIJUMP                                 getstati(STAT_MULTIJUMP)
 #define PHYS_MULTIJUMP_SPEED           getstatf(STAT_MULTIJUMP_SPEED)
 #define PHYS_MULTIJUMP_ADD                     getstati(STAT_MULTIJUMP_ADD)
+#define PHYS_MULTIJUMP_MAXSPEED        getstatf(STAT_MULTIJUMP_MAXSPEED)
+#define PHYS_MULTIJUMP_DODGING                 getstati(STAT_MULTIJUMP_DODGING)
 
 #elif defined(SVQC)
 
 #define PHYS_MULTIJUMP                                 autocvar_g_multijump
 #define PHYS_MULTIJUMP_SPEED           autocvar_g_multijump_speed
 #define PHYS_MULTIJUMP_ADD                     autocvar_g_multijump_add
+#define PHYS_MULTIJUMP_MAXSPEED        autocvar_g_multijump_maxspeed
+#define PHYS_MULTIJUMP_DODGING                 autocvar_g_multijump_dodging
 
 
 .float stat_multijump;
 .float stat_multijump_speed;
 .float stat_multijump_add;
+.float stat_multijump_maxspeed;
+.float stat_multijump_dodging;
 
 void multijump_UpdateStats()
 {SELFPARAM();
        self.stat_multijump = PHYS_MULTIJUMP;
        self.stat_multijump_speed = PHYS_MULTIJUMP_SPEED;
        self.stat_multijump_add = PHYS_MULTIJUMP_ADD;
+       self.stat_multijump_maxspeed = PHYS_MULTIJUMP_MAXSPEED;
+       self.stat_multijump_dodging = PHYS_MULTIJUMP_DODGING;
 }
 
 void multijump_AddStats()
@@ -36,6 +45,8 @@ void multijump_AddStats()
        addstat(STAT_MULTIJUMP, AS_INT, stat_multijump);
        addstat(STAT_MULTIJUMP_SPEED, AS_FLOAT, stat_multijump_speed);
        addstat(STAT_MULTIJUMP_ADD, AS_INT, stat_multijump_add);
+       addstat(STAT_MULTIJUMP_MAXSPEED, AS_FLOAT, stat_multijump_maxspeed);
+       addstat(STAT_MULTIJUMP_DODGING, AS_INT, stat_multijump_dodging);
 }
 
 #endif
@@ -50,16 +61,31 @@ void PM_multijump()
        }
 }
 
-float PM_multijump_checkjump()
+bool PM_multijump_checkjump()
 {SELFPARAM();
        if(!PHYS_MULTIJUMP) { return false; }
 
-       if (!IS_JUMP_HELD(self) && !IS_ONGROUND(self)) // jump button pressed this frame and we are in midair
+#ifdef SVQC
+       bool client_multijump = self.cvar_cl_multijump;
+#elif defined(CSQC)
+       bool client_multijump = cvar("cl_multijump");
+
+       if(cvar("cl_multijump") > 1)
+               return false; // nope
+#endif
+
+       if (!IS_JUMP_HELD(self) && !IS_ONGROUND(self) && client_multijump) // jump button pressed this frame and we are in midair
                self.multijump_ready = true;  // this is necessary to check that we released the jump button and pressed it again
        else
                self.multijump_ready = false;
 
-       if(!player_multijump && self.multijump_ready && (self.multijump_count < PHYS_MULTIJUMP || PHYS_MULTIJUMP == -1) && self.velocity_z > PHYS_MULTIJUMP_SPEED)
+       int phys_multijump = PHYS_MULTIJUMP;
+
+#ifdef CSQC
+       phys_multijump = (PHYS_MULTIJUMP) ? -1 : 0;
+#endif
+
+       if(!player_multijump && self.multijump_ready && (self.multijump_count < phys_multijump || phys_multijump == -1) && self.velocity_z > PHYS_MULTIJUMP_SPEED && (!PHYS_MULTIJUMP_MAXSPEED || vlen(self.velocity) <= PHYS_MULTIJUMP_MAXSPEED))
        {
                if (PHYS_MULTIJUMP)
                {
@@ -76,19 +102,20 @@ float PM_multijump_checkjump()
 
                        if(player_multijump)
                        {
+                               if(PHYS_MULTIJUMP_DODGING)
                                if(self.movement_x != 0 || self.movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
                                {
                                        float curspeed;
                                        vector wishvel, wishdir;
 
-#ifdef SVQC
+/*#ifdef SVQC
                                        curspeed = max(
                                                vlen(vec2(self.velocity)), // current xy speed
                                                vlen(vec2(antilag_takebackavgvelocity(self, max(self.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
                                        );
-#elif defined(CSQC)
+#elif defined(CSQC)*/
                                        curspeed = vlen(vec2(self.velocity));
-#endif
+//#endif
 
                                        makevectors(self.v_angle_y * '0 1 0');
                                        wishvel = v_forward * self.movement_x + v_right * self.movement_y;
@@ -98,7 +125,10 @@ float PM_multijump_checkjump()
                                        self.velocity_y = wishdir_y * curspeed;
                                        // keep velocity_z unchanged!
                                }
-                               self.multijump_count += 1;
+                               if (PHYS_MULTIJUMP > 0)
+                               {
+                                       self.multijump_count += 1;
+                               }
                        }
                }
                self.multijump_ready = false; // require releasing and pressing the jump button again for the next jump
@@ -121,6 +151,12 @@ MUTATOR_HOOKFUNCTION(multijump_PlayerJump)
        return PM_multijump_checkjump();
 }
 
+MUTATOR_HOOKFUNCTION(multijump_GetCvars)
+{
+       GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_multijump, "cl_multijump");
+       return false;
+}
+
 MUTATOR_HOOKFUNCTION(multijump_BuildMutatorsString)
 {
        ret_string = strcat(ret_string, ":multijump");
@@ -137,6 +173,7 @@ MUTATOR_DEFINITION(mutator_multijump)
 {
        MUTATOR_HOOK(PlayerPhysics, multijump_PlayerPhysics, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerJump, multijump_PlayerJump, CBC_ORDER_ANY);
+       MUTATOR_HOOK(GetCvars, multijump_GetCvars, CBC_ORDER_ANY);
        MUTATOR_HOOK(BuildMutatorsString, multijump_BuildMutatorsString, CBC_ORDER_ANY);
        MUTATOR_HOOK(BuildMutatorsPrettyString, multijump_BuildMutatorsPrettyString, CBC_ORDER_ANY);
 
index fcab3c769739c773cf670293b199a86b4523abac..8e49e2aa63404fe6c9505f84026935dd38e830af 100644 (file)
@@ -795,6 +795,10 @@ float nade_customize()
 
 void nade_prime()
 {SELFPARAM();
+       if(autocvar_g_nades_bonus_only)
+       if(!self.bonus_nades)
+               return; // only allow bonus nades
+
        if(self.nade)
                remove(self.nade);
 
index c80f19f6690118b5771a9e58f8a9168c70fe5f5e..172ee4d651430b2d8a6e08458f54cfb71a4f17f9 100644 (file)
@@ -73,6 +73,7 @@ roflsound "New toys, new toys!" sound.
 .string new_toys;
 
 float autocvar_g_new_toys_autoreplace;
+bool autocvar_g_new_toys_use_pickupsound = true;
 const float NT_AUTOREPLACE_NEVER = 0;
 const float NT_AUTOREPLACE_ALWAYS = 1;
 const float NT_AUTOREPLACE_RANDOM = 2;
@@ -106,7 +107,7 @@ string nt_GetFullReplacement(string w)
                case "devastator": return "minelayer";
                case "machinegun": return "hlac";
                case "vortex": return "rifle";
-               case "shotgun": return "shockwave";
+               //case "shotgun": return "shockwave";
                default: return string_null;
        }
 }
@@ -189,7 +190,7 @@ MUTATOR_HOOKFUNCTION(nt_SetWeaponreplace)
 
 MUTATOR_HOOKFUNCTION(nt_FilterItem)
 {SELFPARAM();
-       if(nt_IsNewToy(self.weapon))
+       if(nt_IsNewToy(self.weapon) && autocvar_g_new_toys_use_pickupsound)
                self.item_pickupsound = W_Sound("weaponpickup_new_toys");
        return 0;
 }
index 892211ce0373386d128c21090ad6617c21a2767a..d02158ffc1496a22305c9ab02e79e0eeae1819b3 100644 (file)
@@ -20,15 +20,17 @@ void physical_item_think()
                // if the item is not spawned, make sure the invisible / ghost item returns to its origin and stays there
                if(autocvar_g_physical_items_reset)
                {
-                       if(self.owner.nextthink > time) // awaiting respawn
+                       if(self.owner.wait > time) // awaiting respawn
                        {
                                setorigin(self, self.spawn_origin);
                                self.angles = self.spawn_angles;
                                self.solid = SOLID_NOT;
+                               self.alpha = -1;
                                self.movetype = MOVETYPE_NONE;
                        }
                        else
                        {
+                               self.alpha = 1;
                                self.solid = SOLID_CORPSE;
                                self.movetype = MOVETYPE_PHYSICS;
                        }
@@ -92,12 +94,24 @@ MUTATOR_HOOKFUNCTION(item_spawning)
        wep.touch = physical_item_touch;
        wep.event_damage = physical_item_damage;
 
-       wep.spawn_origin = self.origin;
+       if(!wep.cnt)
+       {
+               // fix the spawn origin
+               setorigin(wep, wep.origin + '0 0 1');
+               entity oldself;
+               oldself = self;
+               self = wep;
+               builtin_droptofloor();
+               self = oldself;
+       }
+
+       wep.spawn_origin = wep.origin;
        wep.spawn_angles = self.angles;
 
        self.effects |= EF_NODRAW; // hide the original weapon
        self.movetype = MOVETYPE_FOLLOW;
        self.aiment = wep; // attach the original weapon
+       self.SendEntity = func_null;
 
        return false;
 }
index 899438d762f911a0b547933085cd41f3b9e28fe7..e3178b338874f9892eb174afdffa6800e2c3c8a7 100644 (file)
@@ -7,9 +7,11 @@
 .float msnt_timer;
 .vector msnt_deathloc;
 
+.float cvar_cl_spawn_near_teammate;
+
 MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
 {SELFPARAM();
-       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint)
+       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
                return 0;
 
        entity p;
@@ -46,7 +48,7 @@ MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
 MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn)
 {SELFPARAM();
        // Note: when entering this, fixangle is already set.
-       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint)
+       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
        {
                if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death)
                        self.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
@@ -158,11 +160,18 @@ MUTATOR_HOOKFUNCTION(msnt_PlayerDies)
        return 0;
 }
 
+MUTATOR_HOOKFUNCTION(msnt_GetCvars)
+{
+       GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_spawn_near_teammate, "cl_spawn_near_teammate");
+       return false;
+}
+
 MUTATOR_DEFINITION(mutator_spawn_near_teammate)
 {
        MUTATOR_HOOK(Spawn_Score, msnt_Spawn_Score, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerSpawn, msnt_PlayerSpawn, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerDies, msnt_PlayerDies, CBC_ORDER_ANY);
+       MUTATOR_HOOK(GetCvars, msnt_GetCvars, CBC_ORDER_ANY);
 
        return 0;
 }
index e7bb9d0182d690438cf9e59b48d556ee13d780b6..32e81319dfe87dda5d6eeaa680aed00836bd77ae 100644 (file)
@@ -388,15 +388,18 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                        return true;
 
                entity _player;
-               float _team = 0;
-               float found = false;
+               int _team = 0;
+               bool found = false;
 
                if(cmd_argc == 2)
                {
-                       if(argv(1) == "red")
-                               _team = NUM_TEAM_1;
-                       else
-                               _team = NUM_TEAM_2;
+                       switch(argv(1))
+                       {
+                               case "red": _team = NUM_TEAM_1; break;
+                               case "blue": _team = NUM_TEAM_2; break;
+                               case "yellow": if(ctf_teams >= 3) _team = NUM_TEAM_3; break;
+                               case "pink": if(ctf_teams >= 4) _team = NUM_TEAM_4; break;
+                       }
                }
 
                FOR_EACH_PLAYER(_player)
index 177e4bc98ce1a5bb7b58beea21f6bd5e2dc1e5c3..d349405bdcc1668274b95b0069fdff479399de20 100644 (file)
@@ -53,7 +53,7 @@ void spawnpoint_use()
                self.team = activator.team;
                some_spawn_has_been_used = 1;
        }
-       LOG_INFO("spawnpoint was used!\n");
+       //LOG_INFO("spawnpoint was used!\n");
 }
 
 void relocate_spawnpoint()
index b654d83caf2af105857004642c06701259e7c691..e697001c18145e96233de28a8bfba1e436f59503 100644 (file)
@@ -6,4 +6,6 @@ float spawnpoint_nag;
 float SpawnEvent_Send(entity to, int sf);
 entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck);
 entity SelectSpawnPoint (float anypoint);
+void spawnfunc_info_player_deathmatch();
+void spawnpoint_use();
 #endif
index 47165c7732921b1f2c1b21da16658c2c9d7dc352..671f1d0eda5cc63d49f9e380ddab6cd56ddf3310 100644 (file)
@@ -75,6 +75,26 @@ void ItemDrawSimple()
     }
 }
 
+void Item_PreDraw()
+{
+       vector org;
+       float alph;
+       org = getpropertyvec(VF_ORIGIN);
+       if(!checkpvs(org, self)) // this makes sense as long as we don't support recursive warpzones
+               alph = 0;
+       else if(self.fade_start)
+               alph = bound(0, (self.fade_end - vlen(org - self.origin - 0.5 * (self.mins + self.maxs))) / (self.fade_end - self.fade_start), 1);
+       else
+               alph = 1;
+       //printf("%v <-> %v\n", view_origin, self.origin + 0.5 * (self.mins + self.maxs));
+       if(self.ItemStatus & ITS_AVAILABLE)
+               self.alpha = alph;
+       if(alph <= 0)
+               self.drawmask = 0;
+       else
+               self.drawmask = MASK_NORMAL;
+}
+
 void ItemRead(float _IsNew)
 {SELFPARAM();
     int sf = ReadByte();
@@ -90,21 +110,16 @@ void ItemRead(float _IsNew)
 
     if(sf & ISF_ANGLES)
     {
-        self.angles_x = ReadCoord();
-        self.angles_y = ReadCoord();
-        self.angles_z = ReadCoord();
+        self.angles_x = ReadAngle();
+        self.angles_y = ReadAngle();
+        self.angles_z = ReadAngle();
         self.move_angles = self.angles;
     }
 
     if(sf & ISF_SIZE)
     {
-        self.mins_x = ReadCoord();
-        self.mins_y = ReadCoord();
-        self.mins_z = ReadCoord();
-        self.maxs_x = ReadCoord();
-        self.maxs_y = ReadCoord();
-        self.maxs_z = ReadCoord();
-        setsize(self, self.mins, self.maxs);
+        float use_bigsize = ReadByte();
+        setsize(self, '-16 -16 0', (use_bigsize) ? '16 16 48' : '16 16 32');
     }
 
     if(sf & ISF_STATUS) // need to read/write status frist so model can handle simple, fb etc.
@@ -150,9 +165,14 @@ void ItemRead(float _IsNew)
     if(sf & ISF_MODEL)
     {
         self.drawmask  = MASK_NORMAL;
-        self.movetype  = MOVETYPE_TOSS;
+               self.move_movetype = self.movetype = MOVETYPE_TOSS;
         self.draw       = ItemDraw;
 
+        self.fade_end = ReadShort();
+        self.fade_start = ReadShort();
+        if(self.fade_start && !autocvar_cl_items_nofade)
+               self.predraw = Item_PreDraw;
+
         if(self.mdl)
             strunzone(self.mdl);
 
@@ -164,8 +184,6 @@ void ItemRead(float _IsNew)
             string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
             self.draw = ItemDrawSimple;
 
-
-
             if(fexists(sprintf("%s%s.md3", _fn2, autocvar_cl_simpleitems_postfix)))
                 self.mdl = strzone(sprintf("%s%s.md3", _fn2, autocvar_cl_simpleitems_postfix));
             else if(fexists(sprintf("%s%s.dpm", _fn2, autocvar_cl_simpleitems_postfix)))
@@ -230,63 +248,60 @@ void ItemRead(float _IsNew)
 #ifdef SVQC
 bool ItemSend(entity to, int sf)
 {SELFPARAM();
-    if(self.gravity)
-        sf |= ISF_DROP;
-    else
-        sf &= ~ISF_DROP;
+       if(self.gravity)
+               sf |= ISF_DROP;
+       else
+               sf &= ~ISF_DROP;
 
        WriteByte(MSG_ENTITY, ENT_CLIENT_ITEM);
        WriteByte(MSG_ENTITY, sf);
 
        //WriteByte(MSG_ENTITY, self.cnt);
-    if(sf & ISF_LOCATION)
-    {
-        WriteCoord(MSG_ENTITY, self.origin.x);
-        WriteCoord(MSG_ENTITY, self.origin.y);
-        WriteCoord(MSG_ENTITY, self.origin.z);
-    }
+       if(sf & ISF_LOCATION)
+       {
+               WriteCoord(MSG_ENTITY, self.origin.x);
+               WriteCoord(MSG_ENTITY, self.origin.y);
+               WriteCoord(MSG_ENTITY, self.origin.z);
+       }
 
-    if(sf & ISF_ANGLES)
-    {
-        WriteCoord(MSG_ENTITY, self.angles.x);
-        WriteCoord(MSG_ENTITY, self.angles.y);
-        WriteCoord(MSG_ENTITY, self.angles.z);
-    }
+       if(sf & ISF_ANGLES)
+       {
+               WriteAngle(MSG_ENTITY, self.angles_x);
+               WriteAngle(MSG_ENTITY, self.angles_y);
+               WriteAngle(MSG_ENTITY, self.angles_z);
+       }
 
-    if(sf & ISF_SIZE)
-    {
-        WriteCoord(MSG_ENTITY, self.mins.x);
-        WriteCoord(MSG_ENTITY, self.mins.y);
-        WriteCoord(MSG_ENTITY, self.mins.z);
-        WriteCoord(MSG_ENTITY, self.maxs.x);
-        WriteCoord(MSG_ENTITY, self.maxs.y);
-        WriteCoord(MSG_ENTITY, self.maxs.z);
-    }
+       if(sf & ISF_SIZE)
+       {
+               WriteByte(MSG_ENTITY, ((self.flags & FL_POWERUP) || self.health || self.armorvalue));
+       }
 
-    if(sf & ISF_STATUS)
-        WriteByte(MSG_ENTITY, self.ItemStatus);
+       if(sf & ISF_STATUS)
+               WriteByte(MSG_ENTITY, self.ItemStatus);
 
-    if(sf & ISF_MODEL)
-    {
+       if(sf & ISF_MODEL)
+       {
+               WriteShort(MSG_ENTITY, self.fade_end);
+               WriteShort(MSG_ENTITY, self.fade_start);
 
-        if(self.mdl == "")
-            LOG_TRACE("^1WARNING!^7 self.mdl is unset for item ", self.classname, "exspect a crash just aboute now\n");
+               if(self.mdl == "")
+                       LOG_TRACE("^1WARNING!^7 self.mdl is unset for item ", self.classname, "exspect a crash just aboute now\n");
 
-        WriteString(MSG_ENTITY, self.mdl);
-    }
+               WriteString(MSG_ENTITY, self.mdl);
+       }
 
 
-    if(sf & ISF_COLORMAP)
-        WriteShort(MSG_ENTITY, self.colormap);
+       if(sf & ISF_COLORMAP)
+               WriteShort(MSG_ENTITY, self.colormap);
 
-    if(sf & ISF_DROP)
-    {
-        WriteCoord(MSG_ENTITY, self.velocity.x);
-        WriteCoord(MSG_ENTITY, self.velocity.y);
-        WriteCoord(MSG_ENTITY, self.velocity.z);
-    }
+       if(sf & ISF_DROP)
+       {
+               WriteCoord(MSG_ENTITY, self.velocity.x);
+               WriteCoord(MSG_ENTITY, self.velocity.y);
+               WriteCoord(MSG_ENTITY, self.velocity.z);
+       }
 
-    return true;
+       return true;
 }
 
 void ItemUpdate(entity item)
@@ -383,21 +398,21 @@ void Item_Show (entity e, float mode)
        }
 
        if (e.items & ITEM_Strength.m_itemid || e.items & ITEM_Shield.m_itemid)
-           e.ItemStatus |= ITS_POWERUP;
+               e.ItemStatus |= ITS_POWERUP;
 
        if (autocvar_g_nodepthtestitems)
                e.effects |= EF_NODEPTHTEST;
 
 
-    if (autocvar_g_fullbrightitems)
+       if (autocvar_g_fullbrightitems)
                e.ItemStatus |= ITS_ALLOWFB;
 
        if (autocvar_sv_simple_items)
-        e.ItemStatus |= ITS_ALLOWSI;
+               e.ItemStatus |= ITS_ALLOWSI;
 
        // relink entity (because solid may have changed)
        setorigin(e, e.origin);
-    e.SendFlags |= ISF_STATUS;
+       e.SendFlags |= ISF_STATUS;
 }
 
 void Item_Think()
@@ -668,6 +683,13 @@ float Item_GiveTo(entity item, entity player)
        if (!pickedup)
                return 0;
 
+       // crude hack to enforce switching weapons
+       if(g_cts && (item.flags & FL_WEAPON))
+       {
+               W_SwitchWeapon_Force(player, item.weapon);
+               return 1;
+       }
+
        if (_switchweapon)
                if (player.switchweapon != w_getbestweapon(player))
                        W_SwitchWeapon_Force(player, w_getbestweapon(player));
@@ -740,6 +762,7 @@ void Item_Touch (void)
                        for(head = world; (head = findfloat(head, team, self.team)); )
                        {
                                if(head.flags & FL_ITEM)
+                               if(head.classname != "item_flag_team" && head.classname != "item_key_team")
                                {
                                        Item_Show(head, -1);
                                        RandomSelection_Add(head, 0, string_null, head.cnt, 0);
@@ -781,13 +804,17 @@ void Item_FindTeam()
                // marker for item team search
                LOG_TRACE("Initializing item team ", ftos(self.team), "\n");
                RandomSelection_Init();
-               for(head = world; (head = findfloat(head, team, self.team)); ) if(head.flags & FL_ITEM)
+               for(head = world; (head = findfloat(head, team, self.team)); )
+               if(head.flags & FL_ITEM)
+               if(head.classname != "item_flag_team" && head.classname != "item_key_team")
                        RandomSelection_Add(head, 0, string_null, head.cnt, 0);
                e = RandomSelection_chosen_ent;
                e.state = 0;
                Item_Show(e, 1);
 
-               for(head = world; (head = findfloat(head, team, self.team)); ) if(head.flags & FL_ITEM)
+               for(head = world; (head = findfloat(head, team, self.team)); )
+               if(head.flags & FL_ITEM)
+               if(head.classname != "item_flag_team" && head.classname != "item_key_team")
                {
                        if(head != e)
                        {
@@ -806,6 +833,7 @@ void Item_FindTeam()
 // TODO: perhaps nice special effect?
 void RemoveItem(void)
 {SELFPARAM();
+       if(wasfreed(self) || !self) { return; }
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
        remove(self);
 }
@@ -962,6 +990,12 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
        self.items = itemid;
        self.weapon = weaponid;
 
+       if(!self.fade_end)
+       {
+               self.fade_start = autocvar_g_items_mindist;
+               self.fade_end = autocvar_g_items_maxdist;
+       }
+
        if(weaponid)
                self.weapons = WepSet_FromWeapon(weaponid);
 
@@ -1023,6 +1057,9 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                        return;
                }
 
+               if(self.angles != '0 0 0')
+                       self.SendFlags |= ISF_ANGLES;
+
                self.reset = Item_Reset;
                // it's a level item
                if(self.spawnflags & 1)
@@ -1041,7 +1078,7 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                                setsize (self, '-16 -16 0', '16 16 48');
                        else
                                setsize (self, '-16 -16 0', '16 16 32');
-
+                       self.SendFlags |= ISF_SIZE;
                        // note droptofloor returns false if stuck/or would fall too far
                        droptofloor();
                        waypoint_spawnforitem(self);
@@ -1106,29 +1143,31 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
        //self.effects |= EF_LOWPRECISION;
 
        if((itemflags & FL_POWERUP) || self.health || self.armorvalue)
-    {
-        self.pos1 = '-16 -16 0';
-        self.pos2 = '16 16 48';
-    }
+       {
+               self.pos1 = '-16 -16 0';
+               self.pos2 = '16 16 48';
+       }
        else
-    {
-        self.pos1 = '-16 -16 0';
-        self.pos2 = '16 16 32';
-    }
-    setsize (self, self.pos1, self.pos2);
+       {
+               self.pos1 = '-16 -16 0';
+               self.pos2 = '16 16 32';
+       }
+       setsize (self, self.pos1, self.pos2);
 
-    if(itemflags & FL_POWERUP)
-        self.ItemStatus |= ITS_ANIMATE1;
+       self.SendFlags |= ISF_SIZE;
+
+       if(itemflags & FL_POWERUP)
+               self.ItemStatus |= ITS_ANIMATE1;
 
        if(self.armorvalue || self.health)
-        self.ItemStatus |= ITS_ANIMATE2;
+               self.ItemStatus |= ITS_ANIMATE2;
 
        if(itemflags & FL_WEAPON)
        {
                if (self.classname != "droppedweapon") // if dropped, colormap is already set up nicely
-            self.colormap = 1024; // color shirt=0 pants=0 grey
-        else
-            self.gravity = 1;
+                       self.colormap = 1024; // color shirt=0 pants=0 grey
+               else
+                       self.gravity = 1;
 
                self.ItemStatus |= ITS_ANIMATE1;
                self.ItemStatus |= ISF_COLORMAP;
@@ -1146,11 +1185,7 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
        else
                Item_Reset();
 
-    Net_LinkEntity(self, false, 0, ItemSend);
-
-       self.SendFlags |= ISF_SIZE;
-       if(self.angles)
-               self.SendFlags |= ISF_ANGLES;
+       Net_LinkEntity(self, !((itemflags & FL_POWERUP) || self.health || self.armorvalue), 0, ItemSend);
 
        // call this hook after everything else has been done
        if(MUTATOR_CALLHOOK(Item_Spawn, self))
index 35cce6178d8a3ec4ca3078c72f5c4e74251a91de..d93e28bb611053773784fb08612df1f16ba83fdb 100644 (file)
@@ -30,13 +30,6 @@ const int IT_PLASMA                                  =   65536;
        #define IT_KEY1                                                 131072
        // -Wdouble-declaration
        #define IT_KEY2                                                 262144
-       // for players:
-       const int IT_RED_FLAG_TAKEN             =   32768;
-       const int IT_RED_FLAG_LOST              =   65536;
-       const int IT_RED_FLAG_CARRYING          =   98304;
-       const int IT_BLUE_FLAG_TAKEN            =  131072;
-       const int IT_BLUE_FLAG_LOST             =  262144;
-       const int IT_BLUE_FLAG_CARRYING         =  393216;
 // end
 
 const int IT_5HP                               =  524288;
@@ -69,6 +62,9 @@ const int ISF_SIZE                            = 128;
 
 .int ItemStatus;
 
+.float fade_start;
+.float fade_end;
+
 #ifdef CSQC
 
 float  autocvar_cl_animate_items = 1;
index 25adab26d519d87239af7603e2cbb137a3c448e6..22dbac33284a32b53f7d91a65515e4c764cf746e 100644 (file)
@@ -141,6 +141,8 @@ void InitGameplayMode()
                ActivateTeamplay();
                fraglimit_override = autocvar_g_keyhunt_point_limit;
                leadlimit_override = autocvar_g_keyhunt_point_leadlimit;
+               if(autocvar_g_keyhunt_team_spawns)
+                       have_team_spawns = -1; // request team spawns
                MUTATOR_ADD(gamemode_keyhunt);
        }
 
@@ -296,7 +298,7 @@ string getwelcomemessage(void)
                else
                        modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena");
        }
-       if(cvar("g_balance_blaster_weaponstart") == 0)
+       else if(cvar("g_balance_blaster_weaponstart") == 0)
                modifications = strcat(modifications, ", No start weapons");
        if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
                modifications = strcat(modifications, ", Low gravity");
@@ -343,6 +345,12 @@ string getwelcomemessage(void)
                s = strcat(s, "\n\n^8special gameplay tips: ^7", cache_mutatormsg);
        }
 
+       string mutator_msg = "";
+       MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
+       mutator_msg = ret_string;
+
+       s = strcat(s, mutator_msg); // trust that the mutator will do proper formatting
+
        motd = autocvar_sv_motd;
        if (motd != "") {
                s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd));