
void () T_MissileTouch;

void () info_player_start;

void (entity targ, entity attacker) ClientObituary;

void () monster_death_use;

void(vector org) spawn_tfog;

float (entity targ, entity inflictor) CanDamage = {

   if ( (targ.movetype == MOVETYPE_PUSH) ) {

      traceline (inflictor.origin,(0.500 * (targ.absmin + targ.absmax)),TRUE,self);
      if ( (trace_fraction == TRUE) ) {

         return ( TRUE );

      }
      if ( (trace_ent == targ) ) {

         return ( TRUE );

      }
      return ( FALSE );

   }
   traceline (inflictor.origin,targ.origin,TRUE,self);
   if ( (trace_fraction == TRUE) ) {

      return ( TRUE );

   }
   traceline (inflictor.origin,(targ.origin + '15.000 15.000 0.000'),TRUE,self);
   if ( (trace_fraction == TRUE) ) {

      return ( TRUE );

   }
   traceline (inflictor.origin,(targ.origin + '-15.000 -15.000 0.000'),TRUE,self);
   if ( (trace_fraction == TRUE) ) {

      return ( TRUE );

   }
   traceline (inflictor.origin,(targ.origin + '-15.000 15.000 0.000'),TRUE,self);
   if ( (trace_fraction == TRUE) ) {

      return ( TRUE );

   }
   traceline (inflictor.origin,(targ.origin + '15.000 -15.000 0.000'),TRUE,self);
   if ( (trace_fraction == TRUE) ) {

      return ( TRUE );

   }
   return ( FALSE );

};
//dmsp2
void () execute_changelevel;
float () reporttime;
string nextmap /* = "" */;
float totalmonsterspawn /* = 0.000 */;

void (entity targ, entity attacker) Killed = {

   local entity oself;
   local entity o;
   local float n;
   local float st;
   local string nstring;
   local float rand;	//for bondo's changes to dmsp2


   oself = self;
   self = targ;
   if ( (self.health < -99.000) ) {

      self.health = -99.000;

   }
   if ( ((self.movetype == MOVETYPE_PUSH) || (self.movetype == MOVETYPE_NONE)) ) {

      self.th_die ();
      self = oself;
      return ;

   }
   self.enemy = attacker;

   if ( (self.flags & FL_MONSTER) ) {

      killed_monsters = (killed_monsters + TRUE);
      WriteByte (MSG_ALL,SVC_KILLEDMONSTER);

   }

   //dmsp2

      if ( (attacker.classname == "player") ) {

         attacker.frags = (attacker.frags + TRUE);

      }
      if ( ((total_monsters == killed_monsters) && (totalmonsterspawn < TRUE)) ) {

         st = reporttime ();
         nstring = ftos ((time - st));
         sprint (attacker,"DMSP precise time: ");
         sprint (attacker,nstring);
         sprint (attacker," seconds\n");



rand = ceil(random()*45);

if (rand == 13) nextmap = "aerowalk";
if (rand == 14) nextmap = "agnosia";
if (rand == 16) nextmap = "argonaut";
if (rand == 35) nextmap = "auhdm1";
if (rand == 27) nextmap = "axeme9";
if (rand == 18) nextmap = "baldm2";
if (rand == 30) nextmap = "barn"; //this map is buggy. ghost monsters spawn in the creek
if (rand == 19) nextmap = "basewalk";
if (rand == 29) nextmap = "bondo01";
if (rand == 2) nextmap = "bondo02";
if (rand == 1) nextmap = "bondo03";
if (rand == 23) nextmap = "bondo05";
if (rand == 15) nextmap = "bondo04";
if (rand == 37) nextmap = "bondo06";
if (rand == 17) nextmap = "bondo10";
if (rand == 8) nextmap = "bondo11";
if (rand == 4) nextmap = "bondo13";
if (rand == 32) nextmap = "bondo13a";
if (rand == 3) nextmap = "bondo14";
if (rand == 12) nextmap = "bondo15";
if (rand == 5) nextmap = "bondo16";
if (rand == 6) nextmap = "bondo17";
if (rand == 7) nextmap = "bondo18";
if (rand == 34) nextmap = "bondo18a";
if (rand == 9) nextmap = "bondo19";
if (rand == 28) nextmap = "bondo20";
if (rand == 10) nextmap = "bondo21";
if (rand == 25) nextmap = "bondo23";
if (rand == 11) nextmap = "bondo24";
if (rand == 20) nextmap = "crdm1";
if (rand == 21) nextmap = "gworld";
if (rand == 36) nextmap = "bondo30";
if (rand == 22) nextmap = "prgatory";
if (rand == 26) nextmap = "q3dm6qw";
if (rand == 31) nextmap = "triumph"; 
if (rand == 38) nextmap = "ranbase";
if (rand == 39) nextmap = "bondo07";
if (rand == 40) nextmap = "bondo08";
if (rand == 41) nextmap = "bondo09";
if (rand == 24) nextmap = "bondo12";
if (rand == 33) nextmap = "bondo31";
if (rand == 42) nextmap = "pkeg2";
if (rand == 43) nextmap = "schloss";
if (rand == 44) nextmap = "skull";
if (rand == 45) nextmap = "timeless2";

         o = spawn ();
         o.map = nextmap;
         gameover = TRUE;
         o.think = execute_changelevel;
         o.nextthink = (time + 0.100);

      }
      n = ((totalmonsterspawn + total_monsters) - killed_monsters);
      nstring = ftos (n);
      if ( (attacker.classname == "player") ) {

         if ( (n == TRUE) ) {

            sprint (attacker,"There is only one left...\n");

         } else {

            if ( (((((n == 50.000) || (n == 40.000)) || (n == SVC_INTERMISSION)) || (n == 20.000)) || ((n > TRUE) && (n < MOVETYPE_BOUNCEMISSILE))) ) {

               sprint (attacker,"There are ");
               sprint (attacker,nstring);
               sprint (attacker," more to go...\n");

            }

         }

      }



   //end dmsp2

   ClientObituary (self,attacker);
   self.takedamage = DAMAGE_NO;
   self.touch = SUB_Null;
   monster_death_use ();
   self.th_die ();
   self = oself;

};

