From: Rudolf Polzer Date: Fri, 19 Mar 2010 20:28:17 +0000 (+0100) Subject: turn NIX into a mutator; fix keyhunt X-Git-Tag: xonotic-v0.1.0preview~685 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=06fc7068ee7c4795ad7b8dd6150ebf3481a10485;p=xonotic%2Fxonotic-data.pk3dir.git turn NIX into a mutator; fix keyhunt --- diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 0d163e72a..f7be50277 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -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(); diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc index 56823b3e2..4c2280099 100644 --- a/qcsrc/server/cl_physics.qc +++ b/qcsrc/server/cl_physics.qc @@ -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 "; diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc index 4a1281424..788a67e51 100644 --- a/qcsrc/server/cl_weapons.qc +++ b/qcsrc/server/cl_weapons.qc @@ -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); - } -} diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index bc9e300eb..e80025a67 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -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; diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index ad9341e2d..228782748 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -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")) diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 16f4a33fb..d9c5ca6eb 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -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; diff --git a/qcsrc/server/mutators/base.qh b/qcsrc/server/mutators/base.qh index 56f20f7f7..11ea2f664 100644 --- a/qcsrc/server/mutators/base.qh +++ b/qcsrc/server/mutators/base.qh @@ -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 index 000000000..71f25c3a8 --- /dev/null +++ b/qcsrc/server/mutators/gamemode_keyhunt.qh @@ -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 index 000000000..a855cb717 --- /dev/null +++ b/qcsrc/server/mutators/mutator_nix.qc @@ -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 index 000000000..bbaad86c2 --- /dev/null +++ b/qcsrc/server/mutators/mutators.qh @@ -0,0 +1,3 @@ +MUTATOR_DECLARATION(gamemode_keyhunt); + +MUTATOR_DECLARATION(mutator_nix); diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index b74d3b914..8b9014071 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -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 diff --git a/qcsrc/server/sv_main.qc b/qcsrc/server/sv_main.qc index 771312523..f9eb9d2a0 100644 --- a/qcsrc/server/sv_main.qc +++ b/qcsrc/server/sv_main.qc @@ -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; + } } diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc index 04328de87..6025578a9 100644 --- a/qcsrc/server/t_items.qc +++ b/qcsrc/server/t_items.qc @@ -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"); diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index 02e4467a1..4e1c16728 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -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)