]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Add DPS information to the guide
authorotta8634 <k9wolf@pm.me>
Wed, 14 May 2025 09:16:36 +0000 (17:16 +0800)
committerotta8634 <k9wolf@pm.me>
Wed, 14 May 2025 09:19:27 +0000 (17:19 +0800)
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.

25 files changed:
qcsrc/common/mutators/mutator/overkill/okhmg.qc
qcsrc/common/mutators/mutator/overkill/okmachinegun.qc
qcsrc/common/mutators/mutator/overkill/oknex.qc
qcsrc/common/mutators/mutator/overkill/okrpc.qc
qcsrc/common/mutators/mutator/overkill/okshotgun.qc
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/hook.qc
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/rifle.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/tuba.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/common/weapons/weapon/vortex.qc

index 2968c6f026a570dd63d95019380170a5b8b21086..d18f2e56c25ef7828277e6dac58e532b3f08bf81 100644 (file)
@@ -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
index 1b4e6ee9c5f3bb52602929911109d2c804bcb429..f03c32873081db4b917200e72f8f961e715a355f 100644 (file)
@@ -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
index 1c5e92a357f91d67910054177bc2cd516c4caae5..d9695c62f1791605ac88d944c9b52810f3b1860c 100644 (file)
@@ -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
index 64b2b423b3fe58d4653beda262e9995eb3bcf798..b2a03327c9a517db380e0f2e974cfba21226db32 100644 (file)
@@ -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
index 22dfa1ed82d731d979ffc9de3a0d1b5dfb55e855..26b0730ceabab30824fcd8ed1e0005e1390a306b 100644 (file)
@@ -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
index 75da68b9ab01cbd1cfaa80af047559a09b074738..80d69b8ed59a0b04825fc775161d17ed53eb977f 100644 (file)
@@ -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
index 53693e0cc692fdf7e1777be853cc72aab25f7783..37188d0a76eecb77378818b7aa7065ac5bef72d1 100644 (file)
@@ -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
index 672a1bdcdcafd62c3cbb19c49350329f523692f3..c7dd72cc88cf2ee637541a4a6ce7fc71e56d95c6 100644 (file)
@@ -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
index 1ab24eada6ff6ad743707c14e80432bef8c471f7..61d0eddf3d12b0af8f25ad777a8314146b39013e 100644 (file)
@@ -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
index 743ab8e1ec16f0f7518416eccade5b20ab473e77..d8fd1c1887d713f1a9da2c3128427cdfe75c867b 100644 (file)
@@ -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
index 975c73045de2f0168220c8e65d96173ad41d99ed..cd91096c116625b9d04cb07947d530df898f1801 100644 (file)
@@ -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
index a53b53a66251a200863db5fba034a9328a9d518b..0856a2c2c71efe3b1768abd0579cb9cfb2363e15 100644 (file)
@@ -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
index 82bb89a23681f31c964b34f6a5504531324336c2..2daf304e622283a95637d8acb6acd93b7a18e89a 100644 (file)
@@ -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
index 97b63dd69cd47782cda1cf902a1a4781e79dda6e..92d3ca77511d1e964a84e4360ff3749ee7000d27 100644 (file)
@@ -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
index b6a2ad8e8773e14b3a0d9b6c4eecd1d017ca603d..2d4c277c478f86c1ca7def976c40cd3bd4eca6d9 100644 (file)
@@ -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
index 706e9af2a188dd2afd5dfdf321a29ef81cf6bc78..510680544eb5535675f54c1d27f6859f60a4c310 100644 (file)
@@ -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
index ece4efa21e25e1578e9f96ca11971bf8ef882173..ec9bb143992b691109a2763baf7120165cfc5d59 100644 (file)
@@ -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
index 074c4b7fa3079c203ef182b284ff99f0398e4a61..9e290a8e31cbab68d4e6ffc422b3ba775d4641e1 100644 (file)
@@ -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
index 3ff9d799b1a50284ef39c46b98b4a20b9972982f..7af648b02366b278c839c1229f08041a7f0b1845 100644 (file)
@@ -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
index 760319cd19a3c27469d0a96dfcd848215919aa8c..fe6e595ef40ae9e5826f7aab5674f6d8d3caad5f 100644 (file)
@@ -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
index 52d5928c1c8b6819e4571538d239ad40ee55d830..27aeadd2eba3d0ce27656bdeb4f053ddeb64837e 100644 (file)
@@ -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
index 429d47b726d5ab5a0192acc75442ab69cc803e99..8328a15c160c799e7dc4ada0e29b0bc531f44b56 100644 (file)
@@ -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
index 82c73daaf12531ed3742653e001f2378f1ff1b08..f03ee2a074e31f6dfeb1d176d3491059bd3883bd 100644 (file)
@@ -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
index eb26fcbcea014392d812257516aaec07a2d5ba7c..8fe7de55f1ef9ddf962932892f5288e1f42ad085 100644 (file)
@@ -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
index dd9d49b827498552f84862696a911df6d1149b5e..cdb8962d21e1dd58168e0713a18d3d4dfc937766 100644 (file)
@@ -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