From: Mario Date: Mon, 7 Oct 2013 23:12:01 +0000 (-0700) Subject: Experimental ammo charging system X-Git-Tag: xonotic-v0.8.0~70^2~29 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=e245108c7baa708b3a1ffec470025dd3b80e80e5;p=xonotic%2Fxonotic-data.pk3dir.git Experimental ammo charging system --- diff --git a/mutators.cfg b/mutators.cfg index 9cd318a6f..b25fb138f 100644 --- a/mutators.cfg +++ b/mutators.cfg @@ -49,6 +49,22 @@ set g_overkill_powerups_replace 1 set g_overkill_superguns_onemag 1 set g_overkill_superguns_respawn_time 20 +set g_overkill_ammo_charge 1 +set g_overkill_ammo_charge_notice 1 +set g_overkill_ammo_charge_limit 1 +set g_overkill_ammo_charge_rate 0.5 +set g_overkill_ammo_charge_rate_nex 0.5 +set g_overkill_ammo_charge_rate_uzi 0.5 +set g_overkill_ammo_charge_rate_shotgun 0.5 +set g_overkill_ammo_charge_rate_hmg 0.25 +set g_overkill_ammo_charge_rate_rpc 1.5 +set g_overkill_ammo_decharge 0.1 +set g_overkill_ammo_decharge_uzi 0.025 +set g_overkill_ammo_decharge_shotgun 0.15 +set g_overkill_ammo_decharge_nex 0.2 +set g_overkill_ammo_decharge_rpc 1 +set g_overkill_ammo_decharge_hmg 0.01 + // ========= // vampire diff --git a/qcsrc/client/View.qc b/qcsrc/client/View.qc index 46920a417..2002f6a92 100644 --- a/qcsrc/client/View.qc +++ b/qcsrc/client/View.qc @@ -1371,6 +1371,10 @@ void CSQC_UpdateView(float w, float h) float nex_charge, nex_chargepool; nex_charge = getstatf(STAT_NEX_CHARGE); nex_chargepool = getstatf(STAT_NEX_CHARGEPOOL); + + float ok_ammo_charge, ok_ammo_chargepool; + ok_ammo_charge = getstatf(STAT_OK_AMMO_CHARGE); + ok_ammo_chargepool = getstatf(STAT_OK_AMMO_CHARGEPOOl); if(nex_charge_movingavg == 0) // this should only happen if we have just loaded up the game nex_charge_movingavg = nex_charge; @@ -1411,8 +1415,14 @@ void CSQC_UpdateView(float w, float h) ring_rgb = wcross_color; ring_image = "gfx/crosshair_ring.tga"; } - - if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring + else if (ok_ammo_charge) + { + ring_value = ok_ammo_chargepool; + ring_alpha = autocvar_crosshair_ring_reload_alpha; + ring_rgb = wcross_color; + ring_image = "gfx/crosshair_ring.tga"; + } + else if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring { ring_value = bound(0, weapon_clipload / weapon_clipsize, 1); ring_scale = autocvar_crosshair_ring_reload_size; diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 9d3b53259..bf3096ec7 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -183,6 +183,9 @@ const float STAT_ROUNDSTARTTIME = 73; const float STAT_WEAPONS2 = 74; const float STAT_WEAPONS3 = 75; +const float STAT_OK_AMMO_CHARGE = 76; +const float STAT_OK_AMMO_CHARGEPOOl = 77; + // mod stats (1xx) const float STAT_REDALIVE = 100; const float STAT_BLUEALIVE = 101; diff --git a/qcsrc/common/notifications.qh b/qcsrc/common/notifications.qh index e004fbbd3..c5cc46fe9 100644 --- a/qcsrc/common/notifications.qh +++ b/qcsrc/common/notifications.qh @@ -646,6 +646,7 @@ void Send_Notification_WOCOVA( MSG_CENTER_NOTIF(1, CENTER_NIX_COUNTDOWN, 0, 2, "item_wepname", CPID_NIX, "1 f2", _("^F2^COUNT^BG until weapon change...\nNext weapon: ^F1%s"), "") \ MSG_CENTER_NOTIF(1, CENTER_NIX_NEWWEAPON, 0, 1, "item_wepname", CPID_NIX, "0 0", _("^F2Active weapon: ^F1%s"), "") \ MSG_CENTER_NOTIF(1, CENTER_NADE, 0, 0, "", NO_CPID, "0 0", _("^BGPress ^F2DROPWEAPON^BG again to toss the grenade!"), "") \ + MSG_CENTER_NOTIF(1, CENTER_OVERKILL_CHARGE, 0, 0, "", CPID_OVERKILL, "0 0", _("^BGYour weapon's charge is too low, release the attack button & wait for it to charge"), "") \ MSG_CENTER_NOTIF(1, CENTER_OVERTIME_FRAG, 0, 0, "", CPID_OVERTIME, "0 0", _("^F2Now playing ^F4OVERTIME^F2!\nKeep fragging until we have a winner!"), _("^F2Now playing ^F4OVERTIME^F2!\nKeep scoring until we have a winner!")) \ MSG_CENTER_NOTIF(1, CENTER_OVERTIME_TIME, 0, 1, "f1time", CPID_OVERTIME, "0 0", _("^F2Now playing ^F4OVERTIME^F2!\n^BGAdded ^F4%s^BG to the game!"), "") \ MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_INVISIBILITY, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Invisibility has worn off"), "") \ diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 0ff90298c..808186c60 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -1214,10 +1214,8 @@ float autocvar_g_balance_hmg_spread_max; float autocvar_g_balance_hmg_spread_min; float autocvar_g_balance_hmg_sustained_ammo; float autocvar_g_balance_hmg_sustained_damage; -//float autocvar_g_balance_hmg_sustained_headshotaddeddamage; float autocvar_g_balance_hmg_sustained_force; float autocvar_g_balance_hmg_sustained_refire; -//float autocvar_g_balance_hmg_sustained_spread; float autocvar_g_balance_hmg_reload_ammo; float autocvar_g_balance_hmg_reload_time; float autocvar_g_balance_rpc_ammo; @@ -1292,3 +1290,6 @@ float autocvar_g_overkill_superguns_respawn_time; float autocvar_g_overkill_100h_anyway; float autocvar_g_overkill_100a_anyway; float autocvar_g_overkill_ammo_start; +float autocvar_g_overkill_ammo_charge; +float autocvar_g_overkill_ammo_charge_notice; +float autocvar_g_overkill_ammo_charge_limit; diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc index 2fc23307e..56ad52f37 100644 --- a/qcsrc/server/cl_weapons.qc +++ b/qcsrc/server/cl_weapons.qc @@ -358,6 +358,8 @@ float forbidWeaponUse() return 1; if(self.player_blocked) return 1; + if(self.weapon_blocked) + return 1; if(self.freezetag_frozen) return 1; return 0; diff --git a/qcsrc/server/cl_weaponsystem.qc b/qcsrc/server/cl_weaponsystem.qc index f530b5404..3c75176e2 100644 --- a/qcsrc/server/cl_weaponsystem.qc +++ b/qcsrc/server/cl_weaponsystem.qc @@ -1279,7 +1279,14 @@ void W_SetupProjectileVelocity(entity missile, float pSpeed, float spread) #define W_SETUPPROJECTILEVELOCITY(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), 0, 0, cvar(#s "_spread"), FALSE) void W_DecreaseAmmo(.float ammo_type, float ammo_use, float ammo_reload) -{ +{ + if(cvar("g_overkill")) + if(autocvar_g_overkill_ammo_charge) + { + ok_DecreaseCharge(self, self.weapon); + return; // TODO + } + if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !ammo_reload) return; @@ -1340,6 +1347,10 @@ void W_Reload(float sent_ammo_min, float sent_ammo_amount, float sent_time, stri entity e; e = get_weaponinfo(self.weapon); + + if(cvar("g_overkill")) + if(autocvar_g_overkill_ammo_charge) + return; // TODO // don't reload weapons that don't have the RELOADABLE flag if not(e.spawnflags & WEP_FLAG_RELOADABLE) diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index c7aebd58f..8ff9de8f0 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -580,6 +580,7 @@ float serverflags; .float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator .float player_blocked; +.float weapon_blocked; // weapon use disabled .float freezetag_frozen; diff --git a/qcsrc/server/mutators/mutator_overkill.qc b/qcsrc/server/mutators/mutator_overkill.qc index 191946ffd..c16198b1f 100644 --- a/qcsrc/server/mutators/mutator_overkill.qc +++ b/qcsrc/server/mutators/mutator_overkill.qc @@ -1,3 +1,41 @@ +void ok_DecreaseCharge(entity ent, float wep) +{ + if not(autocvar_g_overkill_ammo_charge) return; + + entity wepent = get_weaponinfo(wep); + + if(wepent.netname == "") + return; // dummy + + ent.ammo_charge[wep] -= cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname)); +} + +void ok_IncreaseCharge(entity ent, float wep) +{ + entity wepent = get_weaponinfo(wep); + + if(wepent.netname == "") + return; // dummy + + if(autocvar_g_overkill_ammo_charge) + if not(ent.BUTTON_ATCK) + if(ent.ammo_charge[wep] <= autocvar_g_overkill_ammo_charge_limit) + ent.ammo_charge[wep] = min(autocvar_g_overkill_ammo_charge_limit, ent.ammo_charge[wep] + cvar(sprintf("g_overkill_ammo_charge_rate_%s", wepent.netname)) * frametime / W_TICSPERFRAME); +} + +float ok_CheckWeaponCharge(entity ent, float wep, float swep) +{ + if not(autocvar_g_overkill_ammo_charge) return TRUE; + //if(wep != swep) return TRUE; // switching, don't even bother checking + + entity wepent = get_weaponinfo(wep); + + if(wepent.netname == "") + return 0; // dummy + + return !(ent.ammo_charge[wep] < cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname))); +} + MUTATOR_HOOKFUNCTION(ok_PlayerDamage_Calculate) { if(DEATH_ISWEAPON(frag_deathtype, WEP_LASER) && frag_target == frag_attacker) @@ -49,8 +87,8 @@ MUTATOR_HOOKFUNCTION(ok_PlayerDies) cvar_set("g_pickup_items", "1"); self = spawn(); - self.noalign = TRUE; self.ok_item = TRUE; + self.noalign = TRUE; spawnfunc_item_armor_small(); self.movetype = MOVETYPE_TOSS; self.gravity = 1; @@ -66,6 +104,8 @@ MUTATOR_HOOKFUNCTION(ok_PlayerDies) MUTATOR_HOOKFUNCTION(ok_ForbidThrowCurrentWeapon) { + nades_CheckThrow(); + return TRUE; } @@ -80,6 +120,8 @@ MUTATOR_HOOKFUNCTION(ok_PlayerPreThink) if(self.freezetag_frozen) return FALSE; + ok_IncreaseCharge(self, self.weapon); + if(self.BUTTON_ATCK2) if(self.jump_interval <= time) { @@ -91,12 +133,45 @@ MUTATOR_HOOKFUNCTION(ok_PlayerPreThink) self.weapon = w; } + self.weapon_blocked = FALSE; + + self.ok_ammo_charge = self.ammo_charge[self.weapon]; + + if(autocvar_g_overkill_ammo_charge) + if(!ok_CheckWeaponCharge(self, self.weapon, self.switchweapon)) + { + if(autocvar_g_overkill_ammo_charge_notice && time > self.ok_notice_time && self.BUTTON_ATCK && IS_REAL_CLIENT(self)) + { + Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERKILL_CHARGE); + self.ok_notice_time = time + 2; + play2(self, "weapons/dryfire.wav"); + } + if(self.weaponentity.state != WS_CLEAR) + w_ready(); + + self.weapon_blocked = TRUE; + } + self.BUTTON_ATCK2 = 0; + return FALSE; } MUTATOR_HOOKFUNCTION(ok_PlayerSpawn) { + if(autocvar_g_overkill_ammo_charge) + { + float i; + + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + self.ammo_charge[i] = autocvar_g_overkill_ammo_charge_limit; + + self.ok_use_ammocharge = 1; + self.ok_notice_time = time; + } + else + self.ok_use_ammocharge = 0; + if(autocvar_g_overkill_spawnsystem_delay_death) self.ok_spawnsys_timer = time + autocvar_g_overkill_spawnsystem_delay_death; @@ -237,23 +312,25 @@ void start_ma_anyway() MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn) { - if(autocvar_g_powerups != 0) + if(autocvar_g_powerups) if(autocvar_g_overkill_powerups_replace) if(self.classname == "item_strength") { entity wep = spawn(); setorigin(wep, self.origin); + wep.ok_item = TRUE; wep.think = start_hmg; wep.nextthink = time + 0.1; return TRUE; } - if(autocvar_g_powerups != 0) + if(autocvar_g_powerups) if(autocvar_g_overkill_powerups_replace) if(self.classname == "item_invincible") { entity wep = spawn(); setorigin(wep, self.origin); + wep.ok_item = TRUE; wep.think = start_rpc; wep.nextthink = time + 0.1; return TRUE; @@ -276,6 +353,14 @@ MUTATOR_HOOKFUNCTION(ok_ItemRemove) return TRUE; } +MUTATOR_HOOKFUNCTION(ok_SpectateCopy) +{ + self.ammo_charge[self.weapon] = other.ammo_charge[other.weapon]; + self.ok_use_ammocharge = other.ok_use_ammocharge; + + return FALSE; +} + MUTATOR_HOOKFUNCTION(ok_SetModname) { modname = "Overkill"; @@ -318,6 +403,11 @@ void ok_Initialize() precache_model("models/weapons/v_ok_sniper.md3"); precache_model("models/weapons/g_ok_sniper.md3"); + precache_sound("weapons/dryfire.wav"); + + addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge); + addstat(STAT_OK_AMMO_CHARGEPOOl, AS_FLOAT, ok_ammo_charge); + w_uzi(WR_PRECACHE); w_nex(WR_PRECACHE); w_shotgun(WR_PRECACHE); @@ -358,6 +448,7 @@ MUTATOR_DEFINITION(mutator_overkill) MUTATOR_HOOK(OnEntityPreSpawn, ok_OnEntityPreSpawn, CBC_ORDER_ANY); MUTATOR_HOOK(SetModname, ok_SetModname, CBC_ORDER_ANY); MUTATOR_HOOK(FilterItem, ok_ItemRemove, CBC_ORDER_ANY); + MUTATOR_HOOK(SpectateCopy, ok_SpectateCopy, CBC_ORDER_ANY); MUTATOR_HOOK(SetStartItems, ok_StartItems, CBC_ORDER_ANY); MUTATOR_ONADD diff --git a/qcsrc/server/mutators/mutator_overkill.qh b/qcsrc/server/mutators/mutator_overkill.qh index 8b22d444e..17e46e20d 100644 --- a/qcsrc/server/mutators/mutator_overkill.qh +++ b/qcsrc/server/mutators/mutator_overkill.qh @@ -1,4 +1,12 @@ .vector ok_deathloc; .float ok_spawnsys_timer; .float ok_lastwep; -.float ok_item; \ No newline at end of file +.float ok_item; + +.float ok_notice_time; +.float ammo_charge[WEP_MAXCOUNT]; +.float ok_use_ammocharge; +.float ok_ammo_charge; + +void(entity ent, float wep) ok_DecreaseCharge; +