float() crandom;

void (entity targ, entity inflictor, entity attacker, float damage) T_Damage = {

   local vector dir;
   local entity oldself;
   local float save;
   local float take;

//   if ((targ.flags & FL_GODMODE) && (skill < 4))
  //    return ;

   if ( !targ.takedamage ) {

      return ;

   }
   damage_attacker = attacker;
   if ( (attacker.super_damage_finished > time) ) {

      damage = (damage * 4);

   }

 if ((attacker.weapon != IT_SHOTGUN) || (attacker.supershotguntype != 2))
 {
   save = ceil ((targ.armortype * damage)); //save is the amount of damage to inflict on the armor.
   													  //damage is the total damage done to the target
   
   if ( (save >= targ.armorvalue) ) {

      save = targ.armorvalue; 
      targ.armortype = 0; //all armor is gone
      targ.items = (targ.items - (targ.items & ((IT_ARMOR1 | IT_ARMOR2) | IT_ARMOR3))); //remove armor flag
   }
   targ.armorvalue = (targ.armorvalue - save);
   take = ceil ((damage - save)); //take is damage to entity with armor (player)
 }
 else
 	take = damage;
 	
   if ( (targ.flags & FL_CLIENT) ) {

      targ.dmg_take = (targ.dmg_take + take);
      targ.dmg_save = (targ.dmg_save + save);
      targ.dmg_inflictor = inflictor;

   }

   if ( ((inflictor != world) && (targ.movetype == MOVETYPE_WALK)) ) {

      dir = (targ.origin - ((inflictor.absmin + inflictor.absmax) * 0.500));
      dir = normalize (dir);
                targ.velocity = (targ.velocity + ((dir * damage) * 8.0));

   }


   if ( (targ.flags & FL_GODMODE) ) {

      return ;

   }

   if ( (targ.invincible_finished >= time) ) {

      if ( (self.invincible_sound < time) ) {

         sound (targ,CHAN_ITEM,"items/protect3.wav",TRUE,ATTN_NORM);
         self.invincible_sound = (time + FL_SWIM);

      }
      return ;

   }
	
	//teamplay 1 is no friendly fire
   if (((teamplay == 1) && (targ.team > FALSE)) && (targ.team == attacker.team))
      return ;

   targ.health = (targ.health - take);

   if ( (targ.health <= FALSE) )
   {

// ZEUS 2.0 -- figure realistic velocity vectors based on damage/weapon type
	     if ((targ.flags & FL_MONSTER) || (targ.classname == "player"))
	     {
		targ.avelocity_y = 100 + random () * 600;
		if (random () < 0.5)
		  targ.avelocity_y = targ.avelocity_y * -1;

		// shotguns and lightning
		if (attacker == inflictor)
		{
		  dir = normalize (targ.origin - attacker.origin);
		  if (attacker.weapon == IT_SHOTGUN)
		  {
		    targ.velocity = dir * 10 * (random () * 25);
		    targ.velocity_z = 120;
		  }
		  else if (attacker.weapon == IT_SUPER_SHOTGUN)
		  {
		    targ.velocity = dir * 20 * (random () * 25);
		    targ.velocity_z = 200;
		  }
		  else if (attacker.weapon == IT_LIGHTNING)
		  {
		    targ.velocity_x = 18 * (random () * 20);
		    targ.velocity_y = 18 * (random () * 20);
		    targ.velocity_z = 150 + random () * 200;
		  }
		}
		// rockets and grenades
		else if ((inflictor.classname == "missile") || (inflictor.classname == "grenade") || (inflictor.classname == "devspik") || (inflictor.classname == "meat")
			|| (inflictor.classname == "dmissile") || (inflictor.classname == "hmissile") || (inflictor.classname == "man") || (inflictor.classname == "headbomb")
			|| (inflictor.classname == "proxmine") || (inflictor.classname == "rpod"))
		{
		  dir = normalize (targ.origin - inflictor.origin);
		  targ.velocity = dir * 10 * (random () * 80);
		  targ.velocity_z = 100 + (random () * 500);
		}
		else if (inflictor.classname == "plasma")
		{
		  dir = normalize (targ.origin - inflictor.origin);
		   // targ.velocity_x = 40 * (random () * 30);
		    //targ.velocity_y = 40 * (random () * 30);
		    //targ.velocity_z = 100;
		  targ.velocity = dir * 10 * (random () * 80);
		  targ.velocity_z = 150 + (random () * 100);
		   
		}
		// other projectiles
		else
		{
		  dir = normalize (targ.origin - attacker.origin);
		  if (attacker.weapon == IT_NAILGUN)
		  {
		    targ.velocity = dir * 10 * (random () * 40);
		    targ.velocity_z = 125;
		  }
		  else if (attacker.weapon == IT_SUPER_NAILGUN)
		  {
		    targ.velocity = dir * 15 * (random () * 60);
		    targ.velocity_z = 150;
		  }
		}

		// 63.8 is the size of a player/bot and is the reference for velocity
		// additions.  A player/bot always gets 1.0 * figured velocity
		// larger monsters, like the fiend and shambler get (63.8 / 126.2) * figured
		// velocity + additional
		if (targ.classname == "monster_dog")
		  temp_float = 1.4;
		else if (targ.classname == "monster_army")
		  temp_float = 1.2;
		else if (targ.classname == "monster_enforcer")
		  temp_float = 1.0;
		else if (targ.classname == "monster_ogre")
		  temp_float = 0.9;
		else if (targ.classname == "monster_demon1")
		  temp_float = 0.7;
		else if (targ.classname == "monster_fish")
		  temp_float = 1.6;
		else if (targ.classname == "monster_knight")
		  temp_float = 1.1;
		else if (targ.classname == "monster_hell_knight")
		  temp_float = 0.8;
		else if (targ.classname == "monster_shalrath")
		  temp_float = 0.8;
		else if (targ.classname == "monster_shambler")
		  temp_float = 0.8;
		else if (targ.classname == "monster_wizard")
		  temp_float = 1.2;
		else
		// 63.8 is the size of a player/bot and is the reference for velocity
		// additions.  A player/bot always gets 1.0 * figured velocity
		// larger monsters, get (63.8 / vlen (size)) * figured velocity
		  temp_float = 63.8 / vlen (targ.size);


		targ.avelocity_y = targ.avelocity_y * temp_float;
		targ.velocity_x = targ.velocity_x * temp_float;
		targ.velocity_y = targ.velocity_y * temp_float;

		// if in the air already, give entity greater upward velocity
		if (!(targ.flags & FL_ONGROUND) && (targ.movetype == MOVETYPE_FLY))
		  targ.velocity_z = targ.velocity_z * 1.7;
		// scale velocity down if under water
if (((targ.classname == "player") && (targ.waterlevel > 1)) || (targ.waterlevel > 0))
		{
		  targ.velocity = targ.velocity * 0.5;
		  targ.avelocity_y = targ.avelocity_y * 0.5;
		}
		// scale velocity up for Quad damage
		if (attacker.items & IT_QUAD)
		{
		  targ.velocity = targ.velocity * 2.0;
		  targ.avelocity_y = targ.avelocity_y * 2.0;
		}

		targ.movetype = MOVETYPE_BOUNCE;
		targ.flags = targ.flags - (targ.flags & FL_ONGROUND);
	     }
// ZEUS 2.0 - end death velocities mod


// void (entity targ, entity inflictor, entity attacker, float damage) T_Damage
// void (entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage
if (inflictor.classname == "man")
	targ.deathtype = "man";
if (inflictor.classname == "super_laser")
	targ.deathtype = "super_laser";
if (inflictor.classname == "blendernail")
	targ.deathtype = "blendernail";
if (inflictor.classname == "volta")
	targ.deathtype = "volta";
if (inflictor.classname == "godfire")
	targ.deathtype = "godfire";
if (inflictor.classname == "lightmine")
	targ.deathtype = "lightmine";
if (inflictor.classname == "headbomb")
	targ.deathtype = "headbomb";
if (inflictor.classname == "vxgas")
	targ.deathtype = "vxgas";
if (inflictor.classname == "proxmine")
	targ.deathtype = "proxmine";
if (inflictor.classname == "holo")
	targ.deathtype = "holo";
if (inflictor.classname == "pds")
	targ.deathtype = "pds";
if (inflictor.classname == "meat")
	targ.deathtype = "meat";
if (inflictor.classname == "blaze")
	targ.deathtype = "blaze";
if (inflictor.classname == "vortex")
	targ.deathtype = "vortex";
if (inflictor.classname == "flame")
	targ.deathtype = "flame";
if (inflictor.classname == "posibeam")
	targ.deathtype = "posibeam";
if (inflictor.classname == "protonstorm")
	targ.deathtype = "protonstorm";
if (inflictor.classname == "explo")
	targ.deathtype = "explo";
if (inflictor.classname == "railbubble")
	targ.deathtype = "railbubble";
if (inflictor.classname == "laser")
	targ.deathtype = "laser";
if (inflictor.classname == "missile")
	targ.deathtype = "missile";
if (inflictor.classname == "plasma")
	targ.deathtype = "plasma";
if (inflictor.classname == "rpod")
	targ.deathtype = "rpod";
if (inflictor.classname == "throwaxe")
	targ.deathtype = "throwaxe";
if (inflictor.classname == "hmissile")
	targ.deathtype = "hmissile";
if (inflictor.classname == "dmissile")
	targ.deathtype = "dmissile";
if (inflictor.classname == "firebomb")
	targ.deathtype = "firebomb";
if (inflictor.classname == "shammissile")
	targ.deathtype = "shammissile";

      	Killed (targ,attacker);
      	
      return ;

   }
   oldself = self;
   self = targ;
   if ( ((self.flags & FL_MONSTER) && (attacker != world)) ) {

      if ( ((self != attacker) && (attacker != self.enemy)) ) {

         {

            if ( (self.enemy.classname == "player") ) {

               self.oldenemy = self.enemy;

            }
            self.enemy = attacker;
            FoundTarget ();

         }

      }

   }
   if ( self.th_pain ) {

      self.th_pain (attacker,take);
      if ( (skill == MOVETYPE_WALK) ) {

         self.pain_finished = (time + MOVETYPE_FLY);

      }

   }
   self = oldself;

};

void (entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage = {

   local float points;
   local entity head;
   local vector org,dir;	//dir added by bondo

   head = findradius (inflictor.origin,(damage + 40.000));
   while ( head ) {

      if ( (head != ignore) )
      {

         if ( head.takedamage ) {

            org = (head.origin + ((head.mins + head.maxs) * 0.500));
            points = (0.500 * vlen ((inflictor.origin - org)));

				//bondo's attempt to make creatures fly when attacked by radius damage
            dir = head.origin - inflictor.origin;
            dir = normalize(dir);
            //end of attempt

            if ( (points < FALSE) ) {

               points = FALSE;

            }
            points = (damage - points);
            if ( (head == attacker) ) {

               points = (points * 0.500);

            }
            
//	if ((inflictor.classname == "expbullet"))
//		points = points*2; //less damage

            if ( (points > FALSE) ) {

               if ( CanDamage (head,inflictor) )
               {
						//not enough gibbing
						//if (random() < 0.6)
						//	points = points * 2;
							
                  //if (head.classname == "monster_shambler" || head.classname == "mini_shambler" || head.classname == "big_shambler" || head.classname == "big_enforcer")
                    // T_Damage (head,inflictor,attacker,(points * 1.300));
		//				else
			//points = points * 2; //double damage from explosive weapons
                     T_Damage (head,inflictor,attacker,points);

						//bondo attempting again
						//this only causes grenades to bounce you around
						if ((head != attacker) && ( !deathmatch))
						{
						if (head.flags & FL_ONGROUND)
							head.flags = head.flags - FL_ONGROUND;

						//if ((inflictor.classname = "expbullet"))
						//	points = points * 30;
						//else
							points = points * 5;

						head.velocity = dir * points;				
						head.velocity_z = head.velocity_z + points;
						//end again
						}
               }

            }

         }

      }
      head = head.chain;

   }

};

void (entity attacker, float damage) T_BeamDamage = {

   local float points;
   local entity head;

   head = findradius (attacker.origin,(damage + 40.000));
   while ( head ) {

      if ( head.takedamage ) {

         points = (0.500 * vlen ((attacker.origin - head.origin)));
         if ( (points < FALSE) ) {

            points = FALSE;

         }
         points = (damage - points);
         if ( (head == attacker) ) {

            points = (points * 0.500);

         }
         if ( (points > FALSE) ) {

            if ( CanDamage (head,attacker) ) {

               if ( (head.classname == "monster_shambler") ) {

                  T_Damage (head,attacker,attacker,(points * 0.500));

               } else {

                  T_Damage (head,attacker,attacker,points);

               }

            }

         }

      }
      head = head.chain;

   }

};

