]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Add shotgun
authorMario <mario.mario@y7mail.com>
Wed, 11 Dec 2013 08:15:57 +0000 (19:15 +1100)
committerMario <mario.mario@y7mail.com>
Wed, 11 Dec 2013 08:15:57 +0000 (19:15 +1100)
bal-wep-xonotic.cfg
qcsrc/client/damage.qc
qcsrc/client/hud.qc
qcsrc/common/notifications.qh
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/w_shotgun.qc [new file with mode: 0644]
qcsrc/server/cl_client.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/mutator_nades.qc
qcsrc/server/weapons/weaponsystem.qc

index 51ab517bc48238bc1cc4a061bd6f80e15f776def..e395278bd13d7094d49d58b2a54adc4da6380ef4 100644 (file)
@@ -683,3 +683,35 @@ set g_balance_seeker_weaponreplace ""
 set g_balance_seeker_weaponstart 0
 set g_balance_seeker_weaponstartoverride -1
 // }}}
+// {{{ #20: Shotgun (MUTATOR WEAPON)
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_animtime 0.2
+set g_balance_shotgun_primary_bulletconstant 75
+set g_balance_shotgun_primary_bullets 14
+set g_balance_shotgun_primary_damage 4
+set g_balance_shotgun_primary_force 15
+set g_balance_shotgun_primary_refire 0.75
+set g_balance_shotgun_primary_speed 8000
+set g_balance_shotgun_primary_spread 0.12
+set g_balance_shotgun_reload_ammo 0
+set g_balance_shotgun_reload_time 2
+set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_animtime 1
+set g_balance_shotgun_secondary_damage 80
+set g_balance_shotgun_secondary_force 200
+set g_balance_shotgun_secondary_melee_delay 0.25
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 40
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_refire 1.25
+set g_balance_shotgun_switchdelay_drop 0.2
+set g_balance_shotgun_switchdelay_raise 0.2
+set g_balance_shotgun_weaponreplace ""
+set g_balance_shotgun_weaponstart 0
+set g_balance_shotgun_weaponstartoverride -1
+// }}}
index eef9e23ede00e7de3bc8c88eae44ce08f4079363..9a61afdf904131b4a9fbe759b725ca3043f767ab 100644 (file)
@@ -88,7 +88,7 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum)
 
        // if damage was dealt with a bullet weapon, our effect is blood
        // since blood is species dependent, include the species tag
-       if(type == WEP_SHOCKWAVE || type == WEP_UZI || type == WEP_RIFLE)
+       if(type == WEP_SHOCKWAVE || type == WEP_SHOTGUN || type == WEP_UZI || type == WEP_RIFLE)
        {
                if(self.isplayermodel)
                {
index ae8259d04baaa2abc0f6936ac6cb7317c3b500fd..6520048dc52c14428b25580f28d9d77480919a2c 100644 (file)
@@ -426,6 +426,7 @@ float GetAmmoTypeForWep(float i) // WEAPONTODO
        switch(i)
        {
                case WEP_SHOCKWAVE: return 0;
+               case WEP_SHOTGUN: return 0;
                case WEP_UZI: return 1;
                case WEP_MORTAR: return 2;
                case WEP_MINE_LAYER: return 2;
index 5fac570d3ec53f6d7892ad84b8475d637725aae7..a1ee8d0518d0d3159783c53f699d1d6a48f4727d 100644 (file)
@@ -509,6 +509,8 @@ void Send_Notification_WOCOVA(
        MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_SPRAY,           3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponseeker",           _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"), "") \
        MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_TAG,             3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponseeker",           _("^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"), "") \
        MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_SUICIDE,                2, 1, "s1 s2loc spree_lost", "s1",                 "weaponseeker",           _("^BG%s^K1 played with tiny Seeker rockets%s%s"), "") \
+       MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER,                3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponshotgun",          _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"), "") \
+       MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER_SLAP,           3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1",  "notify_melee_shotgun",   _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"), "") \
        MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponshotgun",          _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shockwave%s%s"), "") \
        MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER_SLAP,         3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1",  "notify_melee_shotgun",   _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shockwave%s%s"), "") \
        MSG_INFO_NOTIF(1, INFO_WEAPON_THINKING_WITH_PORTALS,         2, 1, "s1 s2loc spree_lost", "s1",                 "notify_selfkill",        _("^BG%s^K1 is now thinking with portals%s%s"), "") \
@@ -792,6 +794,8 @@ void Send_Notification_WOCOVA(
        MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_SPRAY,           NO_MSG,        INFO_WEAPON_SEEKER_MURDER_SPRAY,           NO_MSG) \
        MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_TAG,             NO_MSG,        INFO_WEAPON_SEEKER_MURDER_TAG,             NO_MSG) \
        MSG_MULTI_NOTIF(1, WEAPON_SEEKER_SUICIDE,                NO_MSG,        INFO_WEAPON_SEEKER_SUICIDE,                CENTER_DEATH_SELF_GENERIC) \
+       MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER,                NO_MSG,        INFO_WEAPON_SHOTGUN_MURDER,                NO_MSG) \
+       MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER_SLAP,           NO_MSG,        INFO_WEAPON_SHOTGUN_MURDER_SLAP,           NO_MSG) \
        MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER,              NO_MSG,        INFO_WEAPON_SHOCKWAVE_MURDER,              NO_MSG) \
        MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER_SLAP,         NO_MSG,        INFO_WEAPON_SHOCKWAVE_MURDER_SLAP,         NO_MSG) \
        MSG_MULTI_NOTIF(1, WEAPON_THINKING_WITH_PORTALS,         NO_MSG,        INFO_WEAPON_THINKING_WITH_PORTALS,         CENTER_DEATH_SELF_GENERIC) \
index de6266f3dfab84f6ad9b3ac9a291d186fca37b36..9429a26bc8296a0f7afdd514ae1f9fdc1cb81f0d 100644 (file)
@@ -24,3 +24,4 @@
 #include "w_rifle.qc"
 #include "w_fireball.qc"
 #include "w_seeker.qc"
+#include "w_shotgun.qc"
diff --git a/qcsrc/common/weapons/w_shotgun.qc b/qcsrc/common/weapons/w_shotgun.qc
new file mode 100644 (file)
index 0000000..8dfa393
--- /dev/null
@@ -0,0 +1,323 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ SHOTGUN,
+/* function  */ w_shotgun,
+/* ammotype  */ ammo_none,
+/* impulse   */ 2,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_MUTATORBLOCKED,
+/* rating    */ BOT_PICKUP_RATING_LOW,
+/* model     */ "shotgun",
+/* shortname */ "shotgun",
+/* fullname  */ _("Shotgun")
+);
+
+#define SHOTGUN_SETTINGS(w_cvar,w_prop) SHOTGUN_SETTINGS_LIST(w_cvar, w_prop, SHOTGUN, shotgun)
+#define SHOTGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
+       w_cvar(id, sn, PRI,  ammo) \
+       w_cvar(id, sn, BOTH, animtime) \
+       w_cvar(id, sn, BOTH, refire) \
+       w_cvar(id, sn, PRI,  bullets) \
+       w_cvar(id, sn, PRI,  bulletconstant) \
+       w_cvar(id, sn, BOTH, damage) \
+       w_cvar(id, sn, BOTH, force) \
+       w_cvar(id, sn, PRI,  spread) \
+       w_cvar(id, sn, PRI,  speed) \
+       w_cvar(id, sn, NONE, secondary) \
+       w_cvar(id, sn, SEC,  melee_time) \
+       w_cvar(id, sn, SEC,  melee_no_doubleslap) \
+       w_cvar(id, sn, SEC,  melee_traces) \
+       w_cvar(id, sn, SEC,  melee_swing_up) \
+       w_cvar(id, sn, SEC,  melee_swing_side) \
+       w_cvar(id, sn, SEC,  melee_nonplayerdamage) \
+       w_cvar(id, sn, SEC,  melee_multihit) \
+       w_cvar(id, sn, SEC,  melee_delay) \
+       w_cvar(id, sn, SEC,  melee_range) \
+       w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
+       w_prop(id, sn, float,  reloading_time, reload_time) \
+       w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
+       w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
+       w_prop(id, sn, string, weaponreplace, weaponreplace) \
+       w_prop(id, sn, float,  weaponstart, weaponstart) \
+       w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride)
+
+#ifdef SVQC
+SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
+#endif
+#else
+#ifdef SVQC
+
+void W_Shotgun_Attack (void)
+{
+       float   sc;
+       entity flash;
+
+       W_DecreaseAmmo(WEP_CVAR_PRI(shotgun, ammo));
+
+       W_SetupShot (self, TRUE, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
+       for (sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
+               fireBallisticBullet(w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, speed), 5, WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN, 0, WEP_CVAR_PRI(shotgun, bulletconstant));
+       endFireBallisticBullet();
+
+       pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
+
+       // casing code
+       if (autocvar_g_casings >= 1)
+               for (sc = 0;sc < WEP_CVAR_PRI(shotgun, ammo);sc = sc + 1)
+                       SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 30) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 1, self);
+
+       // muzzle flash for 1st person view
+       flash = spawn();
+       setmodel(flash, "models/uziflash.md3"); // precision set below
+       flash.think = SUB_Remove;
+       flash.nextthink = time + 0.06;
+       flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+       W_AttachToShotorg(flash, '5 0 0');
+}
+
+.float swing_prev;
+.entity swing_alreadyhit;
+void shotgun_meleethink (void)
+{
+       // declarations
+       float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
+       entity target_victim;
+       vector targpos;
+
+       if(!self.cnt) // set start time of melee
+       {
+               self.cnt = time;
+               W_PlayStrengthSound(self.realowner);
+       }
+
+       makevectors(self.realowner.v_angle); // update values for v_* vectors
+
+       // calculate swing percentage based on time
+       meleetime = WEP_CVAR_SEC(shotgun, melee_time) * W_WeaponRateFactor();
+       swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10);
+       f = ((1 - swing) * WEP_CVAR_SEC(shotgun, melee_traces));
+
+       // check to see if we can still continue, otherwise give up now
+       if((self.realowner.deadflag != DEAD_NO) && WEP_CVAR_SEC(shotgun, melee_no_doubleslap))
+       {
+               remove(self);
+               return;
+       }
+
+       // if okay, perform the traces needed for this frame
+       for(i=self.swing_prev; i < f; ++i)
+       {
+               swing_factor = ((1 - (i / WEP_CVAR_SEC(shotgun, melee_traces))) * 2 - 1);
+
+               targpos = (self.realowner.origin + self.realowner.view_ofs
+                       + (v_forward * WEP_CVAR_SEC(shotgun, melee_range))
+                       + (v_up * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_up))
+                       + (v_right * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_side)));
+
+               WarpZone_traceline_antilag(self, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, self, ANTILAG_LATENCY(self.realowner));
+
+               // draw lightning beams for debugging
+               //te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5);
+               //te_customflash(targpos, 40,  2, '1 1 1');
+
+               is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body");
+
+               if((trace_fraction < 1) // if trace is good, apply the damage and remove self
+                       && (trace_ent.takedamage == DAMAGE_AIM)
+                       && (trace_ent != self.swing_alreadyhit)
+                       && (is_player || WEP_CVAR_SEC(shotgun, melee_nonplayerdamage)))
+               {
+                       target_victim = trace_ent; // so it persists through other calls
+
+                       if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught.
+                               swing_damage = (WEP_CVAR_SEC(shotgun, damage) * min(1, swing_factor + 1));
+                       else
+                               swing_damage = (WEP_CVAR_SEC(shotgun, melee_nonplayerdamage) * min(1, swing_factor + 1));
+
+                       //print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
+
+                       Damage(target_victim, self.realowner, self.realowner,
+                               swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY,
+                               self.realowner.origin + self.realowner.view_ofs,
+                               v_forward * WEP_CVAR_SEC(shotgun, force));
+
+                       if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); }
+
+                       // draw large red flash for debugging
+                       //te_customflash(targpos, 200, 2, '15 0 0');
+
+                       if(WEP_CVAR_SEC(shotgun, melee_multihit)) // allow multiple hits with one swing, but not against the same player twice.
+                       {
+                               self.swing_alreadyhit = target_victim;
+                               continue; // move along to next trace
+                       }
+                       else
+                       {
+                               remove(self);
+                               return;
+                       }
+               }
+       }
+
+       if(time >= self.cnt + meleetime)
+       {
+               // melee is finished
+               remove(self);
+               return;
+       }
+       else
+       {
+               // set up next frame
+               self.swing_prev = i;
+               self.nextthink = time;
+       }
+}
+
+void W_Shotgun_Attack2 (void)
+{
+       sound (self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTEN_NORM);
+       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready);
+
+       entity meleetemp;
+       meleetemp = spawn();
+       meleetemp.realowner = self;
+       meleetemp.think = shotgun_meleethink;
+       meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor();
+       W_SetupShot_Range(self, TRUE, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
+}
+
+void spawnfunc_weapon_shotgun(); // defined in t_items.qc
+
+.float shotgun_primarytime;
+
+float w_shotgun(float req)
+{
+       switch(req)
+       {
+               case WR_AIM:
+               {
+                       if(vlen(self.origin-self.enemy.origin) <= WEP_CVAR_SEC(shotgun, melee_range))
+                               self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE);
+                       else
+                               self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
+
+                       return TRUE;
+               }
+               case WR_THINK:
+               {
+                       if(WEP_CVAR(shotgun, reload_ammo) && self.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
+                       {
+                               // don't force reload an empty shotgun if its melee attack is active
+                               if (!(WEP_CVAR(shotgun, secondary) && self.ammo_shells < WEP_CVAR_PRI(shotgun, ammo)))
+                                       WEP_ACTION(self.weapon, WR_RELOAD);
+                       }
+                       else
+                       {
+                               if (self.BUTTON_ATCK)
+                               {
+                                       if (time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+                                       {
+                                               if(weapon_prepareattack(0, WEP_CVAR_PRI(shotgun, animtime)))
+                                               {
+                                                       W_Shotgun_Attack();
+                                                       self.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor();
+                                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
+                                               }
+                                       }
+                               }
+                       }
+                       if (self.clip_load >= 0) // we are not currently reloading
+                       if (!self.crouch) // no crouchmelee please
+                       if (self.BUTTON_ATCK2 && WEP_CVAR(shotgun, secondary))
+                       if (weapon_prepareattack(1, WEP_CVAR_SEC(shotgun, refire)))
+                       {
+                               // attempt forcing playback of the anim by switching to another anim (that we never play) here...
+                               weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2);
+                       }
+                       
+                       return TRUE;
+               }
+               case WR_INIT:
+               {
+                       precache_model ("models/uziflash.md3");
+                       precache_model ("models/weapons/g_shotgun.md3");
+                       precache_model ("models/weapons/v_shotgun.md3");
+                       precache_model ("models/weapons/h_shotgun.iqm");
+                       precache_sound ("misc/itempickup.wav");
+                       precache_sound ("weapons/shotgun_fire.wav");
+                       precache_sound ("weapons/shotgun_melee.wav");
+                       SHOTGUN_SETTINGS(WEP_SKIPCVAR, WEP_SET_PROP)
+                       return TRUE;
+               }
+               case WR_SETUP:
+               {
+                       self.current_ammo = ammo_none;
+                       return TRUE;
+               }
+               case WR_CHECKAMMO1:
+               case WR_CHECKAMMO2:
+               {
+                       // shotgun has infinite ammo
+                       return TRUE;
+               }
+               case WR_CONFIG:
+               {
+                       SHOTGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
+                       return TRUE;
+               }
+               case WR_RELOAD:
+               {
+                       W_Reload(WEP_CVAR_PRI(shotgun, ammo), "weapons/reload.wav"); // WEAPONTODO
+                       return TRUE;
+               }
+               case WR_SUICIDEMESSAGE:
+               {
+                       return WEAPON_THINKING_WITH_PORTALS;
+               }
+               case WR_KILLMESSAGE:
+               {
+                       if(w_deathtype & HITTYPE_SECONDARY)
+                               return WEAPON_SHOTGUN_MURDER_SLAP;
+                       else
+                               return WEAPON_SHOTGUN_MURDER;
+               }
+       }
+
+       return TRUE;
+}
+#endif
+#ifdef CSQC
+.float prevric;
+float w_shotgun(float req)
+{
+       switch(req)
+       {
+               case WR_IMPACTEFFECT:
+               {
+                       vector org2;
+                       org2 = w_org + w_backoff * 2;
+                       pointparticles(particleeffectnum("shotgun_impact"), org2, w_backoff * 1000, 1);
+                       if(!w_issilent && time - self.prevric > 0.25)
+                       {
+                               if(w_random < 0.0165)
+                                       sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM);
+                               else if(w_random < 0.033)
+                                       sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM);
+                               else if(w_random < 0.05)
+                                       sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM);
+                               self.prevric = time;
+                       }
+
+                       return TRUE;
+               }
+               case WR_INIT:
+               {
+                       precache_sound("weapons/ric1.wav");
+                       precache_sound("weapons/ric2.wav");
+                       precache_sound("weapons/ric3.wav");
+                       return TRUE;
+               }
+       }
+       return TRUE;
+}
+#endif
+#endif
index 7bb024edb70bde4048983441cb0bf6d99870f8d9..7b296f6efceacac63320c57c47bab13969e3ce2c 100644 (file)
@@ -2348,7 +2348,7 @@ void PlayerPreThink (void)
                        do_crouch = 0;
                if(self.freezetag_frozen)
                        do_crouch = 0;
-               if(self.weapon == WEP_SHOCKWAVE && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink) // WEAPONTODO
+               if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink) // WEAPONTODO
                        do_crouch = 0;
 
                if (do_crouch)
index 1527ba4a4f9e8079c8e29f46972b4c56e6e05673..debf95aa4f806e88766e67a3cf3d04a83367851c 100644 (file)
@@ -640,7 +640,7 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO
                        d = FALSE;
        }
        else if (g_cts)
-               d = (i == WEP_SHOCKWAVE); // WEAPONTODO: how to handle shotgun in CTS mode? we're replacing it.. so.... 
+               d = (i == WEP_SHOTGUN);
        else if (g_nexball)
                d = 0; // weapon is set a few lines later
        else
@@ -648,7 +648,7 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO
 
        if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
                d |= (i == WEP_HOOK);
-       if(weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED) // never default mutator blocked guns
+       if(!g_cts && (weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED)) // never default mutator blocked guns
                d = 0;
 
        var float t = weaponinfo.weaponstartoverride;
index 001a71a2b09bba7e021c8651b7025df4cb71b6ed..fcccac72154df171aaa48dd8ddad09cd8f738a68 100644 (file)
@@ -113,10 +113,10 @@ void nade_damage(entity inflictor, entity attacker, float damage, float deathtyp
        if(DEATH_ISWEAPON(deathtype, WEP_UZI))
                damage = self.max_health * 0.1;
 
-       if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) && !(deathtype & HITTYPE_SECONDARY)) // WEAPONTODO
+       if((DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) && !(deathtype & HITTYPE_SECONDARY)) // WEAPONTODO
                damage = self.max_health * 1.1;
 
-       if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) && (deathtype & HITTYPE_SECONDARY))
+       if((DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) && (deathtype & HITTYPE_SECONDARY))
        {
                damage = self.max_health * 0.1;
                force *= 15;
index 9f605db30d22c166f144b188cb4864901c74a3bb..593919ec0548fa6842581a52fd3fc4513590c414 100644 (file)
@@ -613,7 +613,7 @@ void weapon_thinkf(float fr, float t, void() func)
 
        if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
        {
-               if(self.weapon == WEP_SHOCKWAVE && fr == WFRAME_FIRE2)
+               if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && fr == WFRAME_FIRE2)
                        animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
                else
                        animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);