Merge branch 'master' into Mario/rifle_arena
authorMario <mario.mario@y7mail.com>
Sun, 26 May 2013 10:47:29 +0000 (20:47 +1000)
committerMario <mario.mario@y7mail.com>
Sun, 26 May 2013 10:47:29 +0000 (20:47 +1000)
1  2 
defaultXonotic.cfg
effectinfo.txt
qcsrc/common/constants.qh
qcsrc/common/deathtypes.qh
qcsrc/common/notifications.qh
qcsrc/server/autocvars.qh
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/mutator_riflearena.qc
qcsrc/server/mutators/mutators.qh
qcsrc/server/progs.src

Simple merge
diff --cc effectinfo.txt
@@@ -7778,395 -7778,202 +7778,594 @@@ alpha 190 190 18
  sizeincrease -80
  color 0x0000FF 0x000097
  
 +// nades
 +effect nade_blue
 +trailspacing 1
 +type smoke
 +color 0x006cff 0x0600ff
 +tex 65 65
 +size 3 3
 +sizeincrease -1
 +alpha 100 100 250
 +//gravity -0.11
 +// fire
 +effect nade_blue
 +notunderwater
 +trailspacing 8
 +type smoke
 +color 0x0600ff 0x9794ff
 +tex 65 65
 +size 15 25
 +sizeincrease -10
 +alpha 30 30 150
 +// bubbles
 +effect nade_blue
 +underwater
 +trailspacing 16
 +type bubble
 +tex 62 62
 +color 0x006cff 0x0600ff
 +size 1 1
 +alpha 256 256 256
 +gravity -0.125
 +bounce 1.5
 +liquidfriction 4
 +velocityjitter 16 16 16
 +
 +effect nade_red
 +trailspacing 1
 +type smoke
 +color 0xff0000 0xff3c00
 +tex 65 65
 +size 3 3
 +sizeincrease -1
 +alpha 100 100 250
 +//gravity -0.11
 +// fire
 +effect nade_red
 +notunderwater
 +trailspacing 8
 +type smoke
 +color 0xff0000 0xffa2a2
 +tex 65 65
 +size 15 25
 +sizeincrease -10
 +alpha 30 30 150
 +// bubbles
 +effect nade_red
 +underwater
 +trailspacing 16
 +type bubble
 +tex 62 62
 +color 0xff0000 0xff3c00
 +size 1 1
 +alpha 256 256 256
 +gravity -0.125
 +bounce 1.5
 +liquidfriction 4
 +velocityjitter 16 16 16
 +
 +effect nade_red_burn
 +trailspacing 1
 +type smoke
 +color 0xff0000 0xff3c00
 +tex 65 65
 +size 5 5
 +sizeincrease -1
 +alpha 100 100 250
 +//gravity -0.11
 +// fire
 +effect nade_red_burn
 +notunderwater
 +trailspacing 64
 +type smoke
 +color 0xff0000 0xffa2a2
 +tex 65 65
 +size 45 25
 +sizeincrease -30
 +alpha 200 200 1000
 +// bubbles
 +effect nade_red_burn
 +underwater
 +trailspacing 16
 +type bubble
 +tex 62 62
 +color 0xff0000 0xff3c00
 +size 1 1
 +alpha 256 256 256
 +gravity -0.125
 +bounce 1.5
 +liquidfriction 4
 +velocityjitter 16 16 16
 +effect nade_red_burn
 +trailspacing 16
 +type smoke
 +color 0xff0000 0xff3c00
 +tex 71 73
 +size 15 25
 +sizeincrease -40
 +rotate -180 180 20 -20
 +originjitter 2 2 2
 +velocityjitter 10 10 10
 +alpha 300 900 1500
 +
 +effect nade_blue_burn
 +trailspacing 1
 +type smoke
 +color 0x006cff 0x0600ff
 +tex 65 65
 +size 5 5
 +sizeincrease -1
 +alpha 100 100 250
 +//gravity -0.11
 +// fire
 +effect nade_blue_burn
 +notunderwater
 +trailspacing 64
 +type smoke
 +color 0x0600ff 0x9794ff
 +tex 65 65
 +size 45 25
 +sizeincrease -30
 +alpha 200 200 1000
 +// bubbles
 +effect nade_blue_burn
 +underwater
 +trailspacing 16
 +type bubble
 +tex 62 62
 +color 0x006cff 0x0600ff
 +size 1 1
 +alpha 256 256 256
 +gravity -0.125
 +bounce 1.5
 +liquidfriction 4
 +velocityjitter 16 16 16
 +effect nade_blue_burn
 +trailspacing 16
 +type smoke
 +color 0x006cff 0x0600ff
 +tex 33 33
 +size 25 25
 +sizeincrease -30
 +
 +effect nade_blue_explode
 +countabsolute 1
 +type decal
 +tex 8 16
 +size 88 88
 +alpha 256 256 0
 +originjitter 26 26 26
 +lightradius 300
 +lightradiusfade 1500
 +lightcolor 20 20 100
 +// shockwave
 +effect nade_blue_explode
 +type smoke
 +countabsolute 1
 +tex 33 33
 +size 32 32
 +sizeincrease 1800
 +color 0x80C0FF 0x80C0FF
 +alpha 80 80 650
 +velocitymultiplier 44
 +// fire
 +effect nade_blue_explode
 +notunderwater
 +count 16
 +type smoke
 +color 0x629dff 0x0018ff
 +tex 48 55
 +size 20 24
 +sizeincrease 555
 +alpha 400 656 2000
 +airfriction 30
 +originjitter 50 50 50
 +velocityjitter 320 320 320
 +rotate -180 180 -9 9
 +// fire streched
 +effect nade_blue_explode
 +count 8
 +type spark
 +tex 48 55
 +color 0x629dff 0x0018ff
 +size 60 90
 +alpha 1500 3000 13000
 +stretchfactor 80
 +sizeincrease 40
 +velocityjitter 30 30 30
 +airfriction -9
 +//smoke
 +effect nade_blue_explode
 +type smoke
 +count 32
 +blend alpha
 +tex 0 7
 +size 60 30
 +color 0x222222 0x000000
 +alpha 128 328 390
 +rotate -180 180 2 -2
 +velocityjitter 200 200 200
 +velocityoffset 0 0 180
 +originjitter 50 50 10
 +sizeincrease 50
 +airfriction 0.04
 +gravity 0.4
 +// underwater bubbles
 +effect nade_blue_explode
 +underwater
 +count 32
 +type bubble
 +tex 62 62
 +color 0x404040 0x808080
 +size 3 6
 +alpha 128 256 64
 +gravity -0.125
 +bounce 1.5
 +liquidfriction 0.25
 +originjitter 16 16 16
 +velocityjitter 196 196 196
 +rotate 0 0 0 0
 +// bouncing sparks
 +effect nade_blue_explode
 +notunderwater
 +count 8
 +type spark
 +tex 40 40
 +color 0x006cff 0x0600ff
 +size 1 2
 +alpha 644 956 484
 +gravity 1
 +airfriction 1
 +bounce 1.6
 +liquidfriction 0.8
 +velocityoffset 0 0 80
 +originjitter 16 16 16
 +velocityjitter 424 424 624
 +// notbouncing sparks
 +effect nade_blue_explode
 +count 16
 +type spark
 +tex 40 40
 +color 0x006cff 0x0600ff
 +size 1 2
 +alpha 644 956 684
 +gravity 0.5
 +airfriction 0.7
 +liquidfriction 0.8
 +velocityoffset 0 0 80
 +originjitter 16 16 16
 +velocityjitter 424 424 624
 +// derbis
 +effect nade_blue_explode
 +notunderwater
 +count 12
 +type alphastatic
 +tex 66 68
 +color 0x6a3d25 0xcac5b4
 +size 2 6
 +alpha 644 956 684
 +gravity 1.3
 +airfriction 0.5
 +bounce 1.6
 +velocityjitter 324 324 524
 +rotate -180 180 -1000 1000
 +
 +effect nade_red_explode
 +countabsolute 1
 +type decal
 +tex 8 16
 +size 88 88
 +alpha 256 256 0
 +originjitter 26 26 26
 +lightradius 300
 +lightradiusfade 1500
 +lightcolor 100 20 20
 +// shockwave
 +effect nade_red_explode
 +type smoke
 +countabsolute 1
 +tex 33 33
 +size 32 32
 +sizeincrease 2200
 +color 0xff0000 0xffa2a2
 +alpha 80 80 650
 +velocitymultiplier 44
 +// fire
 +effect nade_red_explode
 +notunderwater
 +count 16
 +type smoke
 +color 0xff0000 0xff4200
 +tex 48 55
 +size 20 24
 +sizeincrease 555
 +alpha 400 656 2000
 +airfriction 30
 +originjitter 50 50 50
 +velocityjitter 320 320 320
 +rotate -180 180 -9 9
 +// fire streched
 +effect nade_red_explode
 +count 8
 +type spark
 +tex 48 55
 +color 0xff0000 0xff4200
 +size 60 90
 +alpha 1500 3000 13000
 +stretchfactor 80
 +sizeincrease 40
 +velocityjitter 30 30 30
 +airfriction -9
 +//smoke
 +effect nade_red_explode
 +type smoke
 +count 32
 +blend alpha
 +tex 0 7
 +size 60 30
 +color 0x222222 0x000000
 +alpha 128 328 390
 +rotate -180 180 2 -2
 +velocityjitter 200 200 200
 +velocityoffset 0 0 180
 +originjitter 50 50 10
 +sizeincrease 50
 +airfriction 0.04
 +gravity 0.4
 +// underwater bubbles
 +effect nade_red_explode
 +underwater
 +count 32
 +type bubble
 +tex 62 62
 +color 0x404040 0x808080
 +size 3 6
 +alpha 128 256 64
 +gravity -0.125
 +bounce 1.5
 +liquidfriction 0.25
 +originjitter 16 16 16
 +velocityjitter 196 196 196
 +rotate 0 0 0 0
 +// bouncing sparks
 +effect nade_red_explode
 +notunderwater
 +count 8
 +type spark
 +tex 40 40
 +color 0xff0000 0xffa2a2
 +size 1 2
 +alpha 644 956 484
 +gravity 1
 +airfriction 1
 +bounce 1.6
 +liquidfriction 0.8
 +velocityoffset 0 0 80
 +originjitter 16 16 16
 +velocityjitter 424 424 624
 +// notbouncing sparks
 +effect nade_red_explode
 +count 16
 +type spark
 +tex 40 40
 +color 0xff0000 0xffa2a2
 +size 1 2
 +alpha 644 956 684
 +gravity 0.5
 +airfriction 0.7
 +liquidfriction 0.8
 +velocityoffset 0 0 80
 +originjitter 16 16 16
 +velocityjitter 424 424 624
 +// derbis
 +effect nade_red_explode
 +notunderwater
 +count 8
 +type smoke
 +tex 71 73
 +color 0xff0000 0xffa2a2
 +size 20 40
 +alpha 644 956 2500
 +originjitter 64 64 64
 +velocityjitter 324 324 324
 +rotate -180 180 -100 100
+ // spawn_point_red -- red team idle spawn point effect
+ effect spawn_point_red
+ count 37.5
+ type static
+ color 0xFF0F0F 0xFF0F0F
+ size 1.0 2.0
+ alpha 64 128 128
+ gravity -0.1
+ airfriction 0.2
+ liquidfriction 0.8
+ originjitter 16 16 64
+ velocityjitter 32 32 0
+ //lightradius 200
+ //lighttime 0
+ //lightcolor 0.4 0.9 0.9
+ // spawn_point_blue -- blue team idle spawn point effect
+ effect spawn_point_blue
+ count 37.5
+ type static
+ color 0x0F0FFF 0x0F0FFF
+ size 1.0 2.0
+ alpha 64 128 128
+ gravity -0.1
+ airfriction 0.2
+ liquidfriction 0.8
+ originjitter 16 16 64
+ velocityjitter 32 32 0
+ //lightradius 200
+ //lighttime 0
+ //lightcolor 0.4 0.9 0.9
+ // spawn_point_yellow -- yellow team idle spawn point effect
+ effect spawn_point_yellow
+ count 37.5
+ type static
+ color 0xFFFF0F 0xFFFF0F
+ size 1.0 2.0
+ alpha 64 128 128
+ gravity -0.1
+ airfriction 0.2
+ liquidfriction 0.8
+ originjitter 16 16 64
+ velocityjitter 32 32 0
+ //lightradius 200
+ //lighttime 0
+ //lightcolor 0.4 0.9 0.9
+ // spawn_point_pink -- pink team idle spawn point effect
+ effect spawn_point_pink
+ count 37.5
+ type static
+ color 0xFF0FFF 0xFF0FFF
+ size 1.0 2.0
+ alpha 64 128 128
+ gravity -0.1
+ airfriction 0.2
+ liquidfriction 0.8
+ originjitter 16 16 64
+ velocityjitter 32 32 0
+ //lightradius 200
+ //lighttime 0
+ //lightcolor 0.4 0.9 0.9
+ // spawn_point_neutral -- neutral idle spawn point effect
+ effect spawn_point_neutral
+ count 37.5
+ type static
+ color 0xFFFFFF 0xFFFFFF
+ size 1.0 2.0
+ alpha 64 128 128
+ gravity -0.1
+ airfriction 0.2
+ liquidfriction 0.8
+ originjitter 16 16 64
+ velocityjitter 32 32 0
+ //lightradius 200
+ //lighttime 0
+ //lightcolor 0.4 0.9 0.9
+ // spawn_event_red -- red team spawning effect
+ effect spawn_event_red
+ count 100
+ type spark
+ tex 64 64
+ color 0xFF0F0F 0xFF0F0F
+ size 1 1
+ alpha 0 256 256
+ stretchfactor 0.6
+ //gravity 1
+ bounce 1
+ originjitter 1 1 1
+ velocityjitter 500 500 500
+ velocitymultiplier 0.1
+ airfriction 2
+ effect spawn_event_red
+ countabsolute 1
+ type smoke
+ tex 65 65
+ size 100 100
+ alpha 190 190 180
+ sizeincrease -80
+ color 0xFF0F0F 0xFF0F0F
+ // spawn_event_blue -- blue team spawning effect
+ effect spawn_event_blue
+ count 100
+ type spark
+ tex 64 64
+ color 0x0F0FFF 0x0F0FFF
+ size 1 1
+ alpha 0 256 256
+ stretchfactor 0.6
+ //gravity 1
+ bounce 1
+ originjitter 1 1 1
+ velocityjitter 500 500 500
+ velocitymultiplier 0.1
+ airfriction 2
+ effect spawn_event_blue
+ countabsolute 1
+ type smoke
+ tex 65 65
+ size 100 100
+ alpha 190 190 180
+ sizeincrease -80
+ color 0x0F0FFF 0x0F0FFF
+ // spawn_event_yellow -- yellow team spawning effect
+ effect spawn_event_yellow
+ count 100
+ type spark
+ tex 64 64
+ color 0xFFFF0F 0xFFFF0F
+ size 1 1
+ alpha 0 256 256
+ stretchfactor 0.6
+ //gravity 1
+ bounce 1
+ originjitter 1 1 1
+ velocityjitter 500 500 500
+ velocitymultiplier 0.1
+ airfriction 2
+ effect spawn_event_yellow
+ countabsolute 1
+ type smoke
+ tex 65 65
+ size 100 100
+ alpha 190 190 180
+ sizeincrease -80
+ color 0xFFFF0F 0xFFFF0F
+ // spawn_event_pink -- pink team spawning effect
+ effect spawn_event_pink
+ count 100
+ type spark
+ tex 64 64
+ color 0xFF0FFF 0xFF0FFF
+ size 1 1
+ alpha 0 256 256
+ stretchfactor 0.6
+ //gravity 1
+ bounce 1
+ originjitter 1 1 1
+ velocityjitter 500 500 500
+ velocitymultiplier 0.1
+ airfriction 2
+ effect spawn_event_pink
+ countabsolute 1
+ type smoke
+ tex 65 65
+ size 100 100
+ alpha 190 190 180
+ sizeincrease -80
+ color 0xFF0FFF 0xFF0FFF
+ // spawn_event_neutral -- neutral spawning effect
+ effect spawn_event_neutral
+ count 100
+ type spark
+ tex 64 64
+ color 0xFFFFFF 0xFFFFFF
+ size 1 1
+ alpha 0 256 256
+ stretchfactor 0.6
+ //gravity 1
+ bounce 1
+ originjitter 1 1 1
+ velocityjitter 500 500 500
+ velocitymultiplier 0.1
+ airfriction 2
+ effect spawn_event_neutral
+ countabsolute 1
+ type smoke
+ tex 65 65
+ size 100 100
+ alpha 190 190 180
+ sizeincrease -80
+ color 0xFFFFFF 0xFFFFFF
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -999,39 -904,25 +904,26 @@@ float sv_taunt
  string GetGametype(); // g_world.qc
  void readlevelcvars(void)
  {
-       g_minstagib = cvar("g_minstagib");
-       // load ALL the mutators
-       if(cvar("g_dodging"))
-               MUTATOR_ADD(mutator_dodging);
-       if(cvar("g_spawn_near_teammate"))
-               MUTATOR_ADD(mutator_spawn_near_teammate);
-       if(cvar("g_physical_items"))
-               MUTATOR_ADD(mutator_physical_items);
-       if(cvar("g_touchexplode"))
-               MUTATOR_ADD(mutator_touchexplode);
-       if(cvar("g_riflearena"))
-               MUTATOR_ADD(mutator_riflearena);
-       if(!g_minstagib)
-       {
-               if(cvar("g_invincible_projectiles"))
-                       MUTATOR_ADD(mutator_invincibleprojectiles);
-               if(cvar("g_new_toys"))
-                       MUTATOR_ADD(mutator_new_toys);
-               if(cvar("g_nix"))
-                       MUTATOR_ADD(mutator_nix);
-               if(cvar("g_rocket_flying"))
-                       MUTATOR_ADD(mutator_rocketflying);
-               if(cvar("g_vampire"))
-                       MUTATOR_ADD(mutator_vampire);           
-               if(cvar("g_superspectate"))
-                       MUTATOR_ADD(mutator_superspec);
-       }
-       // is this a mutator? is this a mode?
-       if(cvar("g_sandbox"))
-               MUTATOR_ADD(sandbox);
+       // load mutators
+       #define CHECK_MUTATOR_ADD(mut_cvar,mut_name,dependence) \
+               { if(cvar(mut_cvar) && dependence) { MUTATOR_ADD(mut_name); } }
+               
+       CHECK_MUTATOR_ADD("g_dodging", mutator_dodging, 1);
+       CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, 1);
+       CHECK_MUTATOR_ADD("g_physical_items", mutator_physical_items, 1);
+       CHECK_MUTATOR_ADD("g_touchexplode", mutator_touchexplode, 1);
+       CHECK_MUTATOR_ADD("g_minstagib", mutator_minstagib, 1);
+       CHECK_MUTATOR_ADD("g_invincible_projectiles", mutator_invincibleprojectiles, !cvar("g_minstagib"));
+       CHECK_MUTATOR_ADD("g_new_toys", mutator_new_toys, !cvar("g_minstagib"));
+       CHECK_MUTATOR_ADD("g_nix", mutator_nix, !cvar("g_minstagib"));
+       CHECK_MUTATOR_ADD("g_rocket_flying", mutator_rocketflying, !cvar("g_minstagib"));
+       CHECK_MUTATOR_ADD("g_vampire", mutator_vampire, !cvar("g_minstagib"));
+       CHECK_MUTATOR_ADD("g_superspectate", mutator_superspec, 1);
+       CHECK_MUTATOR_ADD("g_sandbox", sandbox, 1);
++    CHECK_MUTATOR_ADD("g_riflearena", mutator_riflearena, !cvar("g_minstagib"));
+       
+       #undef CHECK_MUTATOR_ADD
+       
        if(cvar("sv_allow_fullbright"))
                serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
  
index 3355f5b,0000000..24a5fbc
mode 100644,000000..100644
--- /dev/null
@@@ -1,368 -1,0 +1,395 @@@
- void ra_toss_nade(vector _velocity, float _time)
 +.entity ra_nade;
 +.float ra_nade_refire;
 +
++float ra_CanThrowNade()
++{
++      if(self.vehicle)
++              return FALSE;
++              
++      if(gameover)
++              return FALSE;
++              
++      if not(autocvar_g_riflearena_nades)
++              return FALSE;
++              
++      if(forbidWeaponUse())
++              return FALSE;
++              
++      return TRUE;
++}
++
 +void ra_nade_timer_think()
 +{
 +      self.skin = 8 - (self.owner.wait - time) / (autocvar_g_riflearena_nade_lifetime / 10);
 +      self.nextthink = time;
 +      if(!self.owner || wasfreed(self.owner))
 +              remove(self);
 +      
 +}
 +
 +void ra_nade_burn_spawn(entity nade)
 +{
 +      switch(nade.realowner.team)
 +      {
 +              case NUM_TEAM_1:
 +                      CSQCProjectile(nade, TRUE, PROJECTILE_NADE_RED_BURN, TRUE);
 +                      break;
 +              case NUM_TEAM_2:
 +                      CSQCProjectile(nade, TRUE, PROJECTILE_NADE_BLUE_BURN, TRUE);
 +                      break;
 +              default:
 +                      CSQCProjectile(nade, TRUE, PROJECTILE_NADE_RED_BURN, TRUE);
 +                      break;
 +      }
 +}
 +
 +void ra_nade_spawn(entity nade)
 +{
 +      entity timer = spawn();
 +      setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
 +      setattachment(timer, nade, "");
 +      timer.classname = "nade_timer";
 +      timer.colormap = nade.colormap;
 +      timer.glowmod = nade.glowmod;
 +      timer.think = ra_nade_timer_think;
 +      timer.nextthink = time;
 +      timer.wait = nade.wait;
 +      timer.owner = nade;     
 +      timer.skin = 10;
 +      
 +      CSQCProjectile(nade, TRUE, ((nade.realowner.team == NUM_TEAM_2) ? PROJECTILE_NADE_BLUE: PROJECTILE_NADE_RED) , TRUE);
 +      
 +}
 +
 +void ra_nade_boom() // TODO: DamageInfo
 +{
 +      sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM);
 +      sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
 +      pointparticles(particleeffectnum((self.realowner.team == NUM_TEAM_2) ? "nade_blue_explode" : "nade_red_explode"), self.origin + '0 0 1', '0 0 0', 1);
 +
 +
 +      self.takedamage = DAMAGE_NO;
 +      RadiusDamage(self, self.realowner, autocvar_g_riflearena_nade_damage, autocvar_g_riflearena_nade_edgedamage,
 +                               autocvar_g_riflearena_nade_radius, self, autocvar_g_riflearena_nade_force, self.projectiledeathtype, self.enemy);
 +
 +      remove(self);
 +}
 +
 +void ra_nade_touch()
 +{
 +      PROJECTILE_TOUCH;
 +      setsize(self, '-2 -2 -2', '2 2 2');
 +      UpdateCSQCProjectile(self);
 +      if(self.health == autocvar_g_riflearena_nade_health)
 +      {
 +              spamsound(self, CH_SHOTS, strcat("weapons/grenade_bounce", ftos(1 + rint(random() * 5)), ".wav"), VOL_BASE, ATTN_NORM);
 +              return;
 +      }
 +
 +      self.enemy = other;
 +      ra_nade_boom();
 +}
 +
 +void ra_nade_beep()
 +{
 +      sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.wav", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX));
 +      self.think = ra_nade_boom;
 +      self.nextthink = max(self.wait, time);
 +}
 +
 +void ra_nade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 +{
 +      if(DEATH_ISWEAPON(deathtype, WEP_LASER))
 +              return;
 +      
 +      self.velocity += force;
 +
 +      if(!damage)
 +              return;
 +
 +      if(self.health == autocvar_g_riflearena_nade_health)
 +      {
 +              sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX));
 +              self.nextthink = max(time + autocvar_g_riflearena_nade_lifetime, time);
 +              self.think = ra_nade_beep;
 +      }
 +
 +      self.health   -= damage;
 +      self.realowner = attacker;
 +
 +      if(self.health <= 0)
 +              W_PrepareExplosionByDamage(attacker, ra_nade_boom);
 +      else
 +              ra_nade_burn_spawn(self);
 +}
 +
-       entity _nade = self.ra_nade;
-       self.ra_nade = world;
++void ra_toss_nade(entity ent, vector _velocity, float _time)
 +{
-       if(self.crouch)
++      entity _nade = ent.ra_nade;
++      ent.ra_nade = world;
 +      
 +      setorigin(_nade, gettaginfo(_nade, gettagindex(_nade, "Object001")));
 +      setattachment(_nade, world, "");
 +      PROJECTILE_MAKETRIGGER(_nade);
 +      setsize(_nade, '-16 -16 -16', '16 16 16');
 +      _nade.movetype = MOVETYPE_BOUNCE;
 +      
-               _nade.velocity = self.velocity + _velocity;
++      if(ent.crouch)
 +              _nade.velocity = '0 0 -10';
 +      else if(autocvar_g_riflearena_nade_newton_style == 1)
-               _nade.velocity = W_CalculateProjectileVelocity(self.velocity, _velocity, FALSE);
++              _nade.velocity = ent.velocity + _velocity;
 +      else if(autocvar_g_riflearena_nade_newton_style == 2)
 +              _nade.velocity = _velocity;
 +      else
-       self.ra_nade_refire = time + autocvar_g_riflearena_nade_refire;
++              _nade.velocity = W_CalculateProjectileVelocity(ent.velocity, _velocity, FALSE);
 +
 +      _nade.solid = SOLID_BBOX;
 +      _nade.touch = ra_nade_touch;
 +      _nade.health = autocvar_g_riflearena_nade_health;
 +      _nade.takedamage = DAMAGE_YES;
 +      _nade.event_damage = ra_nade_damage;
 +      _nade.teleportable = TRUE;
 +
 +      ra_nade_spawn(_nade);
 +
 +      if(_time)
 +      {
 +              _nade.think = ra_nade_boom;
 +              _nade.nextthink = _time;
 +      }
 +      else
 +              _nade.projectiledeathtype = DEATH_NADE_NORMAL;
 +
-                       ra_toss_nade('0 0 0', time + 0.05);
++      ent.ra_nade_refire = time + autocvar_g_riflearena_nade_refire;
 +}
 +
 +void ra_nade_prime()
 +{
 +      if(self.ra_nade)
 +              remove(self.ra_nade);
 +      
 +      self.ra_nade = spawn();
 +      setmodel(self.ra_nade, "models/weapons/h_ok_grenade.iqm");
 +      setattachment(self.ra_nade, self.weaponentity, "");
 +      self.ra_nade.classname = "nade";
 +      self.ra_nade.realowner = self;
 +      self.ra_nade.colormap = self.colormap;
 +      self.ra_nade.glowmod = self.glowmod;
 +      self.ra_nade.wait = time + autocvar_g_riflearena_nade_lifetime;
 +      self.ra_nade.cnt = time;
 +      self.ra_nade.think = ra_nade_beep;
 +      self.ra_nade.nextthink = max(self.ra_nade.wait - 3, time);
 +      self.ra_nade.projectiledeathtype = DEATH_NADE_NORMAL;
 +}
 +
++MUTATOR_HOOKFUNCTION(ra_VehicleEnter)
++{
++      if(other.ra_nade)
++              ra_toss_nade(other, '0 0 100', max(other.ra_nade.wait, time + 0.05));
++              
++      return FALSE;
++}
++
 +MUTATOR_HOOKFUNCTION(ra_PlayerDamage)
 +{
 +      if(IS_PLAYER(frag_attacker))
 +      {
 +              if (DEATH_ISWEAPON(frag_deathtype, WEP_LASER))
 +              {
 +                      if(frag_attacker == frag_target)
 +                              frag_damage = 5;
 +                      else
 +                              frag_damage = 0;
 +                      if (frag_target != frag_attacker)
 +                      {
 +                              if (frag_target.health >= 1 && IS_PLAYER(frag_target))
 +                                      centerprint(frag_attacker, "Laser inflicts no damage!");
 +                              frag_force = '0 0 0';
 +                      }
 +              }
 +      }
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_PlayerSpawn)
 +{
 +      WEPSET_CLEAR_E(self);
 +      WEPSET_OR_EW(self, WEP_RIFLE);
 +      WEPSET_OR_EW(self, WEP_LASER);
 +      
 +      self.ra_nade_refire = time + 1;
 +      
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_FilterItem)
 +{
 +      switch (self.items)
 +      {
 +              case IT_5HP:
 +              case IT_ARMOR_SHARD:
 +                      return FALSE;
 +      }
 +              
 +      return TRUE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_PlayerThink)
 +{
 +      if(self.ra_nade)
 +              if(self.ra_nade.wait - 0.1 <= time)
-                               ra_toss_nade((v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
++                      ra_toss_nade(self, '0 0 0', time + 0.05);
 +
++      if(ra_CanThrowNade())
 +      if(self.ra_nade_refire < time)
 +      {
 +              if(self.BUTTON_HOOK)
 +              {
 +                      if(!self.ra_nade)
 +                              ra_nade_prime();
 +              }
 +              else if(time - self.ra_nade.cnt >= 1)
 +              {
 +                      if(self.ra_nade)
 +                      {
 +                              makevectors(self.v_angle);
 +                              float _force = time - self.ra_nade.cnt;
 +                              _force /= autocvar_g_riflearena_nade_lifetime;
 +                              _force = autocvar_g_riflearena_nade_minforce + (_force * (autocvar_g_riflearena_nade_maxforce - autocvar_g_riflearena_nade_minforce));                          
-               ra_toss_nade('0 0 100', max(self.ra_nade.wait, time + 0.05));
++                              ra_toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
 +                      }
 +              }
 +      }
 +      
 +      self.hasweapon_complain_spam = time + 5; // this isn't needed, so keep it off
 +      
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_RemovePlayer)
 +{
 +      if(self.ra_nade)
 +              remove(self.ra_nade);
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_StartItems)
 +{
 +      start_items |= IT_UNLIMITED_AMMO;
 +      start_ammo_nails = 100;
 +      
 +      g_grappling_hook = 0;
 +
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_PlayerDies)
 +{
 +      if(self.ra_nade)
-       if(self.freezetag_frozen || !autocvar_g_riflearena_nades || self.vehicle)
++              ra_toss_nade(self, '0 0 100', max(self.ra_nade.wait, time + 0.05));
 +
 +      return 0;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_ForbidThrowCurrentWeapon)
 +{
-                       ra_toss_nade((v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0);
++      if(!ra_CanThrowNade())
 +              return 1;
 +
 +      if(!self.ra_nade)
 +      {
 +              if(self.ra_nade_refire < time)
 +              {
 +                      Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE);
 +                      ra_nade_prime();
 +                      self.ra_nade_refire  = time + autocvar_g_riflearena_nade_refire;
 +              }
 +      }
 +      else
 +      {
 +              if(time - self.ra_nade.cnt >= 1)
 +              {
 +                      makevectors(self.v_angle);
 +                      float _force = time - self.ra_nade.cnt;
 +                      _force /= autocvar_g_riflearena_nade_lifetime;
 +                      _force = autocvar_g_riflearena_nade_minforce + (_force * (autocvar_g_riflearena_nade_maxforce - autocvar_g_riflearena_nade_minforce));
++                      ra_toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0);
 +              }
 +      }
 +      return 1;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_BuildMutatorsString)
 +{
 +      ret_string = strcat(ret_string, ":RA");
 +      return 0;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_BuildMutatorsPrettyString)
 +{
 +      ret_string = strcat(ret_string, ", Rifle Arena");
 +      return 0;
 +}
 +
 +MUTATOR_HOOKFUNCTION(ra_SetModname)
 +{
 +      modname = "Rifle Arena";
 +      return TRUE;
 +}
 +
 +MUTATOR_DEFINITION(mutator_riflearena)
 +{
++      MUTATOR_HOOK(VehicleEnter, ra_VehicleEnter, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerDamage_Calculate, ra_PlayerDamage, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerSpawn, ra_PlayerSpawn, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(FilterItem, ra_FilterItem, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(SetStartItems, ra_StartItems, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(MakePlayerObserver, ra_RemovePlayer, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(ClientDisconnect, ra_RemovePlayer, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerDies, ra_PlayerDies, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerPreThink, ra_PlayerThink, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(ForbidThrowCurrentWeapon, ra_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(BuildMutatorsString, ra_BuildMutatorsString, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(BuildMutatorsPrettyString, ra_BuildMutatorsPrettyString, CBC_ORDER_ANY);
 +      
 +      MUTATOR_ONADD
 +      {
 +              cvar_settemp("g_balance_rifle_secondary_spread", "0");
 +              cvar_settemp("g_balance_rifle_secondary_shots", "1");
 +              cvar_settemp("g_balance_rifle_secondary_animtime", "0.15");
 +              cvar_settemp("g_balance_rifle_secondary_refire", "0.15");
 +              cvar_settemp("g_balance_rifle_secondary_damage", "40");
 +              precache_model("models/ok_nade_counter/ok_nade_counter.md3");
 +              
 +              precache_model("models/weapons/h_ok_grenade.iqm");
 +              precache_model("models/weapons/v_ok_grenade.md3");
 +              precache_sound("weapons/rocket_impact.wav");
 +              precache_sound("weapons/grenade_bounce1.wav");
 +              precache_sound("weapons/grenade_bounce2.wav");
 +              precache_sound("weapons/grenade_bounce3.wav");
 +              precache_sound("weapons/grenade_bounce4.wav");
 +              precache_sound("weapons/grenade_bounce5.wav");
 +              precache_sound("weapons/grenade_bounce6.wav");
 +              precache_sound("overkill/grenadebip.wav");
 +              
 +              weapon_action(WEP_LASER, WR_PRECACHE);
 +              weapon_action(WEP_RIFLE, WR_PRECACHE);
 +              
 +              get_weaponinfo(WEP_HOOK).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
 +      }
 +      
 +      MUTATOR_ONROLLBACK_OR_REMOVE
 +      {
 +              get_weaponinfo(WEP_HOOK).spawnflags &~= WEP_FLAG_MUTATORBLOCKED;
 +      }
 +      
 +      MUTATOR_ONREMOVE
 +      {
 +              print("This cannot be removed at runtime\n");
 +              return -1;
 +      }
 +
 +      return 0;
 +}
@@@ -15,7 -19,7 +19,8 @@@ MUTATOR_DECLARATION(mutator_spawn_near_
  MUTATOR_DECLARATION(mutator_physical_items);
  MUTATOR_DECLARATION(mutator_vampire);
  MUTATOR_DECLARATION(mutator_superspec);
+ MUTATOR_DECLARATION(mutator_minstagib);
  MUTATOR_DECLARATION(mutator_touchexplode);
 +MUTATOR_DECLARATION(mutator_riflearena);
  
  MUTATOR_DECLARATION(sandbox);
@@@ -231,8 -246,8 +246,9 @@@ mutators/mutator_spawn_near_teammate.q
  mutators/mutator_physical_items.qc
  mutators/sandbox.qc
  mutators/mutator_superspec.qc
+ mutators/mutator_minstagib.qc
  mutators/mutator_touchexplode.qc
 +mutators/mutator_riflearena.qc
  
  ../warpzonelib/anglestransform.qc
  ../warpzonelib/mathlib.qc