turn NIX into a mutator; fix keyhunt
authorRudolf Polzer <rpolzer@nb-04.(none)>
Fri, 19 Mar 2010 20:28:17 +0000 (21:28 +0100)
committerRudolf Polzer <rpolzer@nb-04.(none)>
Fri, 19 Mar 2010 20:28:17 +0000 (21:28 +0100)
14 files changed:
qcsrc/server/cl_client.qc
qcsrc/server/cl_physics.qc
qcsrc/server/cl_weapons.qc
qcsrc/server/defs.qh
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/base.qh
qcsrc/server/mutators/gamemode_keyhunt.qh [new file with mode: 0644]
qcsrc/server/mutators/mutator_nix.qc [new file with mode: 0644]
qcsrc/server/mutators/mutators.qh [new file with mode: 0644]
qcsrc/server/progs.src
qcsrc/server/sv_main.qc
qcsrc/server/t_items.qc
qcsrc/server/teamplay.qc

index 0d163e72a978184bfce021269c17b559bd562f8d..f7be50277e62b0301c1f1fec5c93891537bcf25a 100644 (file)
@@ -582,7 +582,6 @@ void PutObserverInServer (void)
        }
 
        DropAllRunes(self);
-       MUTATOR_CALLHOOK(MakePlayerObserver);
 
        Portal_ClearAll(self);
 
@@ -697,6 +696,8 @@ void PutObserverInServer (void)
        }
        else
                self.frags = FRAGS_SPECTATOR;
+
+       MUTATOR_CALLHOOK(MakePlayerObserver);
 }
 
 float RestrictSkin(float s)
@@ -993,7 +994,6 @@ void PutClientInServer (void)
                }
 
                self.cnt = WEP_LASER;
-               self.nixnex_lastchange_id = -1;
 
                CL_SpawnWeaponentity();
                self.alpha = default_player_alpha;
@@ -1028,8 +1028,8 @@ void PutClientInServer (void)
                target_voicescript_clear(self);
 
                // reset fields the weapons may use
-        for (j = WEP_FIRST; j <= WEP_LAST; ++j)
-            weapon_action(j, WR_RESETPLAYER);
+               for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+                       weapon_action(j, WR_RESETPLAYER);
 
                oldself = self;
                self = spot;
@@ -1037,6 +1037,8 @@ void PutClientInServer (void)
                                SUB_UseTargets();
                        activator = world;
                self = oldself;
+
+               MUTATOR_CALLHOOK(PlayerSpawn);
        } else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) {
                PutObserverInServer ();
        }
@@ -2509,8 +2511,6 @@ void PlayerPreThink (void)
                        self.effects = self.effects - (self.effects & EF_NODRAW);
                }
 
-               Nixnex_GiveCurrentWeapon();
-
                if(frametime > 0) // don't do this in cl_movement frames, just in server ticks
                        UpdateSelectedPlayer();
 
index 56823b3e2988e4b301aefee956b7b0be38a585d1..4c2280099dc2f0b08e5e86de9466c898c733913b 100644 (file)
@@ -542,7 +542,6 @@ void PM_AirAccelerate(vector wishdir, float wishspeed)
 .vector v_angle_old;
 .string lastclassname;
 
-void Nixnex_GiveCurrentWeapon();
 .float() PlayerPhysplug;
 
 string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
index 4a1281424e39eb8b51c993e3d6460318cf5b9f33..788a67e517a4e13e102eebddeb49268e8944f265 100644 (file)
@@ -267,12 +267,12 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
        w = self.weapon;
        if (w == 0)
                return; // just in case
+       if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon))
+               return;
        if (g_weaponarena)
                return;
        if (g_lms)
                return;
-       if (g_nixnex)
-               return;
        if (g_nexball && w == WEP_GRENADE_LAUNCHER)
                return;
        if (!cvar("g_pickup_items"))
@@ -425,131 +425,3 @@ void W_WeaponFrame()
                self.currentammo = 1;
 #endif
 };
-
-float nixnex_weapon;
-float nixnex_weapon_ammo;
-float nixnex_nextchange;
-float nixnex_nextweapon;
-float nixnex_nextweapon_ammo;
-.float nixnex_lastchange_id;
-.float nixnex_lastinfotime;
-.float nixnex_nextincr;
-
-float NixNex_CanChooseWeapon(float wpn)
-{
-       entity e;
-       e = get_weaponinfo(wpn);
-       if(!e.weapons) // skip dummies
-               return FALSE;
-       if(g_weaponarena)
-       {
-               if not(g_weaponarena & e.weapons)
-                       return FALSE;
-       }
-       else
-       {
-               if(wpn == WEP_LASER && g_nixnex_with_laser)
-                       return FALSE;
-               if not(e.spawnflags & WEP_FLAG_NORMAL)
-                       return FALSE;
-       }
-       return TRUE;
-}
-void Nixnex_ChooseNextWeapon()
-{
-       float j;
-       RandomSelection_Init();
-       for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-               if(NixNex_CanChooseWeapon(j))
-                       RandomSelection_Add(world, j, string_null, 1, (j != nixnex_weapon));
-       nixnex_nextweapon = RandomSelection_chosen_float;
-       nixnex_nextweapon_ammo = W_AmmoItemCode(nixnex_nextweapon);
-}
-
-void Nixnex_GiveCurrentWeapon()
-{
-       float dt;
-       if(g_nixnex)
-       {
-               if(!nixnex_nextweapon)
-                       Nixnex_ChooseNextWeapon();
-
-               dt = ceil(nixnex_nextchange - time);
-
-               if(dt <= 0)
-               {
-                       nixnex_weapon = nixnex_nextweapon;
-                       nixnex_weapon_ammo = nixnex_nextweapon_ammo;
-                       nixnex_nextweapon = 0;
-                       nixnex_nextchange = time + cvar("g_balance_nixnex_roundtime");
-                       //weapon_action(nixnex_weapon, WR_PRECACHE); // forget it, too slow
-               }
-               
-               if(nixnex_nextchange != self.nixnex_lastchange_id) // this shall only be called once per round!
-               {
-                       self.nixnex_lastchange_id = nixnex_nextchange;
-                       if (self.items & IT_UNLIMITED_WEAPON_AMMO)
-                       {
-                               self.ammo_shells = (nixnex_weapon_ammo & IT_SHELLS) ?
-                                       cvar("g_pickup_shells_max") : 0;
-                               self.ammo_nails = (nixnex_weapon_ammo & IT_NAILS) ?
-                                       cvar("g_pickup_nails_max") : 0;
-                               self.ammo_rockets = (nixnex_weapon_ammo & IT_ROCKETS) ?
-                                       cvar("g_pickup_rockets_max") : 0;
-                               self.ammo_cells = (nixnex_weapon_ammo & IT_CELLS) ?
-                                       cvar("g_pickup_cells_max") : 0;
-                               self.ammo_fuel = (nixnex_weapon_ammo & IT_FUEL) ?
-                                       cvar("g_pickup_fuel_max") : 0;
-                       }
-                       else
-                       {
-                               self.ammo_shells = (nixnex_weapon_ammo & IT_SHELLS) ?
-                                       cvar("g_balance_nixnex_ammo_shells") : 0;
-                               self.ammo_nails = (nixnex_weapon_ammo & IT_NAILS) ?
-                                       cvar("g_balance_nixnex_ammo_nails") : 0;
-                               self.ammo_rockets = (nixnex_weapon_ammo & IT_ROCKETS) ?
-                                       cvar("g_balance_nixnex_ammo_rockets") : 0;
-                               self.ammo_cells = (nixnex_weapon_ammo & IT_CELLS) ?
-                                       cvar("g_balance_nixnex_ammo_cells") : 0;
-                               self.ammo_fuel = (nixnex_weapon_ammo & IT_FUEL) ?
-                                       cvar("g_balance_nixnex_ammo_fuel") : 0;
-                       }
-                       self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
-                       if(dt >= 1 && dt <= 5)
-                               self.nixnex_lastinfotime = -42;
-                       else
-                               centerprint(self, strcat("\n\n^2Active weapon: ^3", W_Name(nixnex_weapon)));
-               }
-               if(self.nixnex_lastinfotime != dt)
-               {
-                       self.nixnex_lastinfotime = dt; // initial value 0 should count as "not seen"
-                       if(dt >= 1 && dt <= 5)
-                               centerprint(self, strcat("^3", ftos(dt), "^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nixnex_nextweapon), "\n"));
-               }
-
-               if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nixnex_nextincr)
-               {
-                       if (nixnex_weapon_ammo & IT_SHELLS)
-                               self.ammo_shells = self.ammo_shells + cvar("g_balance_nixnex_ammoincr_shells");
-                       else if (nixnex_weapon_ammo & IT_NAILS)
-                               self.ammo_nails = self.ammo_nails + cvar("g_balance_nixnex_ammoincr_nails");
-                       else if (nixnex_weapon_ammo & IT_ROCKETS)
-                               self.ammo_rockets = self.ammo_rockets + cvar("g_balance_nixnex_ammoincr_rockets");
-                       else if (nixnex_weapon_ammo & IT_CELLS)
-                               self.ammo_cells = self.ammo_cells + cvar("g_balance_nixnex_ammoincr_cells");
-                       if (nixnex_weapon_ammo & IT_FUEL) // hook uses cells and fuel
-                               self.ammo_fuel = self.ammo_fuel + cvar("g_balance_nixnex_ammoincr_fuel");
-                       self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
-               }
-
-               self.weapons = 0;
-               if(g_nixnex_with_laser)
-                       self.weapons = self.weapons | WEPBIT_LASER;
-               self.weapons = self.weapons | W_WeaponBit(nixnex_weapon);
-
-               if(self.switchweapon != nixnex_weapon)
-                       if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
-                               if(client_hasweapon(self, nixnex_weapon, TRUE, FALSE))
-                                       W_SwitchWeapon(nixnex_weapon);
-       }
-}
index bc9e300ebf77dfa94c61880b6eba6aeb83f9ee09..e80025a676e30e27fe43b44838d40b0fabec59d8 100644 (file)
@@ -18,7 +18,7 @@ float require_spawnfunc_prefix; // if this float exists, only functions with spa
 float ctf_score_value(string parameter);
 
 float g_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_ca, g_lms, g_runematch, g_race, g_nexball, g_cts;
-float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_laserguided_missile, g_midair, g_minstagib, g_nixnex, g_nixnex_with_laser, g_pinata, g_norecoil, g_vampire, g_minstagib_invis_alpha, g_bloodloss;
+float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_laserguided_missile, g_midair, g_minstagib, g_pinata, g_norecoil, g_vampire, g_minstagib_invis_alpha, g_bloodloss;
 float g_warmup_limit;
 float g_warmup_allguns;
 float g_warmup_allow_timeout;
index ad9341e2d0f947e6aec137e193b3b5f0650d8a4d..228782748d2aa6fd160719863791434b2fae502e 100644 (file)
@@ -539,6 +539,11 @@ void spawnfunc_worldspawn (void)
 
                GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
                s = ":gameinfo:mutators:LIST";
+
+               ret_string = s;
+               MUTATOR_CALLHOOK(BuildMutatorsString);
+               s = ret_string;
+
                if(cvar("g_grappling_hook"))
                        s = strcat(s, ":grappling_hook");
                if(!cvar("g_use_ammunition"))
@@ -547,8 +552,6 @@ void spawnfunc_worldspawn (void)
                        s = strcat(s, ":no_pickup_items");
                if(cvar_string("g_weaponarena") != "0")
                        s = strcat(s, ":", cvar_string("g_weaponarena"), " arena");
-               if(cvar("g_nixnex"))
-                       s = strcat(s, ":nixnex");
                if(cvar("g_vampire"))
                        s = strcat(s, ":vampire");
                if(cvar("g_laserguided_missile"))
index 16f4a33fbbdf9abb4901af37fa3b9f6429a7b107..d9c5ca6ebca8ff3072669c679020a39bf5a84c3f 100644 (file)
@@ -896,7 +896,6 @@ float want_weapon(string cvarprefix, entity weaponinfo, float allguns)
        return t;
 }
 
-float NixNex_CanChooseWeapon(float wpn);
 void readplayerstartcvars()
 {
        entity e;
@@ -977,17 +976,7 @@ void readplayerstartcvars()
        else
                g_weaponarena_random = 0;
 
-       if (g_nixnex)
-       {
-               start_weapons = 0;
-               // will be done later
-               for (i = WEP_FIRST; i <= WEP_LAST; ++i)
-                       if (NixNex_CanChooseWeapon(i))
-                               weapon_action(i, WR_PRECACHE);
-               if(!cvar("g_use_ammunition"))
-                       start_items |= IT_UNLIMITED_AMMO;
-       }
-       else if (g_weaponarena)
+       if (g_weaponarena)
        {
                start_weapons = g_weaponarena;
                if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
@@ -1027,7 +1016,7 @@ void readplayerstartcvars()
                        start_health = cvar("g_lms_start_health");
                        start_armorvalue = cvar("g_lms_start_armor");
                }
-               else if (cvar("g_use_ammunition"))
+               else
                {
                        start_ammo_shells = cvar("g_start_ammo_shells");
                        start_ammo_nails = cvar("g_start_ammo_nails");
@@ -1035,24 +1024,12 @@ void readplayerstartcvars()
                        start_ammo_cells = cvar("g_start_ammo_cells");
                        start_ammo_fuel = cvar("g_start_ammo_fuel");
                }
-               else
-               {
-                       start_ammo_shells = cvar("g_pickup_shells_max");
-                       start_ammo_nails = cvar("g_pickup_nails_max");
-                       start_ammo_rockets = cvar("g_pickup_rockets_max");
-                       start_ammo_cells = cvar("g_pickup_cells_max");
-                       start_ammo_fuel = cvar("g_pickup_fuel_max");
-                       start_items |= IT_UNLIMITED_AMMO;
-               }
 
                for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
                        e = get_weaponinfo(i);
                        if(want_weapon("g_start_weapon_", e, FALSE))
-                       {
                                start_weapons |= e.weapons;
-                               weapon_action(e.weapon, WR_PRECACHE);
-                       }
                }
        }
 
@@ -1067,16 +1044,13 @@ void readplayerstartcvars()
                warmup_start_armorvalue = start_armorvalue;
                warmup_start_weapons = start_weapons;
 
-               if (!g_weaponarena && !g_nixnex && !g_minstagib && !g_ca)
+               if (!g_weaponarena && !g_minstagib && !g_ca)
                {
-                       if (cvar("g_use_ammunition"))
-                       {
-                               warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
-                               warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
-                               warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
-                               warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
-                               warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
-                       }
+                       warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
+                       warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
+                       warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
+                       warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
+                       warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
                        warmup_start_health = cvar("g_warmup_start_health");
                        warmup_start_armorvalue = cvar("g_warmup_start_armor");
                        warmup_start_weapons = 0;
@@ -1084,10 +1058,7 @@ void readplayerstartcvars()
                        {
                                e = get_weaponinfo(i);
                                if(want_weapon("g_start_weapon_", e, cvar("g_warmup_allguns")))
-                               {
                                        warmup_start_weapons |= e.weapons;
-                                       weapon_action(e.weapon, WR_PRECACHE);
-                               }
                        }
                }
        }
@@ -1100,6 +1071,22 @@ void readplayerstartcvars()
                warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
        }
 
+       if(!cvar("g_use_ammunition"))
+       {
+               start_ammo_shells = cvar("g_pickup_shells_max");
+               start_ammo_nails = cvar("g_pickup_nails_max");
+               start_ammo_rockets = cvar("g_pickup_rockets_max");
+               start_ammo_cells = cvar("g_pickup_cells_max");
+               start_ammo_fuel = cvar("g_pickup_fuel_max");
+               start_items |= IT_UNLIMITED_AMMO;
+               warmup_start_ammo_shells = cvar("g_pickup_shells_max");
+               warmup_start_ammo_nails = cvar("g_pickup_nails_max");
+               warmup_start_ammo_rockets = cvar("g_pickup_rockets_max");
+               warmup_start_ammo_cells = cvar("g_pickup_cells_max");
+               warmup_start_ammo_fuel = cvar("g_pickup_fuel_max");
+               //warmup_start_items |= IT_UNLIMITED_AMMO;
+       }
+
        if (g_jetpack)
                start_items |= IT_JETPACK;
 
@@ -1117,6 +1104,15 @@ void readplayerstartcvars()
                if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel;
        }
 
+       MUTATOR_CALLHOOK(SetStartItems);
+
+       for (i = WEP_FIRST; i <= WEP_LAST; ++i)
+       {
+               e = get_weaponinfo(i);
+               if(e.weapons & (start_weapons | warmup_start_weapons))
+                       weapon_action(e.weapon, WR_PRECACHE);
+       }
+
        start_ammo_shells = max(0, start_ammo_shells);
        start_ammo_nails = max(0, start_ammo_nails);
        start_ammo_cells = max(0, start_ammo_cells);
@@ -1163,6 +1159,10 @@ float sv_accuracy_data_share;
 
 void readlevelcvars(void)
 {
+       // first load all the mutators
+       if(cvar("g_nix"))
+               MUTATOR_ADD(mutator_nix);
+
     g_bugrigs = cvar("g_bugrigs");
     g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
     g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
@@ -1205,8 +1205,6 @@ void readlevelcvars(void)
        g_laserguided_missile = cvar("g_laserguided_missile");
        g_midair = cvar("g_midair");
        g_minstagib = cvar("g_minstagib");
-       g_nixnex = cvar("g_nixnex");
-       g_nixnex_with_laser = cvar("g_nixnex_with_laser");
        g_norecoil = cvar("g_norecoil");
        g_vampire = cvar("g_vampire");
        g_bloodloss = cvar("g_bloodloss");
@@ -1239,10 +1237,6 @@ void readlevelcvars(void)
        g_pickup_respawntimejitter_long = cvar("g_pickup_respawntimejitter_long");
        g_pickup_respawntimejitter_powerup = cvar("g_pickup_respawntimejitter_powerup");
 
-       if (g_minstagib) g_nixnex = g_weaponarena = 0;
-       if (g_nixnex) g_weaponarena = 0;
-               g_weaponarena = 0;
-
        g_weaponspeedfactor = cvar("g_weaponspeedfactor");
        g_weaponratefactor = cvar("g_weaponratefactor");
        g_weapondamagefactor = cvar("g_weapondamagefactor");
@@ -1669,7 +1663,7 @@ void precache()
         precache_sound ("weapons/hook_impact.wav"); // hook
     }
 
-    if (cvar("sv_precacheweapons") || g_nixnex)
+    if(cvar("sv_precacheweapons"))
     {
         //precache weapon models/sounds
         local float wep;
index 56f20f7f73b9b3d75badde1b035363f4cd9b9e4b..11ea2f6645d5bac0a5db844b92caf9684ef06bee 100644 (file)
@@ -38,9 +38,17 @@ void Mutator_Remove(float(float) func); // calls error() on fail
 // register all possible hooks here
 MUTATOR_HOOKABLE(MakePlayerObserver);
 MUTATOR_HOOKABLE(MakePlayerSpectator);
+MUTATOR_HOOKABLE(PlayerSpawn);
 MUTATOR_HOOKABLE(ClientDisconnect);
 MUTATOR_HOOKABLE(PlayerDies); entity other; entity frag_attacker;
 MUTATOR_HOOKABLE(GiveFragsForKill); entity frag_attacker, frag_target; float frag_score;
 MUTATOR_HOOKABLE(MatchEnd);
 MUTATOR_HOOKABLE(GetTeamCount); float ret_float;
 MUTATOR_HOOKABLE(SpectateCopy); entity other;
+MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon);
+MUTATOR_HOOKABLE(SetStartItems);
+MUTATOR_HOOKABLE(BuildMutatorsString); string ret_string;
+MUTATOR_HOOKABLE(BuildMutatorsPrettyString); string ret_string;
+MUTATOR_HOOKABLE(FilterItem); // return error to request removal, or change self.items or self.weapons
+MUTATOR_HOOKABLE(OnEntityPreSpawn); // return error to prevent entity spawn, or modify the entity
+MUTATOR_HOOKABLE(PlayerPreThink);
diff --git a/qcsrc/server/mutators/gamemode_keyhunt.qh b/qcsrc/server/mutators/gamemode_keyhunt.qh
new file mode 100644 (file)
index 0000000..71f25c3
--- /dev/null
@@ -0,0 +1,12 @@
+// ALL OF THESE should be removed in the future, as other code should not have
+// to care
+
+// used by bots:
+float kh_tracking_enabled;
+.entity kh_next;
+float kh_Key_AllOwnedByWhichTeam();
+
+// used by arena.qc ready-restart:
+typedef void(void) kh_Think_t;
+void kh_StartRound();
+void kh_Controller_SetThink(float t, string msg, kh_Think_t func);
diff --git a/qcsrc/server/mutators/mutator_nix.qc b/qcsrc/server/mutators/mutator_nix.qc
new file mode 100644 (file)
index 0000000..a855cb7
--- /dev/null
@@ -0,0 +1,227 @@
+float g_nix, g_nix_with_laser;
+
+float nix_weapon;
+float nix_weapon_ammo;
+float nix_nextchange;
+float nix_nextweapon;
+float nix_nextweapon_ammo;
+.float nix_lastchange_id;
+.float nix_lastinfotime;
+.float nix_nextincr;
+
+float NIX_CanChooseWeapon(float wpn)
+{
+       entity e;
+       e = get_weaponinfo(wpn);
+       if(!e.weapons) // skip dummies
+               return FALSE;
+       if(g_weaponarena)
+       {
+               if not(g_weaponarena & e.weapons)
+                       return FALSE;
+       }
+       else
+       {
+               if(wpn == WEP_LASER && g_nix_with_laser)
+                       return FALSE;
+               if not(e.spawnflags & WEP_FLAG_NORMAL)
+                       return FALSE;
+       }
+       return TRUE;
+}
+void NIX_ChooseNextWeapon()
+{
+       float j;
+       RandomSelection_Init();
+       for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+               if(NIX_CanChooseWeapon(j))
+                       RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
+       nix_nextweapon = RandomSelection_chosen_float;
+       nix_nextweapon_ammo = W_AmmoItemCode(nix_nextweapon);
+}
+
+void NIX_GiveCurrentWeapon()
+{
+       float dt;
+
+       if(!nix_nextweapon)
+               NIX_ChooseNextWeapon();
+
+       dt = ceil(nix_nextchange - time);
+
+       if(dt <= 0)
+       {
+               nix_weapon = nix_nextweapon;
+               nix_weapon_ammo = nix_nextweapon_ammo;
+               nix_nextweapon = 0;
+               nix_nextchange = time + cvar("g_balance_nix_roundtime");
+               //weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow
+       }
+       
+       if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
+       {
+               self.nix_lastchange_id = nix_nextchange;
+               if (self.items & IT_UNLIMITED_WEAPON_AMMO)
+               {
+                       self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
+                               cvar("g_pickup_shells_max") : 0;
+                       self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
+                               cvar("g_pickup_nails_max") : 0;
+                       self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
+                               cvar("g_pickup_rockets_max") : 0;
+                       self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
+                               cvar("g_pickup_cells_max") : 0;
+                       self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
+                               cvar("g_pickup_fuel_max") : 0;
+               }
+               else
+               {
+                       self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
+                               cvar("g_balance_nix_ammo_shells") : 0;
+                       self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
+                               cvar("g_balance_nix_ammo_nails") : 0;
+                       self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
+                               cvar("g_balance_nix_ammo_rockets") : 0;
+                       self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
+                               cvar("g_balance_nix_ammo_cells") : 0;
+                       self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
+                               cvar("g_balance_nix_ammo_fuel") : 0;
+               }
+               self.nix_nextincr = time + cvar("g_balance_nix_incrtime");
+               if(dt >= 1 && dt <= 5)
+                       self.nix_lastinfotime = -42;
+               else
+                       centerprint(self, strcat("\n\n^2Active weapon: ^3", W_Name(nix_weapon)));
+       }
+       if(self.nix_lastinfotime != dt)
+       {
+               self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
+               if(dt >= 1 && dt <= 5)
+                       centerprint(self, strcat("^3", ftos(dt), "^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon), "\n"));
+       }
+
+       if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
+       {
+               if (nix_weapon_ammo & IT_SHELLS)
+                       self.ammo_shells = self.ammo_shells + cvar("g_balance_nix_ammoincr_shells");
+               else if (nix_weapon_ammo & IT_NAILS)
+                       self.ammo_nails = self.ammo_nails + cvar("g_balance_nix_ammoincr_nails");
+               else if (nix_weapon_ammo & IT_ROCKETS)
+                       self.ammo_rockets = self.ammo_rockets + cvar("g_balance_nix_ammoincr_rockets");
+               else if (nix_weapon_ammo & IT_CELLS)
+                       self.ammo_cells = self.ammo_cells + cvar("g_balance_nix_ammoincr_cells");
+               if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel
+                       self.ammo_fuel = self.ammo_fuel + cvar("g_balance_nix_ammoincr_fuel");
+               self.nix_nextincr = time + cvar("g_balance_nix_incrtime");
+       }
+
+       self.weapons = 0;
+       if(g_nix_with_laser)
+               self.weapons = self.weapons | WEPBIT_LASER;
+       self.weapons = self.weapons | W_WeaponBit(nix_weapon);
+
+       if(self.switchweapon != nix_weapon)
+               if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
+                       if(client_hasweapon(self, nix_weapon, TRUE, FALSE))
+                               W_SwitchWeapon(nix_weapon);
+}
+
+MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
+{
+       return 1; // no throwing in NIX
+}
+
+MUTATOR_HOOKFUNCTION(nix_SetStartItems)
+{
+       float i;
+       start_weapons = 0; // will be done later, when player spawns
+       warmup_start_weapons = 0; // will be done later, when player spawns
+       for (i = WEP_FIRST; i <= WEP_LAST; ++i)
+               if (NIX_CanChooseWeapon(i))
+                       weapon_action(i, WR_PRECACHE);
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
+{
+       ret_string = strcat(ret_string, ":NIX");
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
+{
+       ret_string = strcat(ret_string, ", NIX");
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_FilterItem)
+{
+       switch (self.items)
+       {
+               case IT_HEALTH:
+               case IT_5HP:
+               case IT_25HP:
+               case IT_ARMOR:
+               case IT_ARMOR_SHARD:
+                       if (cvar("g_nix_with_healtharmor"))
+                               return 0;
+                       break;
+               case IT_STRENGTH:
+               case IT_INVINCIBLE:
+                       if (cvar("g_nix_with_powerups"))
+                               return 0;
+                       break;
+       }
+
+       return 1; // delete all other items
+}
+
+MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
+{
+       if(self.classname == "target_items") // items triggers cannot work in nixnex (as they change weapons/ammo)
+               return 1;
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
+{
+       if(!intermission_running)
+       if(self.deadflag != DEAD_NO)
+       if(self.classname == "player")
+               NIX_GiveCurrentWeapon();
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
+{
+       self.nix_lastchange_id = -1;
+       return 0;
+}
+
+MUTATOR_DEFINITION(mutator_nix)
+{
+       MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
+       MUTATOR_HOOK(SetStartItems, nix_SetStartItems, CBC_ORDER_EXCLUSIVE);
+       MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
+       MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
+       MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
+       MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
+
+       MUTATOR_ONADD
+       {
+               g_nix = 1;
+               g_nix_with_laser = cvar("g_nix_with_laser");
+
+               nix_nextchange = time;
+       }
+
+       MUTATOR_ONREMOVE
+       {
+               error("NIX currently cannot be shut down.");
+               g_nix = 0;
+       }
+
+       return 0;
+}
diff --git a/qcsrc/server/mutators/mutators.qh b/qcsrc/server/mutators/mutators.qh
new file mode 100644 (file)
index 0000000..bbaad86
--- /dev/null
@@ -0,0 +1,3 @@
+MUTATOR_DECLARATION(gamemode_keyhunt);
+
+MUTATOR_DECLARATION(mutator_nix);
index b74d3b9143730689733166f64e579440678479a3..8b9014071e8fccbd07a1e70f6158be5d46c788b2 100644 (file)
@@ -21,6 +21,7 @@ constants.qh
 defs.qh                // Should rename this, it has fields and globals
 
 mutators/base.qh
+mutators/mutators.qh
 mutators/gamemode_keyhunt.qh // TODO fix this
 
 //// tZork Turrets ////
@@ -171,6 +172,7 @@ cheats.qc
 
 mutators/base.qc
 mutators/gamemode_keyhunt.qc
+mutators/mutator_nix.qc
 
 ../warpzonelib/anglestransform.qc
 ../warpzonelib/mathlib.qc
index 7713125235be848a8e5d46a8e276212a6d5ecd7d..f9eb9d2a0a41cb6fbf36c1653df8d28f8f7c1ba8 100644 (file)
@@ -395,4 +395,10 @@ void SV_OnEntityPreSpawnFunction()
                self.angles_z = self.angles_z + (random() * 2 - 1) * self.anglesjitter_z;
        if(self.anglejitter != 0)
                self.angles_y = self.angles_y + (random() * 2 - 1) * self.anglejitter;
+
+       if(MUTATOR_CALLHOOK(OnEntityPreSpawn))
+       {
+               remove(self);
+               return;
+       }
 }
index 04328de873f246593fe148514231adab3fe6821c..6025578a904b3f3c00b323ee8b456095fe7f8365 100644 (file)
@@ -709,6 +709,19 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
        }
        else
        {
+               self.items = itemid;
+               self.weapons = weaponid;
+
+               if(MUTATOR_CALLHOOK(FilterItem)) // error means we do not want the item
+               {
+                       startitem_failed = TRUE;
+                       remove(self);
+                       return;
+               }
+
+               itemid = self.items;
+               weaponid = self.weapons;
+
                self.reset = Item_Reset;
                // it's a level item
                if(self.spawnflags & 1)
@@ -815,35 +828,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                                return;
                        }
                }
-               else if (g_nixnex)
-               {
-                       local float rm;
-
-                       rm = 1;
-                       switch (itemid)
-                       {
-                               case IT_HEALTH:
-                               case IT_5HP:
-                               case IT_25HP:
-                               case IT_ARMOR:
-                               case IT_ARMOR_SHARD:
-                                       if (cvar("g_nixnex_with_healtharmor"))
-                                               rm = 0;
-                                       break;
-                               case IT_STRENGTH:
-                               case IT_INVINCIBLE:
-                                       if (cvar("g_nixnex_with_powerups"))
-                                               rm = 0;
-                                       break;
-                       }
-
-                       if(rm)
-                       {
-                               startitem_failed = TRUE;
-                               remove (self);
-                               return;
-                       }
-               }
                else if (!cvar("g_pickup_items") && itemid != IT_STRENGTH && itemid != IT_INVINCIBLE && itemid != IT_HEALTH)
                {
                        startitem_failed = TRUE;
@@ -877,8 +861,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                self.respawntimejitter = defaultrespawntimejitter;
        }
        self.netname = itemname;
-       self.items = itemid;
-       self.weapons = weaponid;
        self.flags = FL_ITEM | itemflags;
        self.touch = Item_Touch;
        setmodel (self, self.mdl); // precision set below
@@ -1370,13 +1352,6 @@ void spawnfunc_target_items (void)
        float n, i, j;
        entity e;
 
-       if(g_nixnex)
-       {
-               // items triggers cannot work in nixnex (as they change weapons/ammo)
-               remove(self);
-               return;
-       }
-
        self.use = target_items_use;
        if(!self.strength_finished)
                self.strength_finished = cvar("g_balance_powerup_strength_time");
index 02e4467a1dad6837465576337060fc61f6cb973f..4e1c16728c36cad00c6da719f7279f962e337976 100644 (file)
@@ -489,11 +489,12 @@ void PrintWelcomeMessage(entity pl)
        }
 
 :normal
-       modifications = "";
+       ret_string = "";
+       MUTATOR_CALLHOOK(BuildMutatorsPrettyString);
+       modifications = ret_string;
+       
        if(g_minstagib)
                modifications = strcat(modifications, ", MinstaGib");
-       if(g_nixnex)
-               modifications = strcat(modifications, ", NixNex");
        if(g_weaponarena)
        {
                if(g_weaponarena_random)