Merge branch 'master' into Mario/nades_mutator
authorMario <mario.mario@y7mail.com>
Tue, 11 Jun 2013 04:14:56 +0000 (14:14 +1000)
committerMario <mario.mario@y7mail.com>
Tue, 11 Jun 2013 04:14:56 +0000 (14:14 +1000)
1  2 
qcsrc/client/projectile.qc
qcsrc/server/mutators/mutator_nades.qc

@@@ -101,6 -101,6 +101,18 @@@ void Projectile_Draw(
                        case PROJECTILE_GRENADE_BOUNCING:
                                rot = '0 -1000 0'; // sideways
                                break;
++                      case PROJECTILE_NADE_RED_BURN:
++                      case PROJECTILE_NADE_RED:
++                      case PROJECTILE_NADE_BLUE_BURN:
++                      case PROJECTILE_NADE_BLUE:
++                      case PROJECTILE_NADE_YELLOW_BURN:
++                      case PROJECTILE_NADE_YELLOW:
++                      case PROJECTILE_NADE_PINK_BURN:
++                      case PROJECTILE_NADE_PINK:
++                      case PROJECTILE_NADE_BURN:
++                      case PROJECTILE_NADE:
++                              rot = self.avelocity; 
++                              break;
                        case PROJECTILE_HOOKBOMB:
                                rot = '1000 0 0'; // forward
                                break;
        trailorigin = self.origin;
        switch(self.cnt)
        {
++          case PROJECTILE_NADE_RED_BURN:
++              case PROJECTILE_NADE_RED:
++              case PROJECTILE_NADE_BLUE_BURN:
++              case PROJECTILE_NADE_BLUE:
++              case PROJECTILE_NADE_YELLOW_BURN:
++              case PROJECTILE_NADE_YELLOW:
++              case PROJECTILE_NADE_PINK_BURN:
++              case PROJECTILE_NADE_PINK:
++              case PROJECTILE_NADE_BURN:
++              case PROJECTILE_NADE:
++                      trailorigin += v_up * 4;
++                      break;
                case PROJECTILE_GRENADE:
                case PROJECTILE_GRENADE_BOUNCING:
                        trailorigin += v_right * 1 + v_forward * -10;
@@@ -353,23 -342,6 +377,23 @@@ void Ent_Projectile(
                                self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor;
                                self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop;
                                break;
-                               self.mins = '-3 -3 -3';
-                               self.maxs = '3 3 3';
 +                      case PROJECTILE_NADE_RED_BURN:
 +                      case PROJECTILE_NADE_RED:
 +                      case PROJECTILE_NADE_BLUE_BURN:
 +                      case PROJECTILE_NADE_BLUE:
 +                      case PROJECTILE_NADE_YELLOW_BURN:
 +                      case PROJECTILE_NADE_YELLOW:
 +                      case PROJECTILE_NADE_PINK_BURN:
 +                      case PROJECTILE_NADE_PINK:
 +                      case PROJECTILE_NADE_BURN:
 +                      case PROJECTILE_NADE:
++                              self.mins = '-16 -16 -16';
++                              self.maxs = '16 16 16';
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              self.scale = 1.5;
 +                              self.avelocity = randomvec() * 720;
 +                              break;
                        case PROJECTILE_MINE:
                                self.mins = '-4 -4 -4';
                                self.maxs = '4 4 4';
@@@ -488,6 -460,6 +512,8 @@@ void Projectile_Precache(
        precache_model("models/rocket.md3");
        precache_model("models/tagrocket.md3");
        precache_model("models/tracer.mdl");
++      
++      precache_model("models/weapons/v_ok_grenade.md3");
  
        precache_sound("weapons/electro_fly.wav");
        precache_sound("weapons/rocket_fly.wav");
index 36a5cab,0000000..4466ccf
mode 100644,000000..100644
--- /dev/null
@@@ -1,392 -1,0 +1,405 @@@
-       setsize(self, '-2 -2 -2', '2 2 2');
-       UpdateCSQCProjectile(self);
 +.entity nade;
 +.entity fake_nade;
 +.float nade_refire;
 +
 +void nade_timer_think()
 +{
 +      self.skin = 8 - (self.owner.wait - time) / (autocvar_g_nades_nade_lifetime / 10);
 +      self.nextthink = time;
 +      if(!self.owner || wasfreed(self.owner))
 +              remove(self);
 +      
 +}
 +
 +void nade_burn_spawn(entity _nade)
 +{
 +      float p;
 +      
 +      switch(_nade.realowner.team)
 +      {
 +              case NUM_TEAM_1: p = PROJECTILE_NADE_RED_BURN; break;
 +              case NUM_TEAM_2: p = PROJECTILE_NADE_BLUE_BURN; break;
 +              case NUM_TEAM_3: p = PROJECTILE_NADE_YELLOW_BURN; break;
 +              case NUM_TEAM_4: p = PROJECTILE_NADE_PINK_BURN; break;
 +              default:                 p = PROJECTILE_NADE_BURN; break;
 +      }
 +      
 +      CSQCProjectile(_nade, TRUE, p, TRUE);
 +}
 +
 +void nade_spawn(entity _nade)
 +{
 +      float p;
 +      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 = nade_timer_think;
 +      timer.nextthink = time;
 +      timer.wait = _nade.wait;
 +      timer.owner = _nade;    
 +      timer.skin = 10;
 +      
 +      switch(_nade.realowner.team)
 +      {
 +              case NUM_TEAM_1: p = PROJECTILE_NADE_RED; break;
 +              case NUM_TEAM_2: p = PROJECTILE_NADE_BLUE; break;
 +              case NUM_TEAM_3: p = PROJECTILE_NADE_YELLOW; break;
 +              case NUM_TEAM_4: p = PROJECTILE_NADE_PINK; break;
 +              default:                 p = PROJECTILE_NADE; break;
 +      }
 +      
 +      CSQCProjectile(_nade, TRUE, p, TRUE);
 +      
 +}
 +
 +void nade_boom() // TODO: DamageInfo
 +{
 +      string expef;
 +      
 +      switch(self.realowner.team)
 +      {
 +              case NUM_TEAM_1: expef = "nade_red_explode"; break;
 +              case NUM_TEAM_2: expef = "nade_blue_explode"; break;
 +              case NUM_TEAM_3: expef = "nade_yellow_explode"; break;
 +              case NUM_TEAM_4: expef = "nade_pink_explode"; break;
 +              default:                 expef = "nade_explode"; break;
 +      }
 +      
 +      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(expef), self.origin + '0 0 1', '0 0 0', 1);
 +
 +      self.takedamage = DAMAGE_NO;
 +      RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
 +                               autocvar_g_nades_nade_radius, self, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
 +
 +      remove(self);
 +}
 +
 +void nade_touch()
 +{
 +      PROJECTILE_TOUCH;
-       setorigin(_nade, CENTER_OR_VIEWOFS(e) + (v_right * 10) * -1);
++      //setsize(self, '-2 -2 -2', '2 2 2');
++      //UpdateCSQCProjectile(self);
 +      if(self.health == autocvar_g_nades_nade_health)
 +      {
 +              spamsound(self, CH_SHOTS, strcat("weapons/grenade_bounce", ftos(1 + rint(random() * 5)), ".wav"), VOL_BASE, ATTN_NORM);
 +              return;
 +      }
 +
 +      self.enemy = other;
 +      nade_boom();
 +}
 +
 +void nade_beep()
 +{
 +      sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.ogg", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX));
 +      self.think = nade_boom;
 +      self.nextthink = max(self.wait, time);
 +}
 +
 +void nade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 +{
 +      if(DEATH_ISWEAPON(deathtype, WEP_LASER))
 +              return;
 +
 +      if(DEATH_ISWEAPON(deathtype, WEP_NEX) || DEATH_ISWEAPON(deathtype, WEP_MINSTANEX))
 +      {
 +              force *= 6;
 +              damage = autocvar_g_nades_nade_health * 0.55;
 +      }
 +
 +      if(DEATH_ISWEAPON(deathtype, WEP_UZI))
 +              damage = autocvar_g_nades_nade_health * 0.1;
 +
 +      if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) && !(deathtype & HITTYPE_SECONDARY))
 +              damage = autocvar_g_nades_nade_health * 1.1;
 +              
 +      if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) && (deathtype & HITTYPE_SECONDARY))
 +      {
 +              damage = autocvar_g_nades_nade_health * 0.1;
 +              force *= 15;
 +      }
 +      
 +      self.velocity += force;
 +
 +      if(!damage)
 +              return;
 +
 +      if(self.health == autocvar_g_nades_nade_health)
 +      {
 +              sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX));
 +              self.nextthink = max(time + autocvar_g_nades_nade_lifetime, time);
 +              self.think = nade_beep;
 +      }
 +
 +      self.health   -= damage;
 +      self.realowner = attacker;
 +
 +      if(self.health <= 0)
 +              W_PrepareExplosionByDamage(attacker, nade_boom);
 +      else
 +              nade_burn_spawn(self);
 +}
 +
 +void toss_nade(entity e, vector _velocity, float _time)
 +{
 +      entity _nade = e.nade;
 +      e.nade = world;
 +      
 +      remove(e.fake_nade);
 +      e.fake_nade = world;
 +      
 +      makevectors(e.v_angle);
 +      
++      W_SetupShot(e, FALSE, FALSE, "", CH_WEAPON_A, 0);
++      
 +      Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_NADES);
 +      
-               _nade.velocity = W_CalculateProjectileVelocity(e.velocity, _velocity, FALSE);
++      //setorigin(_nade, CENTER_OR_VIEWOFS(e) + (v_right * 10) * -1);
++      setorigin(_nade, w_shotorg + (v_right * 10) * -1);
 +      setmodel(_nade, "models/weapons/v_ok_grenade.md3");
 +      setattachment(_nade, world, "");
 +      PROJECTILE_MAKETRIGGER(_nade);
 +      setsize(_nade, '-16 -16 -16', '16 16 16');
 +      _nade.movetype = MOVETYPE_BOUNCE;
 +      
++      tracebox(_nade.origin, _nade.mins, _nade.maxs, _nade.origin, FALSE, _nade);
++      if (trace_startsolid)
++              setorigin(_nade, e.origin);
++      
 +      if(e.crouch)
 +              _nade.velocity = '0 0 -10';
 +      else if(autocvar_g_nades_nade_newton_style == 1)
 +              _nade.velocity = e.velocity + _velocity;
 +      else if(autocvar_g_nades_nade_newton_style == 2)
 +              _nade.velocity = _velocity;
 +      else
-       _nade.solid = SOLID_BBOX;
++              _nade.velocity = W_CalculateProjectileVelocity(e.velocity, _velocity, TRUE);
 +
-       self.nade.cnt = time;
++      //_nade.solid = SOLID_BBOX; // TODO: remember why this was needed
 +      _nade.touch = nade_touch;
 +      _nade.health = autocvar_g_nades_nade_health;
 +      _nade.takedamage = DAMAGE_AIM;
 +      _nade.event_damage = nade_damage;
 +      _nade.teleportable = TRUE;
++      _nade.pushable = TRUE;
++      _nade.gravity = 1;
++      _nade.missile_flags = MIF_SPLASH | MIF_ARC;
++      _nade.damagedbycontents = TRUE;
++      _nade.angles = vectoangles(_nade.velocity);
++      _nade.flags = FL_PROJECTILE;
 +
 +      nade_spawn(_nade);
 +
 +      if(_time)
 +      {
 +              _nade.think = nade_boom;
 +              _nade.nextthink = _time;
 +      }
 +
 +      e.nade_refire = time + autocvar_g_nades_nade_refire;
 +}
 +
 +void nade_prime()
 +{
 +      if(self.nade)
 +              remove(self.nade);
 +              
 +      if(self.fake_nade)
 +              remove(self.fake_nade);
 +      
 +      self.nade = spawn();
 +      setmodel(self.nade, "null");
 +      setattachment(self.nade, self, "bip01 l hand");
 +      self.nade.classname = "nade";
 +      self.nade.realowner = self;
 +      self.nade.colormap = self.colormap;
 +      self.nade.glowmod = self.glowmod;
 +      self.nade.wait = time + autocvar_g_nades_nade_lifetime;
-               if(time - self.nade.cnt >= 1)
++      self.nade.lifetime = time;
 +      self.nade.think = nade_beep;
 +      self.nade.nextthink = max(self.nade.wait - 3, time);
 +      self.nade.projectiledeathtype = DEATH_NADE;
 +
 +      self.fake_nade = spawn();
 +      setmodel(self.fake_nade, "models/weapons/h_ok_grenade.iqm");
 +      setattachment(self.fake_nade, self.weaponentity, "");
 +      self.fake_nade.classname = "fake_nade";
 +      //self.fake_nade.viewmodelforclient = self;
 +      self.fake_nade.realowner = self.fake_nade.owner = self;
 +      self.fake_nade.colormap = self.colormap;
 +      self.fake_nade.glowmod = self.glowmod;
 +      self.fake_nade.think = SUB_Remove;
 +      self.fake_nade.nextthink = self.nade.wait;
 +}
 +
 +float CanThrowNade()
 +{
 +      if(self.vehicle)
 +              return FALSE;
 +              
 +      if(gameover)
 +              return FALSE;
 +              
 +      if(self.deadflag != DEAD_NO)
 +              return FALSE;
 +      
 +      if not(autocvar_g_nades)
 +              return FALSE; // allow turning them off mid match
 +              
 +      if(forbidWeaponUse())
 +              return FALSE;
 +              
 +      if not(IS_PLAYER(self))
 +              return FALSE;
 +              
 +      return TRUE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_ForbidThrowing)
 +{
 +      if(!g_weaponarena || !g_minstagib)
 +              return FALSE; // TODO: fix this to support all modes that don't disable weapon dropping
 +              
 +      if(!CanThrowNade())
 +              return FALSE;
 +              
 +      if(!self.nade)
 +      {
 +              if(self.nade_refire < time)
 +              {
 +                      Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE_THROW);
 +                      nade_prime();
 +                      self.nade_refire = time + autocvar_g_nades_nade_refire;
 +              }
 +      }
 +      else
 +      {
-                       float _force = time - self.nade.cnt;
++              if(time - self.nade.lifetime >= 1)
 +              {
 +                      makevectors(self.v_angle);
-               else if(time - self.nade.cnt >= 1)
++                      float _force = time - self.nade.lifetime;
 +                      _force /= autocvar_g_nades_nade_lifetime;
 +                      _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
 +                      toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0);
 +              }
 +      }
 +      
 +      return TRUE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
 +{
 +      if(other.nade)
 +              toss_nade(other, '0 0 100', max(other.nade.wait, time + 0.05));
 +      
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
 +{
 +      float key_pressed = ((g_grappling_hook || client_hasweapon(self, WEP_HOOK, FALSE, FALSE) || WEPSET_CONTAINS_AW(weaponsInMap, WEP_HOOK)) ? self.button16 : self.BUTTON_HOOK);
 +      
 +      if(self.nade)
 +              if(self.nade.wait - 0.1 <= time)
 +                      toss_nade(self, '0 0 0', time + 0.05);
 +                      
 +      if(CanThrowNade())
 +      if(self.nade_refire < time)
 +      {
 +              if(key_pressed)
 +              {
 +                      if(!self.nade)
 +                              nade_prime();
 +              }
-                               float _force = time - self.nade.cnt;
++              else if(time - self.nade.lifetime >= 1)
 +              {
 +                      if(self.nade)
 +                      {
 +                              makevectors(self.v_angle);
++                              float _force = time - self.nade.lifetime;
 +                              _force /= autocvar_g_nades_nade_lifetime;
 +                              _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));                         
 +                              toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
 +                      }
 +              }
 +      }
 +
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_PlayerSpawn)
 +{
 +      if(autocvar_g_nades_spawn)
 +              self.nade_refire = time + autocvar_g_spawnshieldtime;
 +      else
 +              self.nade_refire  = time + autocvar_g_nades_nade_refire;
 +
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_PlayerDies)
 +{
 +      if(self.nade)
 +              toss_nade(self, '0 0 100', max(self.nade.wait, time + 0.05));
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_RemovePlayer)
 +{
 +      if(self.nade)
 +              remove(self.nade);
 +
 +      if(self.fake_nade)
 +              remove(self.fake_nade);
 +              
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_BuildMutatorsString)
 +{
 +      ret_string = strcat(ret_string, ":Nades");
 +      return FALSE;
 +}
 +
 +MUTATOR_HOOKFUNCTION(nades_BuildMutatorsPrettyString)
 +{
 +      ret_string = strcat(ret_string, ", Nades");
 +      return FALSE;
 +}
 +
 +MUTATOR_DEFINITION(mutator_nades)
 +{
 +      MUTATOR_HOOK(ForbidThrowCurrentWeapon, nades_ForbidThrowing, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(VehicleEnter, nades_VehicleEnter, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerPreThink, nades_PlayerPreThink, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerSpawn, nades_PlayerSpawn, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerDies, nades_PlayerDies, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(MakePlayerObserver, nades_RemovePlayer, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(ClientDisconnect, nades_RemovePlayer, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(BuildMutatorsString, nades_BuildMutatorsString, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(BuildMutatorsPrettyString, nades_BuildMutatorsPrettyString, CBC_ORDER_ANY);
 +      
 +      MUTATOR_ONADD
 +      {
 +              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.ogg");
 +      }
 +
 +      return FALSE;
 +}