Merge branch 'master' into Mario/mutator_minstagib
authorMario <mario.mario@y7mail.com>
Wed, 8 May 2013 02:04:39 +0000 (12:04 +1000)
committerMario <mario.mario@y7mail.com>
Wed, 8 May 2013 02:04:39 +0000 (12:04 +1000)
19 files changed:
1  2 
defaultXonotic.cfg
qcsrc/common/notifications.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/aim.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_physics.qc
qcsrc/server/cl_player.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/base.qh
qcsrc/server/mutators/mutator_minstagib.qc
qcsrc/server/mutators/mutators.qh
qcsrc/server/progs.src
qcsrc/server/t_items.qc
qcsrc/server/teamplay.qc
qcsrc/server/w_minstanex.qc

Simple merge
Simple merge
Simple merge
Simple merge
index 08d8ef277bcfb13ee877beb73fc83afd2397d231,3d89301844c248c20f59dd3003e2f3dd434a337e..85c96445acbdbdf85701b5e7524b17e3c83f2255
@@@ -385,8 -385,28 +385,26 @@@ void PutObserverInServer (void
                WriteEntity(MSG_ONE, self);
        }
  
+       if(g_lms)
+       {
+               // Only if the player cannot play at all
+               if(PlayerScore_Add(self, SP_LMS_RANK, 0) == 666)
+                       self.frags = FRAGS_SPECTATOR;
+               else
+                       self.frags = FRAGS_LMS_LOSER;
+       }
+       else if((g_race && g_race_qualifying) || g_cts)
+       {
+               if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
+                       self.frags = FRAGS_LMS_LOSER;
+               else
+                       self.frags = FRAGS_SPECTATOR;
+       }
+       else
+               self.frags = FRAGS_SPECTATOR;
        MUTATOR_CALLHOOK(MakePlayerObserver);
  
 -      minstagib_stop_countdown(self);
 -
        Portal_ClearAll(self);
        
        if(self.alivetime)
@@@ -2581,9 -2600,11 +2547,8 @@@ void PlayerPreThink (void
                        player_powerups();
                }
  
 -              if (g_minstagib)
 -                      minstagib_ammocheck();
 -
                if (self.deadflag != DEAD_NO)
                {
-                       float button_pressed, force_respawn;
                        if(self.personal && g_race_qualifying)
                        {
                                if(time > self.respawn_time)
Simple merge
Simple merge
Simple merge
Simple merge
index fbfe75574b0ae18fe3759cba10cd8b35ae857879,6687f18ebc24064cf023faaa1c9a6b766cdb9396..908f9c34fa5ac6a0cae7617b5243d4b5bd69cf69
@@@ -694,14 -677,44 +672,6 @@@ void Damage (entity targ, entity inflic
                        }
                }
  
--              if(targ.classname == "player")
-               if(attacker.classname == "player")
-               if(attacker != targ)
 -              if (g_minstagib)
--              {
-                       targ.lms_traveled_distance = autocvar_g_lms_campcheck_distance;
-                       attacker.lms_traveled_distance = autocvar_g_lms_campcheck_distance;
 -                      if ((deathtype == DEATH_FALL)  ||
 -                              (deathtype == DEATH_DROWN) ||
 -                              (deathtype == DEATH_SLIME) ||
 -                              (deathtype == DEATH_LAVA)  ||
 -                              (!DEATH_ISWEAPON(deathtype, WEP_LASER) && damage > 0 && damage < 100))
 -                      {
 -                              self = oldself;
 -                              return;
 -                      }
 -                      if(damage > 0)
 -                          damage = 10000;
 -                      if (targ.armorvalue && (deathtype == WEP_MINSTANEX) && damage)
 -                      {
 -                              targ.armorvalue -= 1;
 -                              centerprint(targ, strcat("^3Remaining extra lives: ",ftos(targ.armorvalue)));
 -                              damage = 0;
 -                              targ.hitsound += 1;
 -                              attacker.hitsound += 1; // TODO change this to a future specific hitsound for armor hit
 -                      }
 -                      if (DEATH_ISWEAPON(deathtype, WEP_LASER))
 -                      {
 -                              damage = 0;
 -                              mirrordamage = 0;
 -                              complainteamdamage = 0;
 -                              if (targ != attacker)
 -                              {
 -                                      if ((targ.health >= 1) && (targ.classname == "player"))
 -                                              centerprint(attacker, "Secondary fire inflicts no damage!");
 -                                      force = '0 0 0';
 -                                      // keep mirrorforce
 -                                      attacker = targ;
 -                              }
 -                      }
--              }
--
                if not(DEATH_ISSPECIAL(deathtype))
                {
                        damage *= g_weapondamagefactor;
Simple merge
index ffaccfbcdcae1103832a265d480ac84b936eea69,13eb647dbdeb36d83aeebb371d88a44e4bcef1f4..8ad4520494ac6184b25f90501ba5291999231a5a
@@@ -827,9 -827,24 +827,9 @@@ void readplayerstartcvars(
                g_pinata = 0; // incompatible
                g_weapon_stay = 0; // incompatible
                WEPSET_COPY_AA(start_weapons, g_weaponarena_weapons);
-               if(!(g_lms || g_ca))
+               if(!g_ca)
                        start_items |= IT_UNLIMITED_AMMO;
        }
 -      else if (g_minstagib)
 -      {
 -              g_pinata = 0; // incompatible
 -              g_weapon_stay = 0; // incompatible
 -              g_bloodloss = 0; // incompatible
 -              start_health = 100;
 -              start_armorvalue = 0;
 -              WEPSET_COPY_AW(start_weapons, WEP_MINSTANEX);
 -              g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
 -              start_items |= IT_UNLIMITED_SUPERWEAPONS;
 -
 -              if (g_minstagib_invis_alpha <= 0)
 -                      g_minstagib_invis_alpha = -1;
 -      }
        else
        {
                for (i = WEP_FIRST; i <= WEP_LAST; ++i)
@@@ -992,21 -1008,23 +986,23 @@@ void readlevelcvars(void
                MUTATOR_ADD(mutator_spawn_near_teammate);
        if(cvar("g_physical_items"))
                MUTATOR_ADD(mutator_physical_items);
 -      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);
 -      }
+       if(cvar("g_touchexplode"))
+               MUTATOR_ADD(mutator_touchexplode);
 +      if(cvar("g_minstagib"))
 +              MUTATOR_ADD(mutator_minstagib);
 +      if(cvar("g_invincible_projectiles"))
 +              MUTATOR_ADD(mutator_invincibleprojectiles);
 +      if(cvar("g_new_toys"))
 +              MUTATOR_ADD(mutator_new_toys);
 +      if(!cvar("g_minstagib")) // TODO: nix support?
 +      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"))
      g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
      g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
      g_bugrigs_steer = cvar("g_bugrigs_steer");
 +      
 +      g_minstagib = cvar("g_minstagib");
  
-     g_touchexplode = cvar("g_touchexplode");
-     g_touchexplode_radius = cvar("g_touchexplode_radius");
-     g_touchexplode_damage = cvar("g_touchexplode_damage");
-     g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
-     g_touchexplode_force = cvar("g_touchexplode_force");
        sv_clones = cvar("sv_clones");
        sv_foginterval = cvar("sv_foginterval");
        g_cloaked = cvar("g_cloaked");
Simple merge
index 9f2aa0364250e9fba18583c51bcbf841926f4cd2,0000000000000000000000000000000000000000..efeec3decd04945f19c25486ba2560b8d79203b2
mode 100644,000000..100644
--- /dev/null
@@@ -1,421 -1,0 +1,421 @@@
-               sprint(other, "^3You picked up some extra lives\n");
 +void spawnfunc_item_minst_cells (void) 
 +{
 +      if not(g_minstagib) { remove(self); return; }
 +      if not(self.ammo_cells)
 +              self.ammo_cells = autocvar_g_minstagib_ammo_drop;
 +              
 +      StartItem ("models/items/a_cells.md3",
 +                         "misc/itempickup.wav", 45, 0,
 +                         "MinstaNex Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100);
 +}
 +
 +void minstagib_health_mega()
 +{
 +      self.max_health = 1;
 +      StartItem ("models/items/g_h100.md3",
 +                         "misc/megahealth.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup,
 +                         "Extralife", IT_NAILS, 0, FL_POWERUP, generic_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
 +}
 +
 +.float minstagib_nextthink;
 +.float minstagib_needammo;
 +void minstagib_stop_countdown(entity e)
 +{
 +      if (!e.minstagib_needammo)
 +              return;
 +      Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_MINSTA_FINDAMMO);
 +      e.minstagib_needammo = FALSE;
 +}
 +void minstagib_ammocheck(void)
 +{
 +      if not(IS_PLAYER(self))
 +              return; // not a player
 +      if (time < self.minstagib_nextthink)
 +              return;
 +
 +      if (self.deadflag || gameover)
 +              minstagib_stop_countdown(self);
 +      else if (self.ammo_cells > 0 || (self.items & IT_UNLIMITED_WEAPON_AMMO))
 +              minstagib_stop_countdown(self);
 +      else
 +      {
 +              self.minstagib_needammo = TRUE;
 +              if (self.health == 5)
 +              {
 +                      Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_MINSTAGIB_TERMINATED);
 +              }
 +              else if (self.health == 10)
 +              {
 +                      Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_1);
 +              }
 +              else if (self.health == 20)
 +              {
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_2);
 +              }
 +              else if (self.health == 30)
 +              {
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_3);
 +              }
 +              else if (self.health == 40)
 +              {
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_4);
 +              }
 +              else if (self.health == 50)
 +              {
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_5);
 +              }
 +              else if (self.health == 60)
 +              {
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_6);
 +              }
 +              else if (self.health == 70)
 +              {
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_7);
 +              }
 +              else if (self.health == 80)
 +              {
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_8);
 +              }
 +              else if (self.health == 90)
 +              {
 +                      Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MINSTA_FINDAMMO);
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_9);
 +              }
 +              else if (self.health == 100)
 +              {
 +                      Send_Notification(NOTIF_ONE_ONLY, self, MSG_MULTI, MULTI_MINSTA_FINDAMMO);
 +                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 +              }
 +      }
 +      self.minstagib_nextthink = time + 1;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_MatchEnd)
 +{
 +      entity head;
 +      FOR_EACH_PLAYER(head)
 +              minstagib_stop_countdown(head);
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_BotShouldAttack)
 +{
 +      if(checkentity.items & IT_STRENGTH)
 +              return TRUE;
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_MakePlayerObserver)
 +{
 +      minstagib_stop_countdown(self);
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_PlayerSpawn)
 +{
 +      self.effects |= EF_FULLBRIGHT;
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_PlayerPreThink)
 +{
 +      minstagib_ammocheck();
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_PlayerPowerups)
 +{
 +      if not(self.effects & EF_FULLBRIGHT)
 +              self.effects |= EF_FULLBRIGHT;
 +
 +      if (self.items & IT_STRENGTH)
 +      {
 +              play_countdown(self.strength_finished, "misc/poweroff.wav");
 +              if (time > self.strength_finished)
 +              {
 +                      self.alpha = default_player_alpha;
 +                      self.exteriorweaponentity.alpha = default_weapon_alpha;
 +                      self.items &~= IT_STRENGTH;
 +                      Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
 +              }
 +      }
 +      else
 +      {
 +              if (time < self.strength_finished)
 +              {
 +                      self.alpha = autocvar_g_minstagib_invis_alpha;
 +                      self.exteriorweaponentity.alpha = autocvar_g_minstagib_invis_alpha;
 +                      self.items |= IT_STRENGTH;
 +                      Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
 +                      Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
 +              }
 +      }
 +
 +      if (self.items & IT_INVINCIBLE)
 +      {
 +              play_countdown(self.invincible_finished, "misc/poweroff.wav");
 +              if (time > self.invincible_finished)
 +              {
 +                      self.items &~= IT_INVINCIBLE;
 +                      Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
 +              }
 +      }
 +      else
 +      {
 +              if (time < self.invincible_finished)
 +              {
 +                      self.items |= IT_INVINCIBLE;
 +                      Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
 +                      Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
 +              }
 +      }
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_PlayerPhysics)
 +{
 +      if(self.items & IT_INVINCIBLE)
 +              self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_minstagib_speed_highspeed;
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_SplitHealthArmor)
 +{
 +      damage_save = 0;
 +      //damage_take = frag_damage; // frag_damage isn't even set here?!
 +      
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_ForbidThrowing)
 +{
 +      if (self.health < 1)
 +              return FALSE;
 +              
 +      return TRUE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_PlayerDamage)
 +{
 +      if(autocvar_g_friendlyfire == 0 && !IsDifferentTeam(frag_target, frag_attacker) && IS_PLAYER(frag_target))
 +              frag_damage = 0;
 +              
 +      if(IS_PLAYER(frag_target))
 +      {
 +              if ((frag_deathtype == DEATH_FALL)  ||
 +                      (frag_deathtype == DEATH_DROWN) ||
 +                      (frag_deathtype == DEATH_SLIME) ||
 +                      (frag_deathtype == DEATH_LAVA))
 +              {
 +                      frag_damage = 0;
 +              }
 +              
 +              if (frag_target.armorvalue && (frag_deathtype == WEP_MINSTANEX) && frag_damage)
 +              {
 +                      frag_target.armorvalue -= 1;
 +                      Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_MINSTA_LIVES_REMAINING, frag_target.armorvalue);
 +                      frag_damage = 0;
 +                      frag_target.hitsound += 1;
 +                      frag_attacker.hitsound += 1; // TODO change this to a future specific hitsound for armor hit
 +              }
 +              if (DEATH_ISWEAPON(frag_deathtype, WEP_LASER))
 +              {
 +                      frag_damage = 0;
 +                      frag_mirrordamage = 0;
 +                      if (frag_target != frag_attacker)
 +                      {
 +                              if ((frag_target.health >= 1) && IS_PLAYER(frag_target))
 +                                      Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_MINSTA_SECONDARY);
 +                              frag_force = '0 0 0';
 +                              // keep mirrorfrag_force
 +                              frag_attacker = frag_target;
 +                      }
 +              }
 +      }
 +      
 +      if(frag_mirrordamage > 0)
 +      {
 +              // just lose extra LIVES, don't kill the player for mirror damage
 +              if(frag_attacker.armorvalue > 0)
 +              {
 +                      frag_attacker.armorvalue = frag_attacker.armorvalue - 1;
 +                      Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_MINSTA_LIVES_REMAINING, frag_attacker.armorvalue);
 +                      frag_attacker.hitsound += 1;
 +              }
 +              frag_mirrordamage = 0;
 +      }
 +      
 +      if(frag_target.items & IT_STRENGTH)
 +              yoda = 1;
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_SetStartItems)
 +{
 +      start_ammo_cells = cvar("g_minstagib_ammo_start");
 +      
 +      start_health = 100;
 +      start_armorvalue = 0;
 +      WEPSET_COPY_AW(start_weapons, WEP_MINSTANEX);
 +      start_items |= IT_UNLIMITED_SUPERWEAPONS;
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_FilterItem)
 +{
 +      if(self.classname == "item_cells")
 +              return TRUE; // no normal cells?
 +              
 +      if(self.weapon == WEP_MINSTANEX && self.classname == "droppedweapon")
 +      {
 +              self.ammo_cells = autocvar_g_minstagib_ammo_drop;
 +              return FALSE;
 +      }
 +      
 +      if(self.weapon == WEP_ROCKET_LAUNCHER || self.weapon == WEP_NEX)
 +      {
 +              entity e = spawn();
 +              setorigin(e, self.origin);
 +              entity oldself;
 +              oldself = self;
 +              self = e;
 +              spawnfunc_item_minst_cells();
 +              self = oldself;
 +              return TRUE;
 +      }
 +              
 +      if(self.flags & FL_POWERUP)
 +              return FALSE;
 +              
 +      if(self.ammo_cells > autocvar_g_minstagib_ammo_drop && self.classname != "item_minst_cells")
 +              self.ammo_cells = autocvar_g_minstagib_ammo_drop;
 +              
 +      if(self.ammo_cells && !self.weapon)
 +              return FALSE;
 +              
 +      return TRUE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_CustomizeWaypoint)
 +{
 +      entity e = WaypointSprite_getviewentity(other);
 +      
 +      // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
 +      // but only apply this to real players, not to spectators
 +      if((self.owner.flags & FL_CLIENT) && (self.owner.items & IT_STRENGTH) && (e == other))
 +      if(IsDifferentTeam(self.owner, e))
 +              return TRUE;
 +      
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_ItemCountdown)
 +{
 +      switch(self.items)
 +      {
 +              case IT_STRENGTH:   item_name = "item-invis"; item_color = '0 0 1'; break;
 +              case IT_NAILS:      item_name = "item-extralife"; item_color = '1 0 0'; break;
 +              case IT_INVINCIBLE: item_name = "item-speed"; item_color = '1 0 1'; break;
 +      }
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_ItemTouch)
 +{
 +      if(self.ammo_cells)
 +      {
 +              // play some cool sounds ;)
 +              if (IS_CLIENT(other))
 +              {
 +                      if(other.health <= 5)
 +                              Send_Notification(NOTIF_ONE, other, MSG_ANNCE, ANNCE_MINSTAGIB_LASTSECOND);
 +                      else if(other.health < 50)
 +                              Send_Notification(NOTIF_ONE, other, MSG_ANNCE, ANNCE_MINSTAGIB_NARROWLY);
 +              }
 +
 +              if(other.health < 100)
 +                      other.health = 100;
 +      }
 +      
 +      if(self.max_health)
 +      {
 +              other.armorvalue = bound(other.armorvalue, 999, other.armorvalue + autocvar_g_minstagib_extralives);
++              Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_EXTRALIVES);
 +      }
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_OnEntityPreSpawn)
 +{
 +      if not(autocvar_g_powerups) { return FALSE; }
 +      if not(self.classname == "item_strength" || self.classname == "item_invincible" || self.classname == "item_health_mega")
 +              return FALSE;
 +      
 +      entity e = spawn();
 +      
 +      if(random() < 0.3)
 +              e.think = spawnfunc_item_strength;
 +      else if(random() < 0.6)
 +              e.think = minstagib_health_mega;
 +      else
 +              e.think = spawnfunc_item_invincible;
 +              
 +      e.nextthink = time + 0.1;
 +      e.spawnflags = self.spawnflags;
 +      e.noalign = self.noalign;
 +      setorigin(e, self.origin);
 +      
 +      return TRUE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_BuildMutatorsString)
 +{
 +      ret_string = strcat(ret_string, ":MinstaGib");
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(minstagib_BuildMutatorsPrettyString)
 +{
 +      ret_string = strcat(ret_string, ", MinstaGib");
 +      return FALSE;
 +}
 +
 +MUTATOR_DEFINITION(mutator_minstagib)
 +{
 +      MUTATOR_HOOK(MatchEnd, minstagib_MatchEnd, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(BotShouldAttack, minstagib_BotShouldAttack, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerPhysics, minstagib_PlayerPhysics, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerSpawn, minstagib_PlayerSpawn, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerDamage_Calculate, minstagib_PlayerDamage, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(MakePlayerObserver, minstagib_MakePlayerObserver, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(SetStartItems, minstagib_SetStartItems, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(ItemTouch, minstagib_ItemTouch, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(FilterItem, minstagib_FilterItem, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(CustomizeWaypoint, minstagib_CustomizeWaypoint, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(Item_RespawnCountdown, minstagib_ItemCountdown, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, minstagib_SplitHealthArmor, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerPowerups, minstagib_PlayerPowerups, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(ForbidThrowCurrentWeapon, minstagib_ForbidThrowing, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerPreThink, minstagib_PlayerPreThink, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(OnEntityPreSpawn, minstagib_OnEntityPreSpawn, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(BuildMutatorsString, minstagib_BuildMutatorsString, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(BuildMutatorsPrettyString, minstagib_BuildMutatorsPrettyString, CBC_ORDER_ANY);
 +
 +      return FALSE;
 +}
index 14815206dea742c441cc16cf98d1fc6067f4e6c7,dab42bd65d8c39287701a4c3cffb3daf808f9609..3f9f020affc086c1968fbe80a2bfc64bd9a3d5e3
@@@ -15,6 -19,6 +19,7 @@@ 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(sandbox);
index 3664b6be545b9600fd0dbb761869a2e90ae7dfbc,b3cc22ddaa7a785c9a44472025a74e1b0cde3cb3..957710c3f86edcb4369691d478f0fa79785e6791
@@@ -231,7 -242,7 +242,8 @@@ 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
  
  ../warpzonelib/anglestransform.qc
  ../warpzonelib/mathlib.qc
index b7c3c56eb93fc9a9aef32d82adc04b00c02a2114,40abd18b135fe920265d197357927a458308f990..3471ce1b046fd54dc00a8b12dad110e22115360c
@@@ -600,60 -610,127 +596,60 @@@ float Item_GiveTo(entity item, entity p
        // if nothing happens to player, just return without taking the item
        pickedup = FALSE;
        _switchweapon = FALSE;
 +      // in case the player has autoswitch enabled do the following:
 +      // if the player is using their best weapon before items are given, they
 +      // probably want to switch to an even better weapon after items are given
 +      if (player.autoswitch)
 +      if (player.switchweapon == w_getbestweapon(player))
 +              _switchweapon = TRUE;
  
 -      if (g_minstagib)
 -      {
 -              float prevcells = player.ammo_cells;
 -
 -              pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
 -              pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, 999, ITEM_MODE_NONE);
 -
 -              if(player.ammo_cells > prevcells)
 -              {
 -                      _switchweapon = TRUE;
 -
 -                      // play some cool sounds ;)
 -                      if (clienttype(player) == CLIENTTYPE_REAL)
 -                      {
 -                              if(player.health <= 5)
 -                                      Send_Notification(NOTIF_ONE, player, MSG_ANNCE, ANNCE_MINSTAGIB_LASTSECOND);
 -                              else if(player.health < 50)
 -                                      Send_Notification(NOTIF_ONE, player, MSG_ANNCE, ANNCE_MINSTAGIB_NARROWLY);
 -                      }
 -                      // sound not available
 -                      // else if(item.items == IT_CELLS)
 -                      //      AnnounceTo(player, "ammo");
 +      if not(WEPSET_CONTAINS_EW(player, player.switchweapon))
 +              _switchweapon = TRUE;
  
 -                      if (WEPSET_CONTAINS_EW(item, WEP_MINSTANEX))
 -                              W_GiveWeapon (player, WEP_MINSTANEX);
 -                      player.health = 100;
 -              }
 +      pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
 +      pickedup |= Item_GiveAmmoTo(item, player, ammo_shells, g_pickup_shells_max, ITEM_MODE_NONE);
 +      pickedup |= Item_GiveAmmoTo(item, player, ammo_nails, g_pickup_nails_max, ITEM_MODE_NONE);
 +      pickedup |= Item_GiveAmmoTo(item, player, ammo_rockets, g_pickup_rockets_max, ITEM_MODE_NONE);
 +      pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, g_pickup_cells_max, ITEM_MODE_NONE);
 +      pickedup |= Item_GiveAmmoTo(item, player, health, item.max_health, ITEM_MODE_HEALTH);
 +      pickedup |= Item_GiveAmmoTo(item, player, armorvalue, item.max_armorvalue, ITEM_MODE_ARMOR);
  
 -              if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
 -              {
 -                      pickedup = TRUE;
 -                      player.items |= it;
 -                      sprint (player, strcat("You got the ^2", item.netname, "\n"));
 -              }
 +      if (item.flags & FL_WEAPON)
 +      {
 +              WEPSET_DECLARE_A(it);
 +              WEPSET_COPY_AE(it, item);
 +              WEPSET_ANDNOT_AE(it, player);
  
-               if (!WEPSET_EMPTY_A(it) || (item.spawnshieldtime && self.pickup_anyway))
 -              // extralife powerup
 -              if (item.max_health)
++              if (!WEPSET_EMPTY_A(it) || (item.spawnshieldtime && item.pickup_anyway))
                {
-               pickedup = TRUE;
-               for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+                       pickedup = TRUE;
 -                      // sound not available
 -                      // AnnounceTo(player, "_lives");
 -                      player.armorvalue = bound(player.armorvalue, 999, player.armorvalue + autocvar_g_minstagib_extralives);
 -                      Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_EXTRALIVES);
++                      for(i = WEP_FIRST; i <= WEP_LAST; ++i)
 +                      if(WEPSET_CONTAINS_AW(it, i))
-                       W_GiveWeapon(player, i);
++                              W_GiveWeapon(player, i);
                }
 +      }
  
 -              // invis powerup
 -              if (item.strength_finished)
 -              {
 -                      pickedup = TRUE;
 -                      // sound not available
 -                      // AnnounceTo(player, "invisible");
 -                      player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time;
 -              }
 +      if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
 +      {
 +              pickedup = TRUE;
 +              player.items |= it;
 +              sprint (player, strcat("You got the ^2", item.netname, "\n"));
 +      }
  
 -              // speed powerup
 -              if (item.invincible_finished)
 -              {
 -                      pickedup = TRUE;
 -                      // sound not available
 -                      // AnnounceTo(player, "speed");
 -                      player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_invincible_time;
 -              }
 +      if (item.strength_finished)
 +      {
 +              pickedup = TRUE;
 +              player.strength_finished = max(player.strength_finished, time) + item.strength_finished;
        }
 -      else
 +      if (item.invincible_finished)
        {
 -              // in case the player has autoswitch enabled do the following:
 -              // if the player is using their best weapon before items are given, they
 -              // probably want to switch to an even better weapon after items are given
 -              if (player.autoswitch)
 -              if (player.switchweapon == w_getbestweapon(player))
 -                      _switchweapon = TRUE;
 -
 -              if not(WEPSET_CONTAINS_EW(player, player.switchweapon))
 -                      _switchweapon = TRUE;
 -
 -              pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
 -              pickedup |= Item_GiveAmmoTo(item, player, ammo_shells, g_pickup_shells_max, ITEM_MODE_NONE);
 -              pickedup |= Item_GiveAmmoTo(item, player, ammo_nails, g_pickup_nails_max, ITEM_MODE_NONE);
 -              pickedup |= Item_GiveAmmoTo(item, player, ammo_rockets, g_pickup_rockets_max, ITEM_MODE_NONE);
 -              pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, g_pickup_cells_max, ITEM_MODE_NONE);
 -              pickedup |= Item_GiveAmmoTo(item, player, health, item.max_health, ITEM_MODE_HEALTH);
 -              pickedup |= Item_GiveAmmoTo(item, player, armorvalue, item.max_armorvalue, ITEM_MODE_ARMOR);
 -
 -              if (item.flags & FL_WEAPON)
 -              {
 -                      WEPSET_DECLARE_A(it);
 -                      WEPSET_COPY_AE(it, item);
 -                      WEPSET_ANDNOT_AE(it, player);
 -
 -                      if (!WEPSET_EMPTY_A(it) || (item.spawnshieldtime && self.pickup_anyway))
 -                      {
 -                              pickedup = TRUE;
 -                              for(i = WEP_FIRST; i <= WEP_LAST; ++i)
 -                                      if(WEPSET_CONTAINS_AW(it, i))
 -                                              W_GiveWeapon(player, i);
 -                      }
 -              }
 -
 -              if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
 -              {
 -                      pickedup = TRUE;
 -                      player.items |= it;
 -                      sprint (player, strcat("You got the ^2", item.netname, "\n"));
 -              }
 -
 -              if (item.strength_finished)
 -              {
 -                      pickedup = TRUE;
 -                      player.strength_finished = max(player.strength_finished, time) + item.strength_finished;
 -              }
 -              if (item.invincible_finished)
 -              {
 -                      pickedup = TRUE;
 -                      player.invincible_finished = max(player.invincible_finished, time) + item.invincible_finished;
 -              }
 -              if (item.superweapons_finished)
 -              {
 -                      pickedup = TRUE;
 -                      player.superweapons_finished = max(player.superweapons_finished, time) + item.superweapons_finished;
 -              }
 +              pickedup = TRUE;
 +              player.invincible_finished = max(player.invincible_finished, time) + item.invincible_finished;
 +      }
 +      if (item.superweapons_finished)
 +      {
 +              pickedup = TRUE;
 +              player.superweapons_finished = max(player.superweapons_finished, time) + item.superweapons_finished;
        }
  
  :skip
Simple merge
index 45deff17bc20c5b8d7cc1d2fa316e336a04c8086,611319a16cd94f4794e5606ed55fb35205f4a54b..2ad71ce798667a92a5fa6d63e0f0b6fc8adca963
@@@ -31,40 -39,129 +31,41 @@@ void W_MinstaNex_Attack (void
        // teamcolor / hit beam effect
        vector v;
        v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
--      if(teamplay)
 -      {
 -          switch(self.team)
 -          {
 -            case NUM_TEAM_1:   // Red
 -                if(damage_goodhits)
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v);
 -                else
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v);
 -                break;
 -            case NUM_TEAM_2:   // Blue
 -                if(damage_goodhits)
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v);
 -                else
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v);
 -                break;
 -            case NUM_TEAM_3:   // Yellow
 -                if(damage_goodhits)
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v);
 -                else
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v);
 -                break;
 -            case NUM_TEAM_4:   // Pink
 -                if(damage_goodhits)
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v);
 -                else
 -                    WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v);
 -                break;
 -          }
 -      }
 -      else
 -        WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v);
 -
 -      if (g_minstagib)
 -              W_DecreaseAmmo(ammo_cells, 1, autocvar_g_balance_minstanex_reload_ammo);
 -      else
 -              W_DecreaseAmmo(ammo_cells, autocvar_g_balance_minstanex_ammo, autocvar_g_balance_minstanex_reload_ammo);
 -}
 -
 -
 -.float minstagib_nextthink;
 -.float minstagib_needammo;
 -void minstagib_stop_countdown(entity e)
 -{
 -      if (!e.minstagib_needammo)
 -              return;
 -      Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_MINSTA_FINDAMMO);
 -      e.minstagib_needammo = FALSE;
 -}
 -void minstagib_ammocheck(void)
 -{
 -      if (time < self.minstagib_nextthink)
 -              return;
 -
 -      if (self.deadflag || gameover || (self.flags & FL_GODMODE))
 -              minstagib_stop_countdown(self);
 -      else if (self.ammo_cells > 0 || (self.items & IT_UNLIMITED_WEAPON_AMMO))
++      switch(self.team)
        {
-           switch(self.team)
-           {
-             case NUM_TEAM_1:   // Red
-                 if(damage_goodhits)
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v);
-                 else
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v);
-                 break;
-             case NUM_TEAM_2:   // Blue
-                 if(damage_goodhits)
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v);
-                 else
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v);
-                 break;
-             case NUM_TEAM_3:   // Yellow
-                 if(damage_goodhits)
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v);
-                 else
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v);
-                 break;
-             case NUM_TEAM_4:   // Pink
-                 if(damage_goodhits)
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v);
-                 else
-                     WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v);
-                 break;
-           }
 -              if (self.minstagib_needammo)
 -                      self.health = 100;
 -              minstagib_stop_countdown(self);
 -      }
 -      else
 -      {
 -              self.minstagib_needammo = TRUE;
 -              if (self.health == 5)
 -              {
 -                      Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_MINSTAGIB_TERMINATED);
 -              }
 -              else if (self.health == 10)
 -              {
 -                      Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_1);
 -              }
 -              else if (self.health == 20)
 -              {
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_2);
 -              }
 -              else if (self.health == 30)
 -              {
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_3);
 -              }
 -              else if (self.health == 40)
 -              {
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_4);
 -              }
 -              else if (self.health == 50)
 -              {
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_5);
 -              }
 -              else if (self.health == 60)
 -              {
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_6);
 -              }
 -              else if (self.health == 70)
 -              {
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_7);
 -              }
 -              else if (self.health == 80)
 -              {
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_8);
 -              }
 -              else if (self.health == 90)
 -              {
 -                      Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MINSTA_FINDAMMO);
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -                      Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_9);
 -              }
 -              else if (self.health == 100)
 -              {
 -                      Send_Notification(NOTIF_ONE_ONLY, self, MSG_MULTI, MULTI_MINSTA_FINDAMMO);
 -                      Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
 -              }
++              case NUM_TEAM_1:   // Red
++                      if(damage_goodhits)
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v);
++                      else
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v);
++                      break;
++              case NUM_TEAM_2:   // Blue
++                      if(damage_goodhits)
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v);
++                      else
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v);
++                      break;
++              case NUM_TEAM_3:   // Yellow
++                      if(damage_goodhits)
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v);
++                      else
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v);
++                      break;
++              case NUM_TEAM_4:   // Pink
++                      if(damage_goodhits)
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v);
++                      else
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v);
++                      break;
++              default:
++                      if(damage_goodhits)
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3_HIT"), w_shotorg, v);
++                      else
++                              WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v);
++                      break;
        }
-       else
-               WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v);
 -      self.minstagib_nextthink = time + 1;
 +      
 +      W_DecreaseAmmo(ammo_cells, ((g_minstagib) ? 1 : autocvar_g_balance_minstanex_ammo), autocvar_g_balance_minstanex_reload_ammo);
  }
  
  void spawnfunc_weapon_minstanex (void); // defined in t_items.qc