From: Mario Date: Tue, 11 Jun 2013 04:58:46 +0000 (+1000) Subject: Merge branch 'Mario/rifle_arena' into Mario/mutators X-Git-Tag: xonotic-v0.8.0~366^2~23 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=6ea5f1a79adeb12782110c6fbbbbef4b81a52a13;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'Mario/rifle_arena' into Mario/mutators --- 6ea5f1a79adeb12782110c6fbbbbef4b81a52a13 diff --cc mutators.cfg index 054a32c0a,000000000..b3e8ab94b mode 100644,000000..100644 --- a/mutators.cfg +++ b/mutators.cfg @@@ -1,147 -1,0 +1,158 @@@ +// ========================= +// Config for all mutators +// ========================= + + +// ========= +// dodging +// ========= +set g_dodging 0 "set to 1 to enable dodging in games" + +seta cl_dodging_timeout 0.2 "determines how long apart (in seconds) two taps on the same direction key are considered a dodge. use 0 to disable" + +set sv_dodging_wall_dodging 0 "set to 1 to allow dodging off walls. 0 to disable" +set sv_dodging_delay 0.5 "determines how long a player has to wait to be able to dodge again after dodging" +set sv_dodging_up_speed 200 "the jump velocity of the dodge" +set sv_dodging_horiz_speed 400 "the horizontal velocity of the dodge" +set sv_dodging_ramp_time 0.1 "a ramp so that the horizontal part of the dodge is added smoothly (seconds)" +set sv_dodging_height_threshold 10 "the maximum height above ground where to allow dodging" +set sv_dodging_wall_distance_threshold 10 "the maximum distance from a wall that still allows dodging" +set sv_dodging_sound 1 "if 1 dodging makes a sound. if 0 dodging is silent" + + +// =========== +// minstagib +// =========== +set g_minstagib 0 "enable minstagib" +set g_minstagib_extralives 1 "how many extra lives you will get per powerup" +set g_minstagib_ammo_start 10 "starting ammo" +set g_minstagib_ammo_drop 5 "how much ammo you'll get for weapons or cells" +set g_minstagib_invis_alpha 0.15 +set g_minstagib_speed_highspeed 1.5 "speed-multiplier that applies while you carry the invincibility powerup" + + +// ========= +// vampire +// ========= +set g_vampire 0 "set to 1 to enable the vampire mode, where the damage done to your opponent gets added to your own health" + + +// ========= +// sandbox +// ========= +set g_sandbox 0 "allow players to spawn and edit objects around the map" +set g_sandbox_info 1 "print object information to the server. 1 prints info about spawned / removed objects, 2 also prints info about edited objects" +set g_sandbox_readonly 0 "when this mode is active, players cannot modify objects or use any sandbox commands" +set g_sandbox_storage_name default "name of the selected storage to use" +set g_sandbox_storage_autosave 5 "storage is automatically saved every specified number of seconds" +set g_sandbox_storage_autoload 1 "if a storage file exists for the given map, automatically load it at startup" +set g_sandbox_editor_flood 1 "players must wait this many seconds between spawning objects" +set g_sandbox_editor_maxobjects 1000 "maximum number of objects that may exist at a time" +set g_sandbox_editor_free 1 "0 = players can only copy or edit their own objects, 1 = players can copy but not edit other objects, 2 = players can copy and edit all object" +set g_sandbox_editor_distance_spawn 200 "distance at which objects spawn in front of the player" +set g_sandbox_editor_distance_edit 300 "distance at which players can edit or remove objects they are looking at" +set g_sandbox_object_scale_min 0.1 "minimum scale that objects can be set to" +set g_sandbox_object_scale_max 2 "maximum scale that objects can be set to" +set g_sandbox_object_material_velocity_min 100 "velocity objects must have while colliding for material effects to be applied" +set g_sandbox_object_material_velocity_factor 0.002 "velocity range which decides the intensity of material effects" +set cl_sandbox_clipboard "" + + +// ======================== +// invincible projectiles +// ======================== +set g_invincible_projectiles 0 "set to 1 to disable any damage to projectiles in all balance configs, regardless of g_projectiles_damage" + + +// =============== +// rocket flying +// =============== +set g_rocket_flying 0 "set to 1 to enable rocket flying in all balance configs" + + +// ===================== +// spawn near teammate +// ===================== +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" + + +// ======================== +// NIX (No Items Xonotic) +// ======================== +// at each time, everyone uses the same weapon, +// and in regular intervals, this weapon is cycled +set g_nix 0 "No Items Xonotic - instead of pickup items, everyone plays with the same weapon. After some time, a countdown will start, after which everyone will switch to another weapon, and so on" +set g_nix_with_laser 0 "always carry the laser as an additional weapon in NIX" +set g_nix_with_healtharmor 0 "when 1, health and armor still show up in NIX" +set g_nix_with_powerups 0 "when 1, powerups still show up in NIX" + + +// ================ +// physical items +// ================ +set g_physical_items 0 "1 uses ODE physics for dropped weapons, 2 for all items, requires physics_ode to be enabled" +set g_physical_items_damageforcescale 3 "how affected physical weapons are by damage" +set g_physical_items_reset 1 "return map items to their original lotation after being picked up" + + +// =============== +// touch explode +// =============== +set g_touchexplode 0 "touching other players causes an explosion" +set g_touchexplode_radius 50 +set g_touchexplode_damage 10 +set g_touchexplode_edgedamage 0 +set g_touchexplode_force 150 + + +// ================ +// super spectate +// ================ +set g_superspectate 0 "server side, allows extended spectator functions through the cmd interface. followpowerup, followstrength, followstshield or followfc [red|blue] will transfer spectation to the relevent player, if any" + + +// ================== +// melee only arena +// ================== +set g_melee_only 0 "enable melee only arena" + + +// ================ +// random gravity +// ================ +set g_random_gravity 0 "enable random gravity mutator" +set g_random_gravity_delay 3 "delay between gravity changes" +set g_random_gravity_negative_chance 0.5 "chance of gravity being a negative value" +set g_random_gravity_min -2000 "minimum gravity" +set g_random_gravity_max 2000 "maximum gravity" +set g_random_gravity_positive 1000 "positive gravity multiplier" +set g_random_gravity_negative 1000 "negative gravity multiplier" + + +// ======= +// nades +// ======= +set g_nades 0 "enable off-hand grenades" +set g_nades_spawn 1 "give nades right away when player spawns rather than delaying entire refire" +set g_nades_nade_lifetime 3.5 +set g_nades_nade_minforce 400 +set g_nades_nade_maxforce 2000 +set g_nades_nade_health 25 +set g_nades_nade_refire 6 +set g_nades_nade_damage 225 +set g_nades_nade_edgedamage 90 +set g_nades_nade_radius 300 +set g_nades_nade_force 650 +set g_nades_nade_newton_style 0 ++ ++ ++// ============= ++// rifle arena ++// ============= ++set g_riflearena 0 ++set g_riflearena_rifle_secondary_spread 0 ++set g_riflearena_rifle_secondary_shots 1 ++set g_riflearena_rifle_secondary_animtime 0.15 ++set g_riflearena_rifle_secondary_refire 0.15 ++set g_riflearena_rifle_secondary_damage 40 diff --cc qcsrc/common/notifications.qh index 576743222,d85c1911e..853b71744 --- a/qcsrc/common/notifications.qh +++ b/qcsrc/common/notifications.qh @@@ -476,7 -475,7 +476,7 @@@ void Send_Notification_WOVA MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_FIRE, 0, 0, "", NO_CPID, "0 0", _("^K1You got a little bit too crispy!"), _("^K1You felt a little too hot!")) \ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_GENERIC, 0, 0, "", NO_CPID, "0 0", _("^K1You killed your own dumb self!"), _("^K1You need to be more careful!")) \ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_LAVA, 0, 0, "", NO_CPID, "0 0", _("^K1You couldn't stand the heat!"), "") \ - MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE, 0, 0, "", NO_CPID, "0 0", _("^K1You forgot to put the pin back in!"), _("^K1Try throwing the nade!")) \ - MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE, 0, 0, "", NO_CPID, "0 0", _("^K1You ate your own grenade!"), _("^K1Tastes like chicken!")) \ ++ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE, 0, 0, "", NO_CPID, "0 0", _("^K1You forgot to put the pin back in!"), _("^K1Tastes like chicken!")) \ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NOAMMO, 0, 0, "", NO_CPID, "0 0", _("^K1You were killed for running out of ammo..."), _("^K1You are respawning for running out of ammo...")) \ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_ROT, 0, 0, "", NO_CPID, "0 0", _("^K1You grew too old without taking your medicine"), _("^K1You need to preserve your health")) \ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_SHOOTING_STAR, 0, 0, "", NO_CPID, "0 0", _("^K1You became a shooting star!"), "") \ diff --cc qcsrc/server/miscfunctions.qc index 6e8b5d16a,b0aa2c12d..8489c8a46 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@@ -915,17 -919,8 +915,18 @@@ void readlevelcvars(void CHECK_MUTATOR_ADD("g_rocket_flying", mutator_rocketflying, !cvar("g_minstagib")); CHECK_MUTATOR_ADD("g_vampire", mutator_vampire, !cvar("g_minstagib")); CHECK_MUTATOR_ADD("g_superspectate", mutator_superspec, 1); + CHECK_MUTATOR_ADD("g_pinata", mutator_pinata, !cvar("g_minstagib")); + CHECK_MUTATOR_ADD("g_midair", mutator_midair, 1); + CHECK_MUTATOR_ADD("g_bloodloss", mutator_bloodloss, !cvar("g_minstagib")); + CHECK_MUTATOR_ADD("g_random_gravity", mutator_random_gravity, 1); + CHECK_MUTATOR_ADD("g_norecoil", mutator_norecoil, 1); + CHECK_MUTATOR_ADD("g_multijump", mutator_multijump, 1); + CHECK_MUTATOR_ADD("g_jump_grunt", mutator_jump_grunt, 1); + CHECK_MUTATOR_ADD("g_footsteps", mutator_footsteps, 1); + CHECK_MUTATOR_ADD("g_melee_only", mutator_melee_only, !cvar("g_minstagib")); + CHECK_MUTATOR_ADD("g_nades", mutator_nades, 1); CHECK_MUTATOR_ADD("g_sandbox", sandbox, 1); + CHECK_MUTATOR_ADD("g_riflearena", mutator_riflearena, !cvar("g_minstagib")); #undef CHECK_MUTATOR_ADD diff --cc qcsrc/server/mutators/mutator_nades.qc index 4466ccf53,000000000..a7c0fea51 mode 100644,000000..100644 --- a/qcsrc/server/mutators/mutator_nades.qc +++ b/qcsrc/server/mutators/mutator_nades.qc @@@ -1,405 -1,0 +1,405 @@@ +.entity nade; +.entity fake_nade; +.float nade_refire; + +void nade_timer_think() +{ + self.skin = 8 - (self.owner.wait - time) / (autocvar_g_nades_nade_lifetime / 10); + self.nextthink = time; + if(!self.owner || wasfreed(self.owner)) + remove(self); + +} + +void nade_burn_spawn(entity _nade) +{ + float p; + + switch(_nade.realowner.team) + { + case NUM_TEAM_1: p = PROJECTILE_NADE_RED_BURN; break; + case NUM_TEAM_2: p = PROJECTILE_NADE_BLUE_BURN; break; + case NUM_TEAM_3: p = PROJECTILE_NADE_YELLOW_BURN; break; + case NUM_TEAM_4: p = PROJECTILE_NADE_PINK_BURN; break; + default: p = PROJECTILE_NADE_BURN; break; + } + + CSQCProjectile(_nade, TRUE, p, TRUE); +} + +void nade_spawn(entity _nade) +{ + float p; + entity timer = spawn(); + setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3"); + setattachment(timer, _nade, ""); + timer.classname = "nade_timer"; + timer.colormap = _nade.colormap; + timer.glowmod = _nade.glowmod; + timer.think = nade_timer_think; + timer.nextthink = time; + timer.wait = _nade.wait; + timer.owner = _nade; + timer.skin = 10; + + switch(_nade.realowner.team) + { + case NUM_TEAM_1: p = PROJECTILE_NADE_RED; break; + case NUM_TEAM_2: p = PROJECTILE_NADE_BLUE; break; + case NUM_TEAM_3: p = PROJECTILE_NADE_YELLOW; break; + case NUM_TEAM_4: p = PROJECTILE_NADE_PINK; break; + default: p = PROJECTILE_NADE; break; + } + + CSQCProjectile(_nade, TRUE, p, TRUE); + +} + +void nade_boom() // TODO: DamageInfo +{ + string expef; + + switch(self.realowner.team) + { + case NUM_TEAM_1: expef = "nade_red_explode"; break; + case NUM_TEAM_2: expef = "nade_blue_explode"; break; + case NUM_TEAM_3: expef = "nade_yellow_explode"; break; + case NUM_TEAM_4: expef = "nade_pink_explode"; break; + default: expef = "nade_explode"; break; + } + + sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum(expef), self.origin + '0 0 1', '0 0 0', 1); + + self.takedamage = DAMAGE_NO; + RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, + autocvar_g_nades_nade_radius, self, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy); + + remove(self); +} + +void nade_touch() +{ + PROJECTILE_TOUCH; + //setsize(self, '-2 -2 -2', '2 2 2'); + //UpdateCSQCProjectile(self); + if(self.health == autocvar_g_nades_nade_health) + { + spamsound(self, CH_SHOTS, strcat("weapons/grenade_bounce", ftos(1 + rint(random() * 5)), ".wav"), VOL_BASE, ATTN_NORM); + return; + } + + self.enemy = other; + nade_boom(); +} + +void nade_beep() +{ + sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.ogg", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX)); + self.think = nade_boom; + self.nextthink = max(self.wait, time); +} + +void nade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if(DEATH_ISWEAPON(deathtype, WEP_LASER)) + return; + + if(DEATH_ISWEAPON(deathtype, WEP_NEX) || DEATH_ISWEAPON(deathtype, WEP_MINSTANEX)) + { + force *= 6; + damage = autocvar_g_nades_nade_health * 0.55; + } + + if(DEATH_ISWEAPON(deathtype, WEP_UZI)) + damage = autocvar_g_nades_nade_health * 0.1; + + if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) && !(deathtype & HITTYPE_SECONDARY)) + damage = autocvar_g_nades_nade_health * 1.1; + + if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) && (deathtype & HITTYPE_SECONDARY)) + { + damage = autocvar_g_nades_nade_health * 0.1; + force *= 15; + } + + self.velocity += force; + + if(!damage) + return; + + if(self.health == autocvar_g_nades_nade_health) + { + sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX)); + self.nextthink = max(time + autocvar_g_nades_nade_lifetime, time); + self.think = nade_beep; + } + + self.health -= damage; + self.realowner = attacker; + + if(self.health <= 0) + W_PrepareExplosionByDamage(attacker, nade_boom); + else + nade_burn_spawn(self); +} + +void toss_nade(entity e, vector _velocity, float _time) +{ + entity _nade = e.nade; + e.nade = world; + + remove(e.fake_nade); + e.fake_nade = world; + + makevectors(e.v_angle); + + W_SetupShot(e, FALSE, FALSE, "", CH_WEAPON_A, 0); + + Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_NADES); + + //setorigin(_nade, CENTER_OR_VIEWOFS(e) + (v_right * 10) * -1); + setorigin(_nade, w_shotorg + (v_right * 10) * -1); + setmodel(_nade, "models/weapons/v_ok_grenade.md3"); + setattachment(_nade, world, ""); + PROJECTILE_MAKETRIGGER(_nade); + setsize(_nade, '-16 -16 -16', '16 16 16'); + _nade.movetype = MOVETYPE_BOUNCE; + + tracebox(_nade.origin, _nade.mins, _nade.maxs, _nade.origin, FALSE, _nade); + if (trace_startsolid) + setorigin(_nade, e.origin); + + if(e.crouch) + _nade.velocity = '0 0 -10'; + else if(autocvar_g_nades_nade_newton_style == 1) + _nade.velocity = e.velocity + _velocity; + else if(autocvar_g_nades_nade_newton_style == 2) + _nade.velocity = _velocity; + else + _nade.velocity = W_CalculateProjectileVelocity(e.velocity, _velocity, TRUE); + + //_nade.solid = SOLID_BBOX; // TODO: remember why this was needed + _nade.touch = nade_touch; + _nade.health = autocvar_g_nades_nade_health; + _nade.takedamage = DAMAGE_AIM; + _nade.event_damage = nade_damage; + _nade.teleportable = TRUE; + _nade.pushable = TRUE; + _nade.gravity = 1; + _nade.missile_flags = MIF_SPLASH | MIF_ARC; + _nade.damagedbycontents = TRUE; + _nade.angles = vectoangles(_nade.velocity); + _nade.flags = FL_PROJECTILE; + + nade_spawn(_nade); + + if(_time) + { + _nade.think = nade_boom; + _nade.nextthink = _time; + } + + e.nade_refire = time + autocvar_g_nades_nade_refire; +} + +void nade_prime() +{ + if(self.nade) + remove(self.nade); + + if(self.fake_nade) + remove(self.fake_nade); + + self.nade = spawn(); + setmodel(self.nade, "null"); + setattachment(self.nade, self, "bip01 l hand"); + self.nade.classname = "nade"; + self.nade.realowner = self; + self.nade.colormap = self.colormap; + self.nade.glowmod = self.glowmod; + self.nade.wait = time + autocvar_g_nades_nade_lifetime; + self.nade.lifetime = time; + self.nade.think = nade_beep; + self.nade.nextthink = max(self.nade.wait - 3, time); + self.nade.projectiledeathtype = DEATH_NADE; + + self.fake_nade = spawn(); + setmodel(self.fake_nade, "models/weapons/h_ok_grenade.iqm"); + setattachment(self.fake_nade, self.weaponentity, ""); + self.fake_nade.classname = "fake_nade"; + //self.fake_nade.viewmodelforclient = self; + self.fake_nade.realowner = self.fake_nade.owner = self; + self.fake_nade.colormap = self.colormap; + self.fake_nade.glowmod = self.glowmod; + self.fake_nade.think = SUB_Remove; + self.fake_nade.nextthink = self.nade.wait; +} + +float CanThrowNade() +{ + if(self.vehicle) + return FALSE; + + if(gameover) + return FALSE; + + if(self.deadflag != DEAD_NO) + return FALSE; + + if not(autocvar_g_nades) + return FALSE; // allow turning them off mid match + + if(forbidWeaponUse()) + return FALSE; + + if not(IS_PLAYER(self)) + return FALSE; + + return TRUE; +} + +MUTATOR_HOOKFUNCTION(nades_ForbidThrowing) +{ + if(!g_weaponarena || !g_minstagib) - return FALSE; // TODO: fix this to support all modes that don't disable weapon dropping ++ return FALSE; // TODO: fix this to support all modes that disable weapon dropping + + if(!CanThrowNade()) + return FALSE; + + if(!self.nade) + { + if(self.nade_refire < time) + { + Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE_THROW); + nade_prime(); + self.nade_refire = time + autocvar_g_nades_nade_refire; + } + } + else + { + if(time - self.nade.lifetime >= 1) + { + makevectors(self.v_angle); + float _force = time - self.nade.lifetime; + _force /= autocvar_g_nades_nade_lifetime; + _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce)); + toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0); + } + } + + return TRUE; +} + +MUTATOR_HOOKFUNCTION(nades_VehicleEnter) +{ + if(other.nade) + toss_nade(other, '0 0 100', max(other.nade.wait, time + 0.05)); + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(nades_PlayerPreThink) +{ + float key_pressed = ((g_grappling_hook || client_hasweapon(self, WEP_HOOK, FALSE, FALSE) || WEPSET_CONTAINS_AW(weaponsInMap, WEP_HOOK)) ? self.button16 : self.BUTTON_HOOK); + + if(self.nade) + if(self.nade.wait - 0.1 <= time) + toss_nade(self, '0 0 0', time + 0.05); + + if(CanThrowNade()) + if(self.nade_refire < time) + { + if(key_pressed) + { + if(!self.nade) + nade_prime(); + } + else if(time - self.nade.lifetime >= 1) + { + if(self.nade) + { + makevectors(self.v_angle); + float _force = time - self.nade.lifetime; + _force /= autocvar_g_nades_nade_lifetime; + _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce)); + toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0); + } + } + } + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(nades_PlayerSpawn) +{ + if(autocvar_g_nades_spawn) + self.nade_refire = time + autocvar_g_spawnshieldtime; + else + self.nade_refire = time + autocvar_g_nades_nade_refire; + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(nades_PlayerDies) +{ + if(self.nade) + toss_nade(self, '0 0 100', max(self.nade.wait, time + 0.05)); + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(nades_RemovePlayer) +{ + if(self.nade) + remove(self.nade); + + if(self.fake_nade) + remove(self.fake_nade); + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(nades_BuildMutatorsString) +{ + ret_string = strcat(ret_string, ":Nades"); + return FALSE; +} + +MUTATOR_HOOKFUNCTION(nades_BuildMutatorsPrettyString) +{ + ret_string = strcat(ret_string, ", Nades"); + return FALSE; +} + +MUTATOR_DEFINITION(mutator_nades) +{ + MUTATOR_HOOK(ForbidThrowCurrentWeapon, nades_ForbidThrowing, CBC_ORDER_ANY); + MUTATOR_HOOK(VehicleEnter, nades_VehicleEnter, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerPreThink, nades_PlayerPreThink, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerSpawn, nades_PlayerSpawn, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerDies, nades_PlayerDies, CBC_ORDER_ANY); + MUTATOR_HOOK(MakePlayerObserver, nades_RemovePlayer, CBC_ORDER_ANY); + MUTATOR_HOOK(ClientDisconnect, nades_RemovePlayer, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsString, nades_BuildMutatorsString, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsPrettyString, nades_BuildMutatorsPrettyString, CBC_ORDER_ANY); + + MUTATOR_ONADD + { + precache_model("models/ok_nade_counter/ok_nade_counter.md3"); + + precache_model("models/weapons/h_ok_grenade.iqm"); + precache_model("models/weapons/v_ok_grenade.md3"); + precache_sound("weapons/rocket_impact.wav"); + precache_sound("weapons/grenade_bounce1.wav"); + precache_sound("weapons/grenade_bounce2.wav"); + precache_sound("weapons/grenade_bounce3.wav"); + precache_sound("weapons/grenade_bounce4.wav"); + precache_sound("weapons/grenade_bounce5.wav"); + precache_sound("weapons/grenade_bounce6.wav"); + precache_sound("overkill/grenadebip.ogg"); + } + + return FALSE; +} diff --cc qcsrc/server/mutators/mutator_riflearena.qc index 000000000,540f70d35..b1a65f469 mode 000000,100644..100644 --- a/qcsrc/server/mutators/mutator_riflearena.qc +++ b/qcsrc/server/mutators/mutator_riflearena.qc @@@ -1,0 -1,408 +1,119 @@@ -.entity ra_nade; -.float ra_nade_refire; - -float ra_CanThrowNade() -{ - if(self.vehicle) - return FALSE; - - if(gameover) - return FALSE; - - if(self.deadflag) - return FALSE; - - if not(IS_PLAYER(self)) - return FALSE; - - if not(autocvar_g_riflearena_nades) - return FALSE; - - if(forbidWeaponUse()) - return FALSE; - - return TRUE; -} - -void ra_nade_timer_think() -{ - self.skin = 8 - (self.owner.wait - time) / (autocvar_g_riflearena_nade_lifetime / 10); - self.nextthink = time; - if(!self.owner || wasfreed(self.owner)) - remove(self); - -} - -void ra_nade_burn_spawn(entity nade) -{ - switch(nade.realowner.team) - { - case NUM_TEAM_1: - CSQCProjectile(nade, TRUE, PROJECTILE_NADE_RED_BURN, TRUE); - break; - case NUM_TEAM_2: - CSQCProjectile(nade, TRUE, PROJECTILE_NADE_BLUE_BURN, TRUE); - break; - default: - CSQCProjectile(nade, TRUE, PROJECTILE_NADE_RED_BURN, TRUE); - break; - } -} - -void ra_nade_spawn(entity nade) -{ - entity timer = spawn(); - setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3"); - setattachment(timer, nade, ""); - timer.classname = "nade_timer"; - timer.colormap = nade.colormap; - timer.glowmod = nade.glowmod; - timer.think = ra_nade_timer_think; - timer.nextthink = time; - timer.wait = nade.wait; - timer.owner = nade; - timer.skin = 10; - - CSQCProjectile(nade, TRUE, ((nade.realowner.team == NUM_TEAM_2) ? PROJECTILE_NADE_BLUE: PROJECTILE_NADE_RED) , TRUE); - -} - -void ra_nade_boom() // TODO: DamageInfo -{ - sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); - sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - pointparticles(particleeffectnum((self.realowner.team == NUM_TEAM_2) ? "nade_blue_explode" : "nade_red_explode"), self.origin + '0 0 1', '0 0 0', 1); - - - self.takedamage = DAMAGE_NO; - RadiusDamage(self, self.realowner, autocvar_g_riflearena_nade_damage, autocvar_g_riflearena_nade_edgedamage, - autocvar_g_riflearena_nade_radius, self, autocvar_g_riflearena_nade_force, self.projectiledeathtype, self.enemy); - - remove(self); -} - -void ra_nade_touch() -{ - PROJECTILE_TOUCH; - setsize(self, '-2 -2 -2', '2 2 2'); - UpdateCSQCProjectile(self); - if(self.health == autocvar_g_riflearena_nade_health) - { - spamsound(self, CH_SHOTS, strcat("weapons/grenade_bounce", ftos(1 + rint(random() * 5)), ".wav"), VOL_BASE, ATTN_NORM); - return; - } - - self.enemy = other; - ra_nade_boom(); -} - -void ra_nade_beep() -{ - sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.wav", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX)); - self.think = ra_nade_boom; - self.nextthink = max(self.wait, time); -} - -void ra_nade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(DEATH_ISWEAPON(deathtype, WEP_LASER)) - return; - - self.velocity += force; - - if(!damage) - return; - - if(self.health == autocvar_g_riflearena_nade_health) - { - sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX)); - self.nextthink = max(time + autocvar_g_riflearena_nade_lifetime, time); - self.think = ra_nade_beep; - } - - self.health -= damage; - self.realowner = attacker; - - if(self.health <= 0) - W_PrepareExplosionByDamage(attacker, ra_nade_boom); - else - ra_nade_burn_spawn(self); -} - -void ra_toss_nade(entity ent, vector _velocity, float _time) -{ - entity _nade = ent.ra_nade; - ent.ra_nade = world; - - setorigin(_nade, gettaginfo(_nade, gettagindex(_nade, "Object001"))); - setattachment(_nade, world, ""); - PROJECTILE_MAKETRIGGER(_nade); - setsize(_nade, '-16 -16 -16', '16 16 16'); - _nade.movetype = MOVETYPE_BOUNCE; - - if(ent.crouch) - _nade.velocity = '0 0 -10'; - else if(autocvar_g_riflearena_nade_newton_style == 1) - _nade.velocity = ent.velocity + _velocity; - else if(autocvar_g_riflearena_nade_newton_style == 2) - _nade.velocity = _velocity; - else - _nade.velocity = W_CalculateProjectileVelocity(ent.velocity, _velocity, FALSE); - - _nade.solid = SOLID_BBOX; - _nade.touch = ra_nade_touch; - _nade.health = autocvar_g_riflearena_nade_health; - _nade.takedamage = DAMAGE_YES; - _nade.event_damage = ra_nade_damage; - _nade.teleportable = TRUE; - - ra_nade_spawn(_nade); - - if(_time) - { - _nade.think = ra_nade_boom; - _nade.nextthink = _time; - } - else - _nade.projectiledeathtype = DEATH_NADE_NORMAL; - - ent.ra_nade_refire = time + autocvar_g_riflearena_nade_refire; -} - -void ra_nade_prime() -{ - if(self.ra_nade) - remove(self.ra_nade); - - self.ra_nade = spawn(); - setmodel(self.ra_nade, "models/weapons/h_ok_grenade.iqm"); - setattachment(self.ra_nade, self.weaponentity, ""); - self.ra_nade.classname = "nade"; - self.ra_nade.realowner = self; - self.ra_nade.colormap = self.colormap; - self.ra_nade.glowmod = self.glowmod; - self.ra_nade.wait = time + autocvar_g_riflearena_nade_lifetime; - self.ra_nade.cnt = time; - self.ra_nade.think = ra_nade_beep; - self.ra_nade.nextthink = max(self.ra_nade.wait - 3, time); - self.ra_nade.projectiledeathtype = DEATH_NADE_NORMAL; -} - + void ra_SetCvars() + { + cvar_settemp("g_balance_rifle_secondary_spread", ftos(cvar("g_riflearena_rifle_secondary_spread"))); + cvar_settemp("g_balance_rifle_secondary_shots", ftos(cvar("g_riflearena_rifle_secondary_shots"))); + cvar_settemp("g_balance_rifle_secondary_animtime", ftos(cvar("g_riflearena_rifle_secondary_animtime"))); + cvar_settemp("g_balance_rifle_secondary_refire", ftos(cvar("g_riflearena_rifle_secondary_refire"))); + cvar_settemp("g_balance_rifle_secondary_damage", ftos(cvar("g_riflearena_rifle_secondary_damage"))); + } + -MUTATOR_HOOKFUNCTION(ra_VehicleEnter) -{ - if(other.ra_nade) - ra_toss_nade(other, '0 0 100', max(other.ra_nade.wait, time + 0.05)); - - return FALSE; -} - + MUTATOR_HOOKFUNCTION(ra_PlayerDamage) + { + if(IS_PLAYER(frag_attacker)) + if(IS_PLAYER(frag_target)) + { + if (DEATH_ISWEAPON(frag_deathtype, WEP_LASER)) + { + if(frag_attacker == frag_target) + frag_damage = 5; + else + frag_damage = 0; + if (frag_target != frag_attacker) + { + if (frag_target.health >= 1 && IS_PLAYER(frag_target)) + centerprint(frag_attacker, "Laser inflicts no damage!"); + frag_force = '0 0 0'; + } + } + } + + return FALSE; + } + + MUTATOR_HOOKFUNCTION(ra_PlayerSpawn) + { + WEPSET_CLEAR_E(self); + WEPSET_OR_EW(self, WEP_RIFLE); + WEPSET_OR_EW(self, WEP_LASER); + - self.ra_nade_refire = time + 2; - + return FALSE; + } + + MUTATOR_HOOKFUNCTION(ra_FilterItem) + { + switch (self.items) + { + case IT_5HP: + case IT_ARMOR_SHARD: + return FALSE; + } + + return TRUE; + } + -MUTATOR_HOOKFUNCTION(ra_PlayerThink) -{ - if(self.ra_nade) - if(self.ra_nade.wait - 0.1 <= time) - ra_toss_nade(self, '0 0 0', time + 0.05); - - if(ra_CanThrowNade()) - if(self.ra_nade_refire < time) - { - if(self.BUTTON_HOOK) - { - if(!self.ra_nade) - ra_nade_prime(); - } - else if(time - self.ra_nade.cnt >= 1) - { - if(self.ra_nade) - { - makevectors(self.v_angle); - float _force = time - self.ra_nade.cnt; - _force /= autocvar_g_riflearena_nade_lifetime; - _force = autocvar_g_riflearena_nade_minforce + (_force * (autocvar_g_riflearena_nade_maxforce - autocvar_g_riflearena_nade_minforce)); - ra_toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0); - } - } - } - - self.hasweapon_complain_spam = time + 5; // this isn't needed, so keep it off - - return FALSE; -} - -MUTATOR_HOOKFUNCTION(ra_RemovePlayer) -{ - if(self.ra_nade) - remove(self.ra_nade); - - return FALSE; -} - + MUTATOR_HOOKFUNCTION(ra_StartItems) + { + start_items |= IT_UNLIMITED_AMMO; + start_ammo_nails = 100; + + g_grappling_hook = 0; + + return FALSE; + } + -MUTATOR_HOOKFUNCTION(ra_PlayerDies) -{ - if(self.ra_nade) - ra_toss_nade(self, '0 0 100', max(self.ra_nade.wait, time + 0.05)); - - return 0; -} - + MUTATOR_HOOKFUNCTION(ra_ForbidThrowCurrentWeapon) + { - if(!ra_CanThrowNade()) - return 1; - - if(!self.ra_nade) - { - if(self.ra_nade_refire < time) - { - Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE); - ra_nade_prime(); - self.ra_nade_refire = time + autocvar_g_riflearena_nade_refire; - } - } - else - { - if(time - self.ra_nade.cnt >= 1) - { - makevectors(self.v_angle); - float _force = time - self.ra_nade.cnt; - _force /= autocvar_g_riflearena_nade_lifetime; - _force = autocvar_g_riflearena_nade_minforce + (_force * (autocvar_g_riflearena_nade_maxforce - autocvar_g_riflearena_nade_minforce)); - ra_toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0); - } - } - return 1; ++ return TRUE; + } + + MUTATOR_HOOKFUNCTION(ra_BuildMutatorsString) + { + ret_string = strcat(ret_string, ":RA"); - return 0; ++ return FALSE; + } + + MUTATOR_HOOKFUNCTION(ra_BuildMutatorsPrettyString) + { + ret_string = strcat(ret_string, ", Rifle Arena"); - return 0; ++ return FALSE; + } + + MUTATOR_HOOKFUNCTION(ra_SetModname) + { + modname = "Rifle Arena"; + return TRUE; + } + + MUTATOR_DEFINITION(mutator_riflearena) + { - MUTATOR_HOOK(VehicleEnter, ra_VehicleEnter, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerDamage_Calculate, ra_PlayerDamage, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerSpawn, ra_PlayerSpawn, CBC_ORDER_ANY); + MUTATOR_HOOK(FilterItem, ra_FilterItem, CBC_ORDER_ANY); + MUTATOR_HOOK(SetStartItems, ra_StartItems, CBC_ORDER_ANY); - MUTATOR_HOOK(MakePlayerObserver, ra_RemovePlayer, CBC_ORDER_ANY); - MUTATOR_HOOK(ClientDisconnect, ra_RemovePlayer, CBC_ORDER_ANY); - MUTATOR_HOOK(PlayerDies, ra_PlayerDies, CBC_ORDER_ANY); - MUTATOR_HOOK(PlayerPreThink, ra_PlayerThink, CBC_ORDER_ANY); + MUTATOR_HOOK(ForbidThrowCurrentWeapon, ra_ForbidThrowCurrentWeapon, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsString, ra_BuildMutatorsString, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsPrettyString, ra_BuildMutatorsPrettyString, CBC_ORDER_ANY); + + MUTATOR_ONADD + { + ra_SetCvars(); + - precache_model("models/ok_nade_counter/ok_nade_counter.md3"); - - precache_model("models/weapons/h_ok_grenade.iqm"); - precache_model("models/weapons/v_ok_grenade.md3"); - precache_sound("weapons/rocket_impact.wav"); - precache_sound("weapons/grenade_bounce1.wav"); - precache_sound("weapons/grenade_bounce2.wav"); - precache_sound("weapons/grenade_bounce3.wav"); - precache_sound("weapons/grenade_bounce4.wav"); - precache_sound("weapons/grenade_bounce5.wav"); - precache_sound("weapons/grenade_bounce6.wav"); - precache_sound("overkill/grenadebip.wav"); - + weapon_action(WEP_LASER, WR_PRECACHE); + weapon_action(WEP_RIFLE, WR_PRECACHE); + + get_weaponinfo(WEP_HOOK).spawnflags |= WEP_FLAG_MUTATORBLOCKED; + } + + MUTATOR_ONROLLBACK_OR_REMOVE + { + get_weaponinfo(WEP_HOOK).spawnflags &~= WEP_FLAG_MUTATORBLOCKED; + } + + MUTATOR_ONREMOVE + { + print("This cannot be removed at runtime\n"); + return -1; + } + - return 0; ++ return FALSE; + } diff --cc qcsrc/server/mutators/mutators.qh index b3a3a4b34,a6ace7b99..f6f79c73f --- a/qcsrc/server/mutators/mutators.qh +++ b/qcsrc/server/mutators/mutators.qh @@@ -21,15 -21,6 +21,16 @@@ MUTATOR_DECLARATION(mutator_vampire) MUTATOR_DECLARATION(mutator_superspec); MUTATOR_DECLARATION(mutator_minstagib); MUTATOR_DECLARATION(mutator_touchexplode); +MUTATOR_DECLARATION(mutator_pinata); +MUTATOR_DECLARATION(mutator_midair); +MUTATOR_DECLARATION(mutator_bloodloss); +MUTATOR_DECLARATION(mutator_random_gravity); +MUTATOR_DECLARATION(mutator_norecoil); +MUTATOR_DECLARATION(mutator_multijump); +MUTATOR_DECLARATION(mutator_jump_grunt); +MUTATOR_DECLARATION(mutator_footsteps); +MUTATOR_DECLARATION(mutator_melee_only); +MUTATOR_DECLARATION(mutator_nades); + MUTATOR_DECLARATION(mutator_riflearena); MUTATOR_DECLARATION(sandbox); diff --cc qcsrc/server/progs.src index 22514d748,8ce3adc73..a98580589 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@@ -248,16 -248,7 +248,17 @@@ mutators/sandbox.q mutators/mutator_superspec.qc mutators/mutator_minstagib.qc mutators/mutator_touchexplode.qc +mutators/mutator_pinata.qc +mutators/mutator_midair.qc +mutators/mutator_bloodloss.qc +mutators/mutator_random_gravity.qc +mutators/mutator_norecoil.qc +mutators/mutator_multijump.qc +mutators/mutator_jump_grunt.qc +mutators/mutator_footsteps.qc +mutators/mutator_melee_only.qc +mutators/mutator_nades.qc + mutators/mutator_riflearena.qc ../warpzonelib/anglestransform.qc ../warpzonelib/mathlib.qc