From 0ed3102efa5fb2ed289baa81724f2c944d21a5d2 Mon Sep 17 00:00:00 2001 From: otta8634 Date: Wed, 14 May 2025 17:16:36 +0800 Subject: [PATCH] Add DPS information to the guide The guide now has a short sentence about the damage and damage per second (DPS) for each weapon that can deal damage. Values are the defaults (cvar_defstring). Strings/Functions may need to be updated if the weapons' functionalities are ever changed in future, but this is unavoidable without an overly complicated solution. Electro secondary is currently inaccurate since _secondary_refire and _secondary_refire2 are misnamed. --- .../common/mutators/mutator/overkill/okhmg.qc | 14 +-- .../mutators/mutator/overkill/okmachinegun.qc | 10 +- .../common/mutators/mutator/overkill/oknex.qc | 10 +- .../common/mutators/mutator/overkill/okrpc.qc | 12 +- .../mutators/mutator/overkill/okshotgun.qc | 10 +- qcsrc/common/weapons/all.qc | 105 ++++++++++++++++++ qcsrc/common/weapons/all.qh | 13 +++ qcsrc/common/weapons/weapon/arc.qc | 4 +- qcsrc/common/weapons/weapon/blaster.qc | 4 +- qcsrc/common/weapons/weapon/crylink.qc | 4 +- qcsrc/common/weapons/weapon/devastator.qc | 4 +- qcsrc/common/weapons/weapon/electro.qc | 4 +- qcsrc/common/weapons/weapon/fireball.qc | 4 +- qcsrc/common/weapons/weapon/hagar.qc | 4 +- qcsrc/common/weapons/weapon/hlac.qc | 12 +- qcsrc/common/weapons/weapon/hook.qc | 4 +- qcsrc/common/weapons/weapon/machinegun.qc | 4 +- qcsrc/common/weapons/weapon/minelayer.qc | 4 +- qcsrc/common/weapons/weapon/mortar.qc | 4 +- qcsrc/common/weapons/weapon/rifle.qc | 4 +- qcsrc/common/weapons/weapon/seeker.qc | 4 +- qcsrc/common/weapons/weapon/shotgun.qc | 4 +- qcsrc/common/weapons/weapon/tuba.qc | 4 +- qcsrc/common/weapons/weapon/vaporizer.qc | 6 +- qcsrc/common/weapons/weapon/vortex.qc | 4 +- 25 files changed, 188 insertions(+), 68 deletions(-) diff --git a/qcsrc/common/mutators/mutator/overkill/okhmg.qc b/qcsrc/common/mutators/mutator/overkill/okhmg.qc index 2968c6f026..d18f2e56c2 100644 --- a/qcsrc/common/mutators/mutator/overkill/okhmg.qc +++ b/qcsrc/common/mutators/mutator/overkill/okhmg.qc @@ -163,14 +163,14 @@ METHOD(OverkillHeavyMachineGun, wr_impacteffect, void(entity thiswep, entity act METHOD(OverkillHeavyMachineGun, describe, string(OverkillHeavyMachineGun this)) { TC(OverkillHeavyMachineGun, this); - return sprintf(_("The %s is a superweapon that rapidly fires harmful bullets with a small degree of spread\n\n" - "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around\n\n" - "It is a superweapon found on some maps, meaning that it breaks down after some time\n\n" + return sprintf(_("The %s is a superweapon that rapidly fires harmful bullets with a small degree of spread.\n\n" + "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around.\n\n" + "It is a superweapon found on some maps, meaning that it breaks down after some time.\n\n" "The primary fire consumes %s ammo, although you spawn with an infinite amount of it in %s. " - "It has a limited magazine size, so needs reloading after several shots\n\n" - "The %s can be used in a lot of situations, and it works particularly well at long ranges since the bullets pierce the sky instantaneously\n\n" - "Since its bullets deal a lot more damage than the %s's bullets, it is often heavily contested when it spawns in"), - COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Bullets), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this), COLORED_NAME(WEP_OVERKILL_MACHINEGUN)); + "It has a limited magazine size, so needs reloading after several shots.\n\n" + "The %s can be used in a lot of situations, and it works particularly well at long ranges since the bullets pierce the sky instantaneously.\n\n" + "Since its bullets deal a lot more damage than the %s's bullets, it is often heavily contested when it spawns in.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Bullets), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this), COLORED_NAME(WEP_OVERKILL_MACHINEGUN), W_Guide_DPS_onlyOne(this.netname, "primary")); } #endif diff --git a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc index 1b4e6ee9c5..f03c328730 100644 --- a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc +++ b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc @@ -162,12 +162,12 @@ METHOD(OverkillMachineGun, wr_impacteffect, void(entity thiswep, entity actor)) METHOD(OverkillMachineGun, describe, string(OverkillMachineGun this)) { TC(OverkillMachineGun, this); - return sprintf(_("The %s quickly fires bullets with a small degree of spread\n\n" - "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around\n\n" + return sprintf(_("The %s quickly fires bullets with a small degree of spread.\n\n" + "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around.\n\n" "The primary fire consumes %s ammo, although you spawn with an infinite amount of it in %s. " - "It has a limited magazine size, so needs reloading after several shots\n\n" - "The %s can be used in a lot of situations, and it works particularly well at long ranges since the bullets pierce the sky instantaneously"), - COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Bullets), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this)); + "It has a limited magazine size, so needs reloading after several shots.\n\n" + "The %s can be used in a lot of situations, and it works particularly well at long ranges since the bullets pierce the sky instantaneously.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Bullets), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this), W_Guide_DPS_onlyOne(this.netname, "primary")); } #endif diff --git a/qcsrc/common/mutators/mutator/overkill/oknex.qc b/qcsrc/common/mutators/mutator/overkill/oknex.qc index 1c5e92a357..d9695c62f1 100644 --- a/qcsrc/common/mutators/mutator/overkill/oknex.qc +++ b/qcsrc/common/mutators/mutator/overkill/oknex.qc @@ -369,12 +369,12 @@ METHOD(OverkillNex, wr_zoomdir, bool(entity thiswep)) METHOD(OverkillNex, describe, string(OverkillNex this)) { TC(OverkillNex, this); - return sprintf(_("The %s fires harmful beams of energy that traverse the map instantaneously and deal a significant chunk of damage on impact\n\n" - "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around\n\n" + return sprintf(_("The %s fires harmful beams of energy that traverse the map instantaneously and deal a significant chunk of damage on impact.\n\n" + "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around.\n\n" "The primary fire consumes %s ammo, although you spawn with an infinite amount of it in %s. " - "It has a limited magazine size, so needs reloading after several shots\n\n" - "Since it is the only %s weapon with no spread, the %s stands out at long ranges"), - COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Cells), COLORED_NAME(MUTATOR_ok), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this)); + "It has a limited magazine size, so needs reloading after several shots.\n\n" + "Since it is the only %s weapon with no spread, the %s stands out at long ranges.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Cells), COLORED_NAME(MUTATOR_ok), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this), W_Guide_DPS_onlyOne(this.netname, "primary")); } #endif diff --git a/qcsrc/common/mutators/mutator/overkill/okrpc.qc b/qcsrc/common/mutators/mutator/overkill/okrpc.qc index 64b2b423b3..b2a03327c9 100644 --- a/qcsrc/common/mutators/mutator/overkill/okrpc.qc +++ b/qcsrc/common/mutators/mutator/overkill/okrpc.qc @@ -238,12 +238,12 @@ METHOD(OverkillRocketPropelledChainsaw, wr_impacteffect, void(entity thiswep, en METHOD(OverkillRocketPropelledChainsaw, describe, string(OverkillRocketPropelledChainsaw this)) { TC(OverkillRocketPropelledChainsaw, this); - return sprintf(_("As the name suggests, the %s is a superweapon that fires a rocket propelled chainsaw which explodes on impact, dealing a lot of splash damage to any players close by\n\n" - "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around\n\n" - "It is a superweapon found on some maps, meaning that it breaks down after some time\n\n" - "The primary fire consumes %s ammo, although you spawn with an infinite amount of it in %s\n\n" - "Since it is the only %s weapon which deals splash damage, the %s is a good choice of weapon for attacking groups of enemies"), - COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Rockets), COLORED_NAME(MUTATOR_ok), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this)); + return sprintf(_("As the name suggests, the %s is a superweapon that fires a rocket propelled chainsaw which explodes on impact, dealing a lot of splash damage to any players close by.\n\n" + "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around.\n\n" + "It is a superweapon found on some maps, meaning that it breaks down after some time.\n\n" + "The primary fire consumes %s ammo, although you spawn with an infinite amount of it in %s.\n\n" + "Since it is the only %s weapon which deals splash damage, the %s is a good choice of weapon for attacking groups of enemies.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Rockets), COLORED_NAME(MUTATOR_ok), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this), W_Guide_DPS_onlyOne(this.netname, "primary")); } #endif diff --git a/qcsrc/common/mutators/mutator/overkill/okshotgun.qc b/qcsrc/common/mutators/mutator/overkill/okshotgun.qc index 22dfa1ed82..26b0730cea 100644 --- a/qcsrc/common/mutators/mutator/overkill/okshotgun.qc +++ b/qcsrc/common/mutators/mutator/overkill/okshotgun.qc @@ -127,12 +127,12 @@ METHOD(OverkillShotgun, wr_impacteffect, void(entity thiswep, entity actor)) METHOD(OverkillShotgun, describe, string(OverkillShotgun this)) { TC(OverkillShotgun, this); - return sprintf(_("The %s fires a single shotgun round which spreads into multiple pellets upon exiting the barrel, dealing a deadly blow if up close\n\n" - "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around\n\n" + return sprintf(_("The %s fires a single shotgun round which spreads into multiple pellets upon exiting the barrel, dealing a deadly blow if up close.\n\n" + "Like with all %s weapons, the secondary fire shoots a laser which does not damage or push enemies, but can be used to push yourself around.\n\n" "The primary fire consumes %s ammo, although you spawn with an infinite amount of it in %s. " - "It has a limited magazine size, so needs reloading after several shots\n\n" - "The %s's damage drops off quickly as the range increases, so it is only useful for close combat or sometimes medium range combat"), - COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Shells), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this)); + "It has a limited magazine size, so needs reloading after several shots.\n\n" + "The %s's damage drops off quickly as the range increases, so it is only useful for close combat or sometimes medium range combat.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(MUTATOR_ok), COLORED_NAME(ITEM_Shells), COLORED_NAME(MUTATOR_ok), COLORED_NAME(this), W_Guide_DPS_onlyOneMultishot(this.netname, "primary", "primary_bullets", "")); } #endif diff --git a/qcsrc/common/weapons/all.qc b/qcsrc/common/weapons/all.qc index 75da68b9ab..80d69b8ed5 100644 --- a/qcsrc/common/weapons/all.qc +++ b/qcsrc/common/weapons/all.qc @@ -829,3 +829,108 @@ REPLICATE(cvar_cl_weaponpriorities[7], string, "cl_weaponpriority7", W_FixWeapon REPLICATE(cvar_cl_weaponpriorities[8], string, "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete); REPLICATE(cvar_cl_weaponpriorities[9], string, "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete); #endif + + +#ifdef MENUQC +// One function for each translatable string + +string W_Guide_DPS_onlyOne_unnamed(string name) +{ + const string dmg = cvar_defstring(sprintf("g_balance_%s_damage", name)); + const float rft = stof(cvar_defstring(sprintf("g_balance_%s_refire", name))); + return sprintf(_("By default, it does %s damage (DPS: %.2f)."), + dmg, rft <= 0 ? 1337 : stof(dmg) / rft); +} +string W_Guide_DPS_onlyOne(string name, string fire) +{ + return W_Guide_DPS_onlyOne_unnamed(sprintf("%s_%s", name, fire)); +} +string W_Guide_DPS(string name, string pri, string sec) +{ + // TODO: rename all wep primary cvars to g_balance_*_primary_*, vice versa for secondary. + // Example exception: g_balance_arc_beam_* (primary) + const string pri_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, pri)); + const float pri_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, pri))); + const string sec_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, sec)); + const float sec_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, sec))); + return sprintf(_("By default, the %s does %s damage (DPS: %.2f), and the %s does %s damage (DPS: %.2f)."), + pri, pri_dmg, (pri_rft <= 0 ? 1337 : stof(pri_dmg) / pri_rft), + sec, sec_dmg, (sec_rft <= 0 ? 1337 : stof(sec_dmg) / sec_rft)); +} +string W_Guide_DPS_bothMultishot(string name, string pri, string sec) +{ + const string pri_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, pri)); + const float pri_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, pri))); + const string pri_shots = cvar_defstring(sprintf("g_balance_%s_%s_shots", name, pri)); + const string sec_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, sec)); + const float sec_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, sec))); + const string sec_shots = cvar_defstring(sprintf("g_balance_%s_%s_shots", name, sec)); + return strcat(sprintf(_("By default, the %s shoots %s shots doing %s damage each (DPS: %.2f)"), + pri, pri_shots, pri_dmg, (pri_rft <= 0 ? 1337 : stof(pri_dmg) / pri_rft * stof(pri_shots))), + sprintf(_(", and the %s shoots %s shots doing %s damage each (DPS: %.2f)."), + sec, sec_shots, sec_dmg, (sec_rft <= 0 ? 1337 : stof(sec_dmg) / sec_rft * stof(sec_shots))) + ); +} +string W_Guide_DPS_secondaryMultishot(string name, string pri, string sec, string shots, string refire2) +{ + const string pri_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, pri)); + const float pri_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, pri))); + string sec_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, sec)); + if (sec_dmg == "") + sec_dmg = pri_dmg; + float sec_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, sec))); + const string sec_shots = cvar_defstring(sprintf("g_balance_%s_%s", name, shots)); + const float num_shots = stof(sec_shots); + if (refire2 != "") + sec_rft = (num_shots - 1) * sec_rft + stof(cvar_defstring(sprintf("g_balance_%s_%s", name, refire2))); + return sprintf(_("By default, the %s does %s damage (DPS: %.2f), and the %s shoots %s shots doing %s damage each (DPS: %.2f)."), + pri, pri_dmg, (pri_rft <= 0 ? 1337 : stof(pri_dmg) / pri_rft), + sec, sec_shots, sec_dmg, (sec_rft <= 0 ? 1337 : stof(sec_dmg) / sec_rft * num_shots)); +} +string W_Guide_DPS_primaryMultishot(string name, string pri, string sec, string shots, string refire2) +{ + const string pri_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, pri)); + float pri_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, pri))); + const string pri_shots = cvar_defstring(sprintf("g_balance_%s_%s", name, shots)); + const string sec_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, sec)); + const float sec_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, sec))); + const float num_shots = stof(pri_shots); + if (refire2 != "") + pri_rft = (num_shots - 1) * pri_rft + stof(cvar_defstring(sprintf("g_balance_%s_%s", name, refire2))); + return sprintf(_("By default, the %s shoots %s shots doing %s damage each (DPS: %.2f), and the %s does %s damage (DPS: %.2f)."), + pri, pri_shots, pri_dmg, (pri_rft <= 0 ? 1337 : stof(pri_dmg) / pri_rft * num_shots), + sec, sec_dmg, (sec_rft <= 0 ? 1337 : stof(sec_dmg) / sec_rft)); +} +string W_Guide_DPS_onlyOneMultishot(string name, string fire, string shots, string refire2) +{ + const string dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, fire)); + float rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, fire))); + const string shots_s = cvar_defstring(sprintf("g_balance_%s_%s", name, shots)); + const float num_shots = stof(shots_s); + if (refire2 != "") + rft = (num_shots - 1) * rft + stof(cvar_defstring(sprintf("g_balance_%s_%s", name, refire2))); + return sprintf(_("By default, it shoots %s shots doing %s damage each (DPS: %.2f)."), + shots_s, dmg, (rft <= 0 ? 1337 : stof(dmg) / rft * num_shots)); +} +string W_Guide_DPS_withCombo(string name, string pri, string sec) +{ + const string pri_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, pri)); + const float pri_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, pri))); + const string sec_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, sec)); + const float sec_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, sec))); + const string cmb_dmg = cvar_defstring(sprintf("g_balance_%s_combo_damage", name)); + return sprintf(_("By default, the %s does %s damage (DPS: %.2f), the %s does %s damage (DPS: %.2f), and the combo adds an extra %s damage."), + pri, pri_dmg, (pri_rft <= 0 ? 1337 : stof(pri_dmg) / pri_rft), + sec, sec_dmg, (sec_rft <= 0 ? 1337 : stof(sec_dmg) / sec_rft), + cmb_dmg); +} +string W_Guide_DPS_primaryDPS(string name, string pri, string sec) +{ + const string pri_dps = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, pri)); + const string sec_dmg = cvar_defstring(sprintf("g_balance_%s_%s_damage", name, sec)); + const float sec_rft = stof(cvar_defstring(sprintf("g_balance_%s_%s_refire", name, sec))); + return sprintf(_("By default, the %s does %s damage per second, and the %s does %s damage (DPS: %.2f)."), + pri, pri_dps, + sec, sec_dmg, (sec_rft <= 0 ? 1337 : stof(sec_dmg) / sec_rft)); +} +#endif diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh index 53693e0cc6..37188d0a76 100644 --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@ -452,3 +452,16 @@ int GetAmmoStat(Resource ammotype); string W_Sound(string w_snd); string W_Model(string w_mdl); + + +#ifdef MENUQC +string W_Guide_DPS_onlyOne_unnamed(string name); +string W_Guide_DPS_onlyOne(string name, string fire); +string W_Guide_DPS(string name, string pri, string sec); +string W_Guide_DPS_bothMultishot(string name, string pri, string sec); +string W_Guide_DPS_secondaryMultishot(string name, string pri, string sec, string shots, string refire2); +string W_Guide_DPS_primaryMultishot(string name, string pri, string sec, string shots, string refire2); +string W_Guide_DPS_onlyOneMultishot(string name, string fire, string shots, string refire2); +string W_Guide_DPS_withCombo(string name, string pri, string sec); +string W_Guide_DPS_primaryDPS(string name, string pri, string sec); +#endif diff --git a/qcsrc/common/weapons/weapon/arc.qc b/qcsrc/common/weapons/weapon/arc.qc index 672a1bdcdc..c7dd72cc88 100644 --- a/qcsrc/common/weapons/weapon/arc.qc +++ b/qcsrc/common/weapons/weapon/arc.qc @@ -1517,8 +1517,8 @@ METHOD(Arc, describe, string(Arc this)) return sprintf(_("The %s fires a continuous stream of electricity, steadily dealing damage to any enemies that cross its path.\n\n" "The secondary fire rapidly shoots electro balls forward, exploding on impact and dealing some splash damage.\n\n" "It consumes %s ammo, steadily churning through your supply to maintain the stream.\n\n" - "The %s is quite a versatile weapon, however it is more effective at close to medium ranges, since the stream is not instantaneous."), - COLORED_NAME(this), COLORED_NAME(ITEM_Cells), COLORED_NAME(this)); + "The %s is quite a versatile weapon, however it is more effective at close to medium ranges, since the stream is not instantaneous.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Cells), COLORED_NAME(this), W_Guide_DPS_primaryDPS(this.netname, "beam", "bolt")); } #endif diff --git a/qcsrc/common/weapons/weapon/blaster.qc b/qcsrc/common/weapons/weapon/blaster.qc index 1ab24eada6..61d0eddf3d 100644 --- a/qcsrc/common/weapons/weapon/blaster.qc +++ b/qcsrc/common/weapons/weapon/blaster.qc @@ -162,8 +162,8 @@ METHOD(Blaster, describe, string(Blaster this)) "It doesn't require ammo, meaning it is a great choice if you are running low on ammo and need to preserve some.\n\n" "The %s is always available so ends up being used a lot when players spawn in, but it's difficult to master when used over a medium to long range.\n\n" "One of the most common uses of the %s is \"laser jumping,\" where you can gain height by aiming down, jumping, then firing to boost yourself up. " - "Because it does a lot of knockback, another common usage is alternating between a high damage weapon and the %s to throw the enemy's aim off."), - COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this)); + "Because it does a lot of knockback, another common usage is alternating between a high damage weapon and the %s to throw the enemy's aim off.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this), W_Guide_DPS_onlyOne(this.netname, "primary")); } #endif diff --git a/qcsrc/common/weapons/weapon/crylink.qc b/qcsrc/common/weapons/weapon/crylink.qc index 743ab8e1ec..d8fd1c1887 100644 --- a/qcsrc/common/weapons/weapon/crylink.qc +++ b/qcsrc/common/weapons/weapon/crylink.qc @@ -642,8 +642,8 @@ METHOD(Crylink, describe, string(Crylink this)) "Close to medium range is the ideal time to use the %s, although the secondary fire can be useful for long range combat sometimes.\n\n" "The %s deals knockback in a unique way, pulling the player from their center to the point of impact. " "This makes it one of the best weapons to slow someone down if you are chasing them, particularly with the secondary fire. " - "Another common use of the %s is \"crylink running,\" where you partially angle down and use the secondary fire to pull yourself forwards, in order to gain speed."), - COLORED_NAME(this), COLORED_NAME(ITEM_Cells), COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this)); + "Another common use of the %s is \"crylink running,\" where you partially angle down and use the secondary fire to pull yourself forwards, in order to gain speed.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Cells), COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this), W_Guide_DPS_bothMultishot(this.netname, "primary", "secondary")); } #endif diff --git a/qcsrc/common/weapons/weapon/devastator.qc b/qcsrc/common/weapons/weapon/devastator.qc index 975c73045d..cd91096c11 100644 --- a/qcsrc/common/weapons/weapon/devastator.qc +++ b/qcsrc/common/weapons/weapon/devastator.qc @@ -622,8 +622,8 @@ METHOD(Devastator, describe, string(Devastator this)) "It can be used in almost any scenario, working best in medium range combat. " "In close range combat, the large splash radius means often rockets can damage yourself as well as the enemy.\n\n" "Due to the ability to remotely detonate rockets, a common usage is \"rocket flying,\" where you fire a rocket and immediately detonate it to boost yourself while mid-air, " - "much more effective with the %s mutator enabled."), - COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(WEP_VORTEX), COLORED_NAME(this), COLORED_NAME(MUTATOR_rocketflying)); + "much more effective with the %s mutator enabled.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(WEP_VORTEX), COLORED_NAME(this), COLORED_NAME(MUTATOR_rocketflying), W_Guide_DPS_onlyOne_unnamed(this.netname)); } #endif diff --git a/qcsrc/common/weapons/weapon/electro.qc b/qcsrc/common/weapons/weapon/electro.qc index a53b53a662..0856a2c2c7 100644 --- a/qcsrc/common/weapons/weapon/electro.qc +++ b/qcsrc/common/weapons/weapon/electro.qc @@ -788,8 +788,8 @@ METHOD(Electro, describe, string(Electro this)) "The balls burst after some time, and can be forced to burst in a \"combo\" if a primary fire ball bursts near them.\n\n" "It consumes some %s ammo for each ball.\n\n" "The %s is one of the best spam weapons to use in crowded areas, since combos can deal tons of damage, if the enemy is close enough. " - "Since the primary fire doesn't travel particularly fast, the %s is not useful in many other situations."), - COLORED_NAME(this), COLORED_NAME(MAPINFO_TYPE_CTF), COLORED_NAME(ITEM_Cells), COLORED_NAME(this), COLORED_NAME(this)); + "Since the primary fire doesn't travel particularly fast, the %s is not useful in many other situations.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(MAPINFO_TYPE_CTF), COLORED_NAME(ITEM_Cells), COLORED_NAME(this), COLORED_NAME(this), W_Guide_DPS_withCombo(this.netname, "primary", "secondary")); // TODO FIXME } #endif diff --git a/qcsrc/common/weapons/weapon/fireball.qc b/qcsrc/common/weapons/weapon/fireball.qc index 82bb89a236..2daf304e62 100644 --- a/qcsrc/common/weapons/weapon/fireball.qc +++ b/qcsrc/common/weapons/weapon/fireball.qc @@ -443,8 +443,8 @@ METHOD(Fireball, describe, string(Fireball this)) "It is a superweapon, so isn't often found in game.\n\n" "It doesn't require ammo, but it is destroyed after some time.\n\n" "Since the %s takes a moment to charge and the fireball travels slowly, using it effectively may be difficult, " - "but if done properly it can deal a ton of damage."), - COLORED_NAME(this), COLORED_NAME(this)); + "but if done properly it can deal a ton of damage.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(this), W_Guide_DPS(this.netname, "primary", "secondary")); } #endif diff --git a/qcsrc/common/weapons/weapon/hagar.qc b/qcsrc/common/weapons/weapon/hagar.qc index 97b63dd69c..92d3ca7751 100644 --- a/qcsrc/common/weapons/weapon/hagar.qc +++ b/qcsrc/common/weapons/weapon/hagar.qc @@ -500,8 +500,8 @@ METHOD(Hagar, describe, string(Hagar this)) "These rockets can't be held forever, so it will fire itself after some time (after a warning beep) if the secondary fire isn't released.\n\n" "It consumes %s ammo for each rocket.\n\n" "The %s works best over close to medium ranges, since it's hard to land hits at a long distance. " - "A common usage is fully loading the secondary fire before turning a corner, so you can surprise any enemies around the corner with a bunch of rockets to the face."), - COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this)); + "A common usage is fully loading the secondary fire before turning a corner, so you can surprise any enemies around the corner with a bunch of rockets to the face.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this), W_Guide_DPS_secondaryMultishot(this.netname, "primary", "secondary", "secondary_load_max", "secondary_load_speed")); } #endif diff --git a/qcsrc/common/weapons/weapon/hlac.qc b/qcsrc/common/weapons/weapon/hlac.qc index b6a2ad8e87..2d4c277c47 100644 --- a/qcsrc/common/weapons/weapon/hlac.qc +++ b/qcsrc/common/weapons/weapon/hlac.qc @@ -241,15 +241,17 @@ METHOD(HLAC, wr_impacteffect, void(entity thiswep, entity actor)) METHOD(HLAC, describe, string(HLAC this)) { TC(HLAC, this); - return sprintf(_("The %s (or HLAC for short) fires lasers in quick succession. " + string s = sprintf(_("The %s (or HLAC for short) fires lasers in quick succession. " "The projectiles it fires are similar to those of the %s.\n\n" "The secondary fire shoots a randomly scattered burst of multiple lasers at once.\n\n" - "Unlike the %s, it consumes %s ammo for each laser shot, meaning that it cannot be used infinitely.\n\n" - "The %s works best in close ranges, but the primary fire is also useful in medium ranges.\n\n" + "Unlike the %s, it consumes %s ammo for each laser shot, meaning that it cannot be used infinitely.\n\n"), + COLORED_NAME(this), COLORED_NAME(WEP_BLASTER), COLORED_NAME(WEP_BLASTER), COLORED_NAME(ITEM_Cells)); + s = strcat(s, sprintf(_("The %s works best in close ranges, but the primary fire is also useful in medium ranges.\n\n" "A unique aspect of the %s is that the longer the primary fire is held, the more that the lasers will start to spread out. " "This means releasing primary fire every now and then is important to restore accuracy. " - "Also, the %s has less spread when used while crouching."), - COLORED_NAME(this), COLORED_NAME(WEP_BLASTER), COLORED_NAME(WEP_BLASTER), COLORED_NAME(ITEM_Cells), COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this)); + "Also, the %s has less spread when used while crouching.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this), W_Guide_DPS_secondaryMultishot(this.netname, "primary", "secondary", "secondary_shots", ""))); + return s; } #endif diff --git a/qcsrc/common/weapons/weapon/hook.qc b/qcsrc/common/weapons/weapon/hook.qc index 706e9af2a1..510680544e 100644 --- a/qcsrc/common/weapons/weapon/hook.qc +++ b/qcsrc/common/weapons/weapon/hook.qc @@ -431,8 +431,8 @@ METHOD(Hook, describe, string(Hook this)) "It usually requires %s ammo to work, consuming it both when initially firing the hook, and after a couple seconds as it reels you in.\n\n" "The %s allows reaching previously unreachable places on maps and zooming around the map at high speeds, " "making both surprise ambushes and miraculous escapes possible.\n\n" - "It isn't available very often on maps, unless the %s mutator is active, in which all players have it on their offhand, used with the ^3+hook^7 bind."), - COLORED_NAME(this), COLORED_NAME(ITEM_JetpackFuel), COLORED_NAME(this), COLORED_NAME(MUTATOR_hook)); + "It isn't available very often on maps, unless the %s mutator is active, in which all players have it on their offhand, used with the ^3+hook^7 bind.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_JetpackFuel), COLORED_NAME(this), COLORED_NAME(MUTATOR_hook), W_Guide_DPS_onlyOne(this.netname, "secondary")); } #endif diff --git a/qcsrc/common/weapons/weapon/machinegun.qc b/qcsrc/common/weapons/weapon/machinegun.qc index ece4efa21e..ec9bb14399 100644 --- a/qcsrc/common/weapons/weapon/machinegun.qc +++ b/qcsrc/common/weapons/weapon/machinegun.qc @@ -423,8 +423,8 @@ METHOD(MachineGun, describe, string(MachineGun this)) "The secondary fire fires a quick burst of bullets faster than the primary fire and with no spread, but there's a short delay until it can be used again.\n\n" "It consumes %s ammo for each bullet shot, until the whole magazine is emptied.\n\n" "The %s can be used in a lot of situations, and it works particularly well at long ranges since the bullets pierce the sky instantaneously. " - "Since the secondary fire has no spread, it's the better option when firing over a long range."), - COLORED_NAME(this), COLORED_NAME(ITEM_Bullets), COLORED_NAME(this)); + "Since the secondary fire has no spread, it's the better option when firing over a long range.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Bullets), COLORED_NAME(this), W_Guide_DPS_secondaryMultishot(this.netname, "sustained", "burst", "burst", "burst_refire2")); } #endif diff --git a/qcsrc/common/weapons/weapon/minelayer.qc b/qcsrc/common/weapons/weapon/minelayer.qc index 074c4b7fa3..9e290a8e31 100644 --- a/qcsrc/common/weapons/weapon/minelayer.qc +++ b/qcsrc/common/weapons/weapon/minelayer.qc @@ -526,8 +526,8 @@ METHOD(MineLayer, describe, string(MineLayer this)) "The secondary fire instantaneously detonates any mines fired by the primary fire, first waiting until you're far enough away.\n\n" "It consumes %s ammo for each mine laid.\n\n" "The mines are not launched very far before they hit the ground, so the %s isn't very effective at medium to long ranges. " - "It is often used to protect important areas of the map such as the flag in %s, control points in %s, or checkpoints in %s."), - COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this), COLORED_NAME(MAPINFO_TYPE_CTF), COLORED_NAME(MAPINFO_TYPE_ONSLAUGHT), COLORED_NAME(MAPINFO_TYPE_ASSAULT)); + "It is often used to protect important areas of the map such as the flag in %s, control points in %s, or checkpoints in %s.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this), COLORED_NAME(MAPINFO_TYPE_CTF), COLORED_NAME(MAPINFO_TYPE_ONSLAUGHT), COLORED_NAME(MAPINFO_TYPE_ASSAULT), W_Guide_DPS_onlyOne_unnamed(this.netname)); } #endif diff --git a/qcsrc/common/weapons/weapon/mortar.qc b/qcsrc/common/weapons/weapon/mortar.qc index 3ff9d799b1..7af648b023 100644 --- a/qcsrc/common/weapons/weapon/mortar.qc +++ b/qcsrc/common/weapons/weapon/mortar.qc @@ -382,8 +382,8 @@ METHOD(Mortar, describe, string(Mortar this)) "The secondary fire shoots a similar grenade that explodes shortly after bouncing.\n\n" "It consumes %s ammo for every grenade launched.\n\n" "The %s works best at close to medium ranges, but it's quite tricky to hit an enemy if they're airborne. " - "Since the secondary fire grenade bounces before exploding, it can be bounced against walls to damage enemies lurking around a corner."), - COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this)); + "Since the secondary fire grenade bounces before exploding, it can be bounced against walls to damage enemies lurking around a corner.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this), W_Guide_DPS(this.netname, "primary", "secondary")); } #endif diff --git a/qcsrc/common/weapons/weapon/rifle.qc b/qcsrc/common/weapons/weapon/rifle.qc index 760319cd19..fe6e595ef4 100644 --- a/qcsrc/common/weapons/weapon/rifle.qc +++ b/qcsrc/common/weapons/weapon/rifle.qc @@ -271,8 +271,8 @@ METHOD(Rifle, describe, string(Rifle this)) "It consumes %s ammo for each bullet shot.\n\n" "Unlike the %s, the secondary fire doesn't zoom, so the ^3+zoom^7 bind needs to be used manually with the %s. " "Also, it needs to be reloaded after its magazine is emptied.\n\n" - "Similar to the %s, the %s can be used at any range, but it stands out at long ranges."), - COLORED_NAME(this), COLORED_NAME(ITEM_Bullets), COLORED_NAME(WEP_VORTEX), COLORED_NAME(this), COLORED_NAME(WEP_VORTEX), COLORED_NAME(this)); + "Similar to the %s, the %s can be used at any range, but it stands out at long ranges.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Bullets), COLORED_NAME(WEP_VORTEX), COLORED_NAME(this), COLORED_NAME(WEP_VORTEX), COLORED_NAME(this), W_Guide_DPS_secondaryMultishot(this.netname, "primary", "secondary", "secondary_shots", "")); } #endif diff --git a/qcsrc/common/weapons/weapon/seeker.qc b/qcsrc/common/weapons/weapon/seeker.qc index 52d5928c1c..27aeadd2eb 100644 --- a/qcsrc/common/weapons/weapon/seeker.qc +++ b/qcsrc/common/weapons/weapon/seeker.qc @@ -676,8 +676,8 @@ METHOD(Seeker, describe, string(Seeker this)) "The secondary fire launches a rapid barrage of scattered explosives that travel only a short distance.\n\n" "It consumes %s ammo, even when the tag doesn't land.\n\n" "The %s primary fire deals quite a lot of damage when a tag lands, although it requires skill to aim effectively. " - "The secondary fire is only useful in close range combat, and sometimes the explosives can damage yourself too."), - COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this)); + "The secondary fire is only useful in close range combat, and sometimes the explosives can damage yourself too.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Rockets), COLORED_NAME(this), W_Guide_DPS_primaryMultishot(this.netname, "missile", "flac", "missile_count", "tag_refire")); } #endif diff --git a/qcsrc/common/weapons/weapon/shotgun.qc b/qcsrc/common/weapons/weapon/shotgun.qc index 429d47b726..8328a15c16 100644 --- a/qcsrc/common/weapons/weapon/shotgun.qc +++ b/qcsrc/common/weapons/weapon/shotgun.qc @@ -395,8 +395,8 @@ METHOD(Shotgun, describe, string(Shotgun this)) "The secondary fire swings the %s, slapping players close enough with the head of the weapon. " "Since the slap takes a moment to land, timing this well is difficult.\n\n" "The primary fire consumes %s ammo, although if you spawn in with the %s you will already have some.\n\n" - "The %s's damage drops off quickly as the range increases, so it is only useful for close combat or sometimes medium range combat."), - COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(ITEM_Shells), COLORED_NAME(this), COLORED_NAME(this)); + "The %s's damage drops off quickly as the range increases, so it is only useful for close combat or sometimes medium range combat.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(ITEM_Shells), COLORED_NAME(this), COLORED_NAME(this), W_Guide_DPS_primaryMultishot(this.netname, "primary", "secondary", "primary_bullets", "")); } #endif diff --git a/qcsrc/common/weapons/weapon/tuba.qc b/qcsrc/common/weapons/weapon/tuba.qc index 82c73daaf1..f03ee2a074 100644 --- a/qcsrc/common/weapons/weapon/tuba.qc +++ b/qcsrc/common/weapons/weapon/tuba.qc @@ -603,8 +603,8 @@ METHOD(Tuba, describe, string(Tuba this)) "The only ammo it needs to operate is the breath from your lungs.\n\n" "Since your enemies need to be close by to hear your rubbish music, the %s is only effective at very close ranges.\n\n" "The pitch the %s plays depends on the movement keys pressed. " - "Reloading the weapon switches its model and notes played."), - COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this)); + "Reloading the weapon switches its model and notes played.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(this), COLORED_NAME(this), W_Guide_DPS_onlyOne_unnamed(this.netname)); } #endif diff --git a/qcsrc/common/weapons/weapon/vaporizer.qc b/qcsrc/common/weapons/weapon/vaporizer.qc index eb26fcbcea..8fe7de55f1 100644 --- a/qcsrc/common/weapons/weapon/vaporizer.qc +++ b/qcsrc/common/weapons/weapon/vaporizer.qc @@ -417,10 +417,10 @@ METHOD(Vaporizer, describe, string(Vaporizer this)) TC(Vaporizer, this); return sprintf(_("The %s is unique weapon, firing a deadly beam of energy dealing a huge amount of damage. " "In %s, the beam has the ability to instantly kill enemies with a single shot, unless they have an %s.\n\n" - "The secondary fire fires a laser similar to that fired by the %s, with very strong knockback.\n\n" + "The secondary fire fires a laser identical to that fired by the %s, with strong knockback.\n\n" "It is a superweapon, so isn't often found in game, except in %s where all players spawn with it.\n\n" - "It consumes some %s ammo with each shot."), - COLORED_NAME(this), COLORED_NAME(MUTATOR_mutator_instagib), COLORED_NAME(ITEM_ExtraLife), COLORED_NAME(WEP_BLASTER), COLORED_NAME(MUTATOR_mutator_instagib), COLORED_NAME(ITEM_Cells)); + "It consumes some %s ammo with each shot.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(MUTATOR_mutator_instagib), COLORED_NAME(ITEM_ExtraLife), COLORED_NAME(WEP_BLASTER), COLORED_NAME(MUTATOR_mutator_instagib), COLORED_NAME(ITEM_Cells), W_Guide_DPS_onlyOne(this.netname, "primary")); } #endif diff --git a/qcsrc/common/weapons/weapon/vortex.qc b/qcsrc/common/weapons/weapon/vortex.qc index dd9d49b827..cdb8962d21 100644 --- a/qcsrc/common/weapons/weapon/vortex.qc +++ b/qcsrc/common/weapons/weapon/vortex.qc @@ -385,8 +385,8 @@ METHOD(Vortex, describe, string(Vortex this)) "It consumes %s ammo for each bullet shot.\n\n" "Unlike the %s, the %s doesn't need to be reloaded manually, although you have to wait a couple seconds between shots. " "Uniquely, it can be fired slightly before it finishes completely reloading, albeit with the tradeoff of dealing slightly less damage.\n\n" - "Similar to the %s, the %s can be used at any range, but it stands out at long ranges."), - COLORED_NAME(this), COLORED_NAME(ITEM_Cells), COLORED_NAME(WEP_RIFLE), COLORED_NAME(this), COLORED_NAME(WEP_RIFLE), COLORED_NAME(this)); + "Similar to the %s, the %s can be used at any range, but it stands out at long ranges.\n\n%s"), + COLORED_NAME(this), COLORED_NAME(ITEM_Cells), COLORED_NAME(WEP_RIFLE), COLORED_NAME(this), COLORED_NAME(WEP_RIFLE), COLORED_NAME(this), W_Guide_DPS_onlyOne(this.netname, "primary")); } #endif -- 2.39.5