Beispiel #1
0
void hover_fire_blaster (edict_t *self)
{
	vec3_t	start;
	vec3_t	forward, right;
	vec3_t	end;
	vec3_t	dir;
	int		effect;

	if (!self->enemy)
		return;
	if (self->s.frame == FRAME_attak104)
		effect = EF_HYPERBLASTER;
	else
		effect = 0;

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1], forward, right, start);

	VectorCopy (self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;
	VectorSubtract (end, start, dir);

	if (self->radius_dmg)
		monster_fire_blaster (self, start, dir, 8 + (int) ceil(2.4 * self->monsterinfo.skill), 1000, MZ2_HOVER_BLASTER_1, effect);
	else
		monster_fire_blaster (self, start, dir, 3 + (int) ceil(1.2 * self->monsterinfo.skill), 1000, MZ2_HOVER_BLASTER_1, effect);
}
Beispiel #2
0
//Blaster
void actorBlaster (edict_t *self)
{
	vec3_t	start, target;
	vec3_t	forward, right, up;
	int		damage;
	int		effect, color;

	if(!self->enemy || !self->enemy->inuse)
		return;

	// Knightmare- select color and effect
	if (blaster_color->value == 2) { //green
		color = BLASTER_GREEN;
		effect = (EF_BLASTER|EF_TRACKER);
	}
	else if (blaster_color->value == 3) { //blue
		color = BLASTER_BLUE;
#ifdef KMQUAKE2_ENGINE_MOD
		effect = EF_BLASTER|EF_BLUEHYPERBLASTER;
#else
		effect = EF_BLUEHYPERBLASTER;
#endif
	}
#ifdef KMQUAKE2_ENGINE_MOD
	else if (blaster_color->value == 4) {//red
		color = BLASTER_RED;
		effect = EF_BLASTER|EF_IONRIPPER;
	}
#endif
	else { //standard yellow
		color = BLASTER_ORANGE;
		effect = EF_BLASTER;
	}

	AngleVectors (self->s.angles, forward, right, up);
	G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start);
	ActorTarget(self,target);
	VectorSubtract (target, start, forward);
	VectorNormalize (forward);

	if(self->monsterinfo.aiflags & AI_TWO_GUNS)
		damage = 5;
	else
		damage = 10;

	monster_fire_blaster (self, start, forward, damage, 600, MZ2_SOLDIER_BLASTER_2, effect, color);

	if(developer->value)
		TraceAimPoint(start,target);

	if(self->monsterinfo.aiflags & AI_TWO_GUNS)
	{
		G_ProjectSource2(self->s.origin,self->muzzle2,forward,right,up,start);
		VectorSubtract (target, start, forward);
		VectorNormalize (forward);
		monster_fire_blaster (self, start, forward, damage, 600, MZ2_SOLDIER_BLASTER_2, effect, color);
	}

}
Beispiel #3
0
void TankBlaster (edict_t *self)
{
	vec3_t	forward, right;
	vec3_t	start;
	vec3_t	end;
	vec3_t	dir;
	int		flash_number;

	if(!self->enemy || !self->enemy->inuse)		//PGM
		return;									//PGM

	if (self->s.frame == FRAME_attak110)
		flash_number = MZ2_TANK_BLASTER_1;
	else if (self->s.frame == FRAME_attak113)
		flash_number = MZ2_TANK_BLASTER_2;
	else // (self->s.frame == FRAME_attak116)
		flash_number = MZ2_TANK_BLASTER_3;

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);

	VectorCopy (self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;
	VectorSubtract (end, start, dir);

	monster_fire_blaster (self, start, dir, 30, 800, flash_number, EF_BLASTER);
}	
Beispiel #4
0
// FIXME: This is all wrong. He's not firing at the proper angles.
void MakronHyperblaster (edict_t *self)
{
	vec3_t	dir;
	vec3_t	vec;
	vec3_t	start;
	vec3_t	forward, right;
	int		flash_number;

	flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405);

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);

	if (self->enemy)
	{
		VectorCopy (self->enemy->s.origin, vec);
		vec[2] += self->enemy->viewheight;
		VectorSubtract (vec, start, vec);
		vectoangles (vec, vec);
		dir[0] = vec[0];
	}
	else
	{
		dir[0] = 0;
	}
	if (self->s.frame <= FRAME_attak413)
		dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413);
	else
		dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421);
	dir[2] = 0;

	AngleVectors (dir, forward, NULL, NULL);

	monster_fire_blaster (self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER);
}	
void hover_fire_blaster (edict_t *self)
{
	vec3_t	start;
	vec3_t	forward, right;
	vec3_t	end;
	vec3_t	dir;
	int		effect;

	if (self->s.frame == FRAME_attak104)
		effect = EF_HYPERBLASTER;
	else
		effect = 0;

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1], forward, right, start);

	VectorCopy (self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;

	// Lazarus fog reduction of accuracy
	if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
	{
		end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
	}
	
	VectorSubtract (end, start, dir);
	monster_fire_blaster (self, start, dir, 1, 1000, MZ2_HOVER_BLASTER_1, effect, BLASTER_ORANGE);
}
Beispiel #6
0
void myTankBlaster (edict_t *self)
{
	int		flash_number, speed, damage;
	vec3_t	forward, start;

	// alternate attack for commander
	if (self->s.skinnum & 2)
	{
		myTankRail(self);
		return;
	}

	if (self->s.frame == FRAME_attak110)
		flash_number = MZ2_TANK_BLASTER_1;
	else if (self->s.frame == FRAME_attak113)
		flash_number = MZ2_TANK_BLASTER_2;
	else
		flash_number = MZ2_TANK_BLASTER_3;

	damage = 50 + 10*self->monsterinfo.level;
	speed = 1000 + 50*self->monsterinfo.level;

	MonsterAim(self, 0.8, speed, false, flash_number, forward, start);
	monster_fire_blaster(self, start, forward, damage, speed, EF_BLASTER, BLASTER_PROJ_BOLT, 2.0, true, flash_number);
}	
Beispiel #7
0
 void
 hover_fire_blaster ( edict_t *self )
 {
   vec3_t start;
   vec3_t forward, right;
   vec3_t end;
   vec3_t dir;
   q_int32_t effect;

   if ( !self ) {
     return;
   }

   if ( self->s.frame == FRAME_attak104 ) {
     effect = EF_HYPERBLASTER;
   } else {
     effect = 0;
   }

   AngleVectors ( self->s.angles, forward, right, NULL );
   G_ProjectSource ( self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1],
                     forward, right, start );

   VectorCopy ( self->enemy->s.origin, end );
   end[2] += self->enemy->viewheight;
   VectorSubtract ( end, start, dir );

   monster_fire_blaster ( self, start, dir, 1, 1000, MZ2_HOVER_BLASTER_1, effect );
 }
Beispiel #8
0
void floater_fire_blaster(edict_t * self)
{
	vec3_t start;
	vec3_t forward, right;
	vec3_t end;
	vec3_t dir;
	int effect;

	if ((self->s.frame == FRAME_attak104)
	    || (self->s.frame == FRAME_attak107))
		effect = EF_HYPERBLASTER;
	else
		effect = 0;
	AngleVectors(self->s.angles, forward, right, NULL);
	G_ProjectSource(self->s.origin,
			monster_flash_offset[MZ2_FLOAT_BLASTER_1], forward,
			right, start);

	VectorCopy(self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;
	VectorSubtract(end, start, dir);

	monster_fire_blaster(self, start, dir, 1, 1000, MZ2_FLOAT_BLASTER_1,
			     effect);
}
Beispiel #9
0
void flyer_fire(edict_t *self, int flash_number)
{
	vec3_t	start, end;
	vec3_t	forward, right, dir;
	int		effect;

	if (self->s.frame == FRAME_attak204 || self->s.frame == FRAME_attak207 || self->s.frame == FRAME_attak210)
		effect = EF_HYPERBLASTER;
	else
		effect = 0;

	AngleVectors(self->s.angles, forward, right, NULL);
	G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start);
	VectorCopy(self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;

	// Lazarus fog reduction of accuracy
	/*if (self->monsterinfo.visibility < FOG_CANSEEGOOD)
	{
		end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
	}*/
	AdjustAccuracy(self, end); //mxd. Fog & Invisibility mode adjustments

	VectorSubtract(end, start, dir);
	monster_fire_blaster(self, start, dir, 1, 1000, flash_number, effect, BLASTER_ORANGE);
}
Beispiel #10
0
void
flyer_fire(edict_t *self, int flash_number)
{
	vec3_t start;
	vec3_t forward, right;
	vec3_t end;
	vec3_t dir;
	int effect;

	if (!self)
	{
		return;
	}

	if ((self->s.frame == FRAME_attak204) ||
		(self->s.frame == FRAME_attak207) ||
		(self->s.frame == FRAME_attak210))
	{
		effect = EF_HYPERBLASTER;
	}
	else
	{
		effect = 0;
	}

	AngleVectors(self->s.angles, forward, right, NULL);
	G_ProjectSource(self->s.origin, monster_flash_offset[flash_number],
			forward, right, start);

	VectorCopy(self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;
	VectorSubtract(end, start, dir);

	monster_fire_blaster(self, start, dir, 1, 1000, flash_number, effect);
}
Beispiel #11
0
void TankBlaster (edict_t *self)
{
	vec3_t	forward, right;
	vec3_t	start;
	vec3_t	end;
	vec3_t	dir;
	int		flash_number;

	if (!self->enemy || !self->enemy->inuse)
		return;

	if (self->s.frame == FRAME_attak110)
		flash_number = MZ2_TANK_BLASTER_1;
	else if (self->s.frame == FRAME_attak113)
		flash_number = MZ2_TANK_BLASTER_2;
	else // (self->s.frame == FRAME_attak116)
		flash_number = MZ2_TANK_BLASTER_3;

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
	VectorCopy (self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;

	// Lazarus fog reduction of accuracy
	if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
	{
		end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
	}

	VectorSubtract (end, start, dir);
	monster_fire_blaster (self, start, dir, 30, 800, flash_number, EF_BLASTER, BLASTER_ORANGE);
}	
Beispiel #12
0
void
soldier_fire(edict_t * self, int flash_number)
{
	vec3_t		start;
	vec3_t		forward, right, up;
	vec3_t		aim;
	vec3_t		dir;
	vec3_t		end;
	float		r       , u;
	int		flash_index;

	if (self->s.skinnum < 2)
		flash_index = blaster_flash[flash_number];
	else if (self->s.skinnum < 4)
		flash_index = shotgun_flash[flash_number];
	else
		flash_index = machinegun_flash[flash_number];

	AngleVectors(self->s.angles, forward, right, NULL);
	G_ProjectSource(self->s.origin, monster_flash_offset[flash_index], forward, right, start);

	if (flash_number == 5 || flash_number == 6) {
		VectorCopy(forward, aim);
	} else {
		VectorCopy(self->enemy->s.origin, end);
		end[2] += self->enemy->viewheight;
		VectorSubtract(end, start, aim);
		vectoangles(aim, dir);
		AngleVectors(dir, forward, right, up);

		r = crandom() * 1000;
		u = crandom() * 500;
		VectorMA(start, 8192, forward, end);
		VectorMA(end, r, right, end);
		VectorMA(end, u, up, end);

		VectorSubtract(end, start, aim);
		VectorNormalize(aim);
	}

	if (self->s.skinnum <= 1) {
		monster_fire_blaster(self, start, aim, 5, 600, flash_index, EF_BLASTER);
	} else if (self->s.skinnum <= 3) {
		monster_fire_shotgun(self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
	} else {
		if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
			self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;

		monster_fire_bullet(self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);

		if (level.time >= self->monsterinfo.pausetime)
			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		else
			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
	}
}
Beispiel #13
0
// FIXME: This is all wrong. He's not firing at the proper angles.
void MakronHyperblaster (edict_t *self)
{
	vec3_t	forward, start;
	int		damage, speed, flash_number;

	flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405);

	damage = 50 + 10*self->monsterinfo.level;
	speed = 1000 + 50*self->monsterinfo.level;

	MonsterAim(self, 0.8, 1500, false, flash_number, forward, start);
	monster_fire_blaster(self, start, forward, damage, speed, EF_BLASTER, BLASTER_PROJ_BOLT, 2.0, true, flash_number);
}	
Beispiel #14
0
void soldier_fireblaster (edict_t *self)
{
	int		damage, speed;
	vec3_t	forward, start;
	
	if (!G_EntExists(self->enemy))
		return;

	damage = 50 + 10*self->monsterinfo.level;
	speed = 1000 + 50*self->monsterinfo.level;

	MonsterAim(self, 0.8, speed, false, MZ2_SOLDIER_BLASTER_8, forward, start);
	monster_fire_blaster(self, start, forward, damage, speed, EF_BLASTER, BLASTER_PROJ_BOLT, 2.0, true, MZ2_SOLDIER_BLASTER_8);
}
Beispiel #15
0
void mymedic_fire_bolt (edict_t *self)
{
	int		min, max, damage;
	vec3_t	forward, start;

	min = 4*self->monsterinfo.level;
	max = 60 + 30*self->monsterinfo.level;

	damage = GetRandom(min, max);

	MonsterAim(self, 0.8, 1500, false, MZ2_MEDIC_BLASTER_1, forward, start);
	monster_fire_blaster(self, start, forward, damage, 1500, EF_BLASTER, BLASTER_PROJ_BLAST, 2.0, true, MZ2_MEDIC_BLASTER_1);

	gi.sound (self, CHAN_WEAPON, gi.soundindex("weapons/photon.wav"), 1, ATTN_NORM, 0);
}
Beispiel #16
0
void MakronHyperblaster (edict_t *self)
{
	vec3_t	v;
	vec3_t	dir;
	vec3_t	vec;
	vec3_t	start;
	vec3_t	forward, right;
	int		flash_number;
	int damage;

	if (!self->enemy)
		return;

	if (self->radius_dmg)
		damage = 40 + 6 * self->monsterinfo.skill;
	else
		damage = 20 + 3 * self->monsterinfo.skill;

	flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405);

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);

	VectorSubtract (self->enemy->s.origin, self->s.origin, v);
	self->ideal_yaw = vectoyaw(v);
	M_ChangeYaw (self);
	VectorMA(self->enemy->s.origin, 0.3, self->enemy->velocity, vec);
//	VectorCopy (self->enemy->s.origin, vec);
	vec[2] += self->enemy->viewheight;
	VectorSubtract (vec, start, vec);
	vectoangles (vec, vec);
	dir[0] = vec[0];

	if (self->s.frame <= FRAME_attak413)
		dir[1] = self->s.angles[1] - (1.5 - 0.01 * self->monsterinfo.skill) * (self->s.frame - FRAME_attak413);
	else
		dir[1] = self->s.angles[1] + (1.5 - 0.01 * self->monsterinfo.skill) * (self->s.frame - FRAME_attak421);

	dir[2] = 0;

	AngleVectors (dir, forward, NULL, NULL);

	monster_fire_blaster (self, start, forward, damage, 600 + 15 * self->monsterinfo.skill, MZ2_MAKRON_BLASTER_1, EF_BLASTER);
}
Beispiel #17
0
void mymedic_fire_blaster (edict_t *self)
{
	int		effect, damage;
	vec3_t	forward, start;
	qboolean bounce = false;
	
	if ((self->s.frame == FRAME_attack9) || (self->s.frame == FRAME_attack12))
	{
		effect = EF_BLASTER;
		bounce = true;
	}
	else
		effect = EF_HYPERBLASTER;

	damage = 20 + 3*self->monsterinfo.level;

	MonsterAim(self, 0.8, 2000, false, MZ2_MEDIC_BLASTER_1, forward, start);
	monster_fire_blaster(self, start, forward, damage, 2000, effect, BLASTER_PROJ_BOLT, 2.0, bounce, MZ2_MEDIC_BLASTER_1);
}
Beispiel #18
0
// FIXME: This is all wrong. He's not firing at the proper angles.
void MakronHyperblaster (edict_t *self)
{
	vec3_t	dir;
	vec3_t	vec;
	vec3_t	start;
	vec3_t	forward, right;
	int		flash_number;

	flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405);

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);

	if (self->enemy)
	{
		VectorCopy (self->enemy->s.origin, vec);
		vec[2] += self->enemy->viewheight;
		// Lazarus fog reduction of accuracy
		if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
		{
			vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		}
		VectorSubtract (vec, start, vec);
		vectoangles (vec, vec);
		dir[0] = vec[0];
	}
	else
	{
		dir[0] = 0;
	}
	if (self->s.frame <= FRAME_attak413)
		dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413);
	else
		dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421);
	dir[2] = 0;

	AngleVectors (dir, forward, NULL, NULL);

	monster_fire_blaster (self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER, BLASTER_ORANGE);
}
Beispiel #19
0
void
medic_fire_blaster(edict_t *self)
{
	vec3_t start;
	vec3_t forward, right;
	vec3_t end;
	vec3_t dir;
	int effect;

	if (!self)
	{
		return;
	}

	if ((self->s.frame == FRAME_attack9) || (self->s.frame == FRAME_attack12))
	{
		effect = EF_BLASTER;
	}
	else if ((self->s.frame == FRAME_attack19) ||
			 (self->s.frame == FRAME_attack22) ||
			 (self->s.frame == FRAME_attack25) ||
			 (self->s.frame == FRAME_attack28))
	{
		effect = EF_HYPERBLASTER;
	}
	else
	{
		effect = 0;
	}

	AngleVectors(self->s.angles, forward, right, NULL);
	G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_MEDIC_BLASTER_1],
			forward, right, start);

	VectorCopy(self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;
	VectorSubtract(end, start, dir);

	monster_fire_blaster(self, start, dir, 2, 1000, MZ2_MEDIC_BLASTER_1, effect);
}
Beispiel #20
0
void fixbot_fire_blaster (edict_t *self)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	end;
	vec3_t	dir;

	if (!visible(self, self->enemy))
	{
		self->monsterinfo.currentmove = &fixbot_move_run;	
	}
	
	AngleVectors (self->s.angles, forward, right, up);
	G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_fixbot_BLASTER_1], forward, right, start);

	VectorCopy (self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;
	VectorSubtract (end, start, dir);

	monster_fire_blaster (self, start, dir, 15, 1000, MZ2_fixbot_BLASTER_1, EF_BLASTER);
	
}
void medic_fire_blaster (edict_t *self)
{
	vec3_t	start;
	vec3_t	forward, right;
	vec3_t	end;
	vec3_t	dir;
	int		effect;
	int		damage = 2;

	// paranoia checking
	if (!(self->enemy && self->enemy->inuse))
		return;

	if ((self->s.frame == FRAME_attack9) || (self->s.frame == FRAME_attack12))
		effect = EF_BLASTER;
	else if ((self->s.frame == FRAME_attack19) || (self->s.frame == FRAME_attack22) || (self->s.frame == FRAME_attack25) || (self->s.frame == FRAME_attack28))
		effect = EF_HYPERBLASTER;
	else
		effect = 0;

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MEDIC_BLASTER_1], forward, right, start);

	VectorCopy (self->enemy->s.origin, end);
	end[2] += self->enemy->viewheight;
	VectorSubtract (end, start, dir);

	if (!strcmp(self->enemy->classname, "tesla"))
		damage = 3;

	// medic commander shoots blaster2
	if (self->mass > 400)
		monster_fire_blaster2 (self, start, dir, damage, 1000, MZ2_MEDIC_BLASTER_2, effect);
	else
		monster_fire_blaster (self, start, dir, damage, 1000, MZ2_MEDIC_BLASTER_1, effect);
}
Beispiel #22
0
void soldier_fire (edict_t *self, int flash_number)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	aim;
	vec3_t	dir;
	vec3_t	end;
	float	r, u;
	int		flash_index;

	if ((self->s.skinnum % 6) < 2)
		flash_index = blaster_flash[flash_number];
	else if ((self->s.skinnum % 6) < 4)
		flash_index = shotgun_flash[flash_number];
	else
		flash_index = machinegun_flash[flash_number];

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);

	if (flash_number == 5 || flash_number == 6)
	{
		VectorCopy (forward, aim);
	}
	else
	{
		VectorCopy (self->enemy->s.origin, end);
		end[2] += self->enemy->viewheight;

		// Lazarus fog reduction of accuracy
		if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
		{
			end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		}
		
		VectorSubtract (end, start, aim);
		// Lazarus: Accuracy is skill level dependent
		if(skill->value < 3)
		{
			vectoangles (aim, dir);
			AngleVectors (dir, forward, right, up);

			r = crandom()*(1000 - 333*skill->value);
			u = crandom()*(500 - 167*skill->value);
			VectorMA (start, 8192, forward, end);
			VectorMA (end, r, right, end);
			VectorMA (end, u, up, end);

			VectorSubtract (end, start, aim);
		}
		VectorNormalize (aim);
	}

	if ((self->s.skinnum % 6) <= 1)
	{
		// Lazarus: make bolt speed skill level dependent
		monster_fire_blaster (self, start, aim, 5, 600 + 100*skill->value, flash_index, EF_BLASTER, BLASTER_ORANGE);
	}
	else if ((self->s.skinnum % 6) <= 3)
	{
		monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
	}
	else
	{
		if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
			self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;

		monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);

		if (level.time >= self->monsterinfo.pausetime)
			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		else
			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
	}
}
Beispiel #23
0
void soldier_fire (edict_t *self, int flash_number)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	aim;
	vec3_t	dir;
	vec3_t	end;
	float	r, u;
	int		flash_index;

	if (!self->enemy)
		return;
	if (self->s.skinnum < 2)
		flash_index = blaster_flash[flash_number];
	else if (self->s.skinnum < 4)
		flash_index = shotgun_flash[flash_number];
	else
		flash_index = machinegun_flash[flash_number];

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);

	if (flash_number == 5 || flash_number == 6)
	{
		VectorCopy (forward, aim);
	}
	else
	{
		VectorMA(self->enemy->s.origin, 0.3, self->enemy->velocity, end);
		end[2] += self->enemy->viewheight;
		VectorSubtract (end, start, aim);
		vectoangles (aim, dir);
		AngleVectors (dir, forward, right, up);

		if (self->s.skinnum <= 1)
		{
			r = crandom()*(500 - 6 * self->monsterinfo.skill);
			u = crandom()*(250 - 3 * self->monsterinfo.skill);
		} else {
			r = crandom()*(800 - 16 * self->monsterinfo.skill);
			u = crandom()*(400 - 8 * self->monsterinfo.skill);
		}

		VectorMA (start, 8192, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);

		VectorSubtract (end, start, aim);
		VectorNormalize (aim);
	}

	if (self->s.skinnum <= 1) {
		if (self->radius_dmg)
			monster_fire_blaster (self, start, aim, (int) ceil(8.0 + 5.0 * self->monsterinfo.skill), 1500 + 50 * self->monsterinfo.skill, flash_index, 0);
		else
			monster_fire_blaster (self, start, aim, (int) ceil(4.0 + 2.5 * self->monsterinfo.skill), 900 + 30 * self->monsterinfo.skill, flash_index, 0);
		if (self->s.frame == 41) {
			if (level.time >= self->monsterinfo.pausetime) {
				if (visible(self, self->enemy) && (self->enemy->health > 0) && (random() <= 0.9)) {
					self->monsterinfo.pausetime = level.time + (4 + rand() % 4) * FRAMETIME;
					self->monsterinfo.aiflags |= AI_HOLD_FRAME;
				} else {
					self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
				}
			} else {
				self->monsterinfo.aiflags |= AI_HOLD_FRAME;
			}
		}
	}
	else if (self->s.skinnum <= 3)
	{
		if (self->radius_dmg)
			monster_fire_shotgun (self, start, aim, (int) ceil(2.0 + 0.6 * self->monsterinfo.skill), 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
		else
			monster_fire_shotgun (self, start, aim, (int) ceil(1.0 + 0.3 * self->monsterinfo.skill), 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
	}
	else
	{
		vec3_t	target;
		if ((!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) && (self->health > 0))
			self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;

		// project enemy back a bit and target there
		VectorCopy (self->enemy->s.origin, target);
		VectorMA (target, (-0.5 + 0.015 * self->monsterinfo.skill), self->enemy->velocity, target);
		target[2] += self->enemy->viewheight;

		VectorSubtract (target, start, aim);
		VectorNormalize (aim);

		if (self->radius_dmg)
			monster_fire_bullet (self, start, aim, (int) ceil(4.2 + 2.2 * self->monsterinfo.skill), 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);
		else
			monster_fire_bullet (self, start, aim, (int) ceil(2.1 + 1.1 * self->monsterinfo.skill), 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);

		if (level.time >= self->monsterinfo.pausetime)
			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		else {
			self->s.frame--;
//			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
		}
	}
}
Beispiel #24
0
//void soldier_fire (edict_t *self, int flash_number)  PMM
void soldier_fire (edict_t *self, int in_flash_number)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	aim;
	vec3_t	dir;
	vec3_t	end;
	float	r, u;
	int		flash_index;
	int		flash_number;
#ifdef RUN_SHOOT
	vec3_t	aim_norm;
	float	angle;
#endif
#ifdef CHECK_TARGET
	trace_t	tr;
	vec3_t aim_good;
#endif

	if ((!self->enemy) || (!self->enemy->inuse))
	{
		self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		return;
	}

	if (in_flash_number < 0)
	{
		flash_number = -1 * in_flash_number;
	}
	else
		flash_number = in_flash_number;

	if (self->s.skinnum < 2)
		flash_index = blaster_flash[flash_number];
	else if (self->s.skinnum < 4)
		flash_index = shotgun_flash[flash_number];
	else
		flash_index = machinegun_flash[flash_number];

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);

	if (flash_number == 5 || flash_number == 6) // he's dead
	{
		VectorCopy (forward, aim);
	}
	else
	{
		VectorCopy (self->enemy->s.origin, end);
		end[2] += self->enemy->viewheight;
		VectorSubtract (end, start, aim);
#ifdef CHECK_TARGET
		VectorCopy (end, aim_good);
#endif
#ifdef RUN_SHOOT
		//PMM
		if (in_flash_number < 0)
		{
			VectorCopy (aim, aim_norm);
			VectorNormalize (aim_norm);
			angle = DotProduct (aim_norm, forward);
			//gi.dprintf ("Dot Product:  %f", DotProduct (aim_norm, forward));
			if (angle < 0.9)  // ~25 degree angle
			{
//				if(g_showlogic && g_showlogic->value)
//					gi.dprintf (" not firing due to bad dotprod %f\n", angle);
				return;
			}
//			else
//			{
//				if(g_showlogic && g_showlogic->value)
//					gi.dprintf (" firing:  dotprod = %f\n", angle);
//			}
		}
		//-PMM
#endif
		vectoangles (aim, dir);
		AngleVectors (dir, forward, right, up);
		
		if (skill->value < 2)
		{
			r = crandom()*1000;
			u = crandom()*500;
		}
		else
		{
			r = crandom()*500;
			u = crandom()*250;
		}
		VectorMA (start, 8192, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);

		VectorSubtract (end, start, aim);
		VectorNormalize (aim);
	}
#ifdef CHECK_TARGET
	if (!(flash_number == 5 || flash_number == 6)) // he's dead
	{
		tr = gi.trace (start, NULL, NULL, aim_good, self, MASK_SHOT);
		if ((tr.ent != self->enemy) && (tr.ent != world))
		{
//			if(g_showlogic && g_showlogic->value)
//				gi.dprintf ("infantry shot aborted due to bad target\n");
			return;
		}
	}
#endif
	if (self->s.skinnum <= 1)
	{
		monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER);
	}
	else if (self->s.skinnum <= 3)
	{
		monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
	}
	else
	{
		// PMM - changed to wait from pausetime to not interfere with dodge code
		if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
			self->wait = level.time + (3 + rand() % 8) * FRAMETIME;

		monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);

		if (level.time >= self->wait)
			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		else
			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
	}
}
Beispiel #25
0
int T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod) {
	qboolean mod_magic = false;
	gclient_t	*client;
	int			take = 0;
	int			save = 0;
	int			asave = 0;
	int			psave = 0;
	int			rsave = 0;
	int			sasave = 0;
	int			te_sparks;

	if (!targ->takedamage)
		return 0;

// Can't heal monsters
	if ((damage < 0) && (targ->svflags & SVF_MONSTER)) {
		return 0;
	}

	if (mod & MOD_MAGIC) { //damage dealt by magic
		mod_magic = true;
		mod &= ~MOD_MAGIC;
	}
	// friendly fire avoidance
	// if enabled you can't hurt teammates (but you can hurt yourself)
	// knockback still occurs

	// team damage avoidance, if not telefrag
	if (mod != MOD_TELEFRAG) {
		if (deathmatch->value && attacker->client && targ->client && (targ != attacker) && (((targ->count == attacker->count) && teams->value) || (game.monsterhunt == 10)) && (damage > 0)) { // Two players on same team
			damage *= teamdamage->value;
		}
		if (coop->value && attacker->client && targ->client && (targ != attacker)) {
			damage *= teamdamage->value;
		}
	}
	meansOfDeath = mod;

	client = targ->client;

	if (dflags & DAMAGE_BULLET)
		te_sparks = TE_BULLET_SPARKS;
	else
		te_sparks = TE_SPARKS;

	VectorNormalize(dir);

	if (targ->flags & FL_NO_KNOCKBACK)
		knockback = 0;

// Simulate armor pierce and armor breaker on monsters
// This has been disabled, since it applies bonus AFTER all other bonuses, resulting in crazy total bonuses
/*	if ((targ->svflags & SVF_MONSTER) && (attacker->client) && (!mod_magic)) {
		if (attacker->client->pers.skill[2] > 0) {
			if (mod == MOD_BLASTER) {
				iteminfo_t *winfo = getWornItemInfo(attacker, 0);
				damage *= 1 + 0.75 * (winfo->arg4 + winfo->arg5 * attacker->client->pers.skill[2]);
			} else {
				damage *= 1 + 0.02 * attacker->client->pers.skill[2];
			}
		}
		if (attacker->client->pers.skill[72] > 0) {
			damage *= 1 + 0.02 * attacker->client->pers.skill[72];
		}
	}*/

	if ((targ->svflags & SVF_MONSTER) && (targ->health > 0)) {
		float manaburn_mult = 0.0f;
		float manaleech_mult = 0.0f;
		if ((targ->radius_dmg) && (targ->monsterinfo.ability) && (damage > 0)) {
			rsave = 0;
			if ((targ->monsterinfo.ability & GIEX_MABILITY_RES_EXPL) &&
				((mod == MOD_GRENADE) || (mod == MOD_G_SPLASH) ||
				(mod == MOD_ROCKET) || (mod == MOD_R_SPLASH) ||
				(mod == MOD_HANDGRENADE) || (mod == MOD_HG_SPLASH))) {
				rsave += 0.33 * damage;
			}
			if ((targ->monsterinfo.ability & GIEX_MABILITY_RES_IMPACT) &&
				((mod == MOD_MACHINEGUN) || (mod == MOD_CHAINGUN) ||
				(mod == MOD_SHOTGUN) || (mod == MOD_SSHOTGUN))) {
				rsave += 0.33 * damage;
			}
			if ((targ->monsterinfo.ability & GIEX_MABILITY_RES_ENERGY) &&
				((mod == MOD_BLASTER) || (mod == MOD_HYPERBLASTER) ||
				(mod == MOD_LASERMINE) || (mod == MOD_RAILGUN) ||
				(mod == MOD_BFG_LASER) || (mod == MOD_BFG_BLAST) || (mod == MOD_BFG_EFFECT))) {
				rsave += 0.33 * damage;
			}
			if ((targ->monsterinfo.ability & GIEX_MABILITY_RES_BMAGIC) &&
				((mod == MOD_PLAGUEBOMB) || (mod == MOD_DRAIN) || (mod == MOD_SPORE))) {
				rsave += 0.33 * damage;
			}
			if ((targ->monsterinfo.ability & GIEX_MABILITY_RES_FMAGIC) &&
				((mod == MOD_INFERNO) || (mod == MOD_FIREBOLT) ||
				(mod == MOD_FIREBALL) || (mod == MOD_CORPSEEXPLOSION))) {
				rsave += 0.33 * damage;
			}
			if ((targ->monsterinfo.ability & GIEX_MABILITY_RES_LMAGIC) &&
				((mod == MOD_LIGHTNING) || (mod == MOD_SPARK) || (mod == MOD_BOLT) || (mod == MOD_STORM))) {
				rsave += 0.33 * damage;
			}
			if (rsave > 0) {
				//Anti-resist
				int arlvl = getAuraLevel(attacker, 84);
				if (arlvl > 0) {
					int slot = getAuraSlot(attacker, 84);
					if (attacker->client->aura_caster[slot]->client->magic > 0) {
						attacker->client->aura_caster[slot]->client->magic -= 0.1 * rsave;
						attacker->client->aura_caster[slot]->client->magregentime = level.time + 1.0;
						rsave *= 1 - (arlvl * 0.02);
					}
				}
				damage -= rsave;
			}
		}

		if (attacker->client) {
			if (dflags & DAMAGE_10_MANABURN) // 10%
				manaburn_mult += 0.1;
			if (dflags & DAMAGE_25_MANABURN) // 25%
				manaburn_mult += 0.25;
			if (dflags & DAMAGE_50_MANABURN) // 50%
				manaburn_mult += 0.5;
			if (dflags & DAMAGE_100_MANABURN) // 100%
				manaburn_mult += 1.0;
			if (dflags & DAMAGE_200_MANABURN) // 200%
				manaburn_mult += 2.0;
			if (dflags & DAMAGE_400_MANABURN) // 400%
				manaburn_mult += 4.0;
			if (dflags & DAMAGE_50_MANALEECH) // 50%
				manaleech_mult += 0.5;
			if (dflags & DAMAGE_100_MANALEECH) // 100%
				manaleech_mult += 1.0;
			if (dflags & DAMAGE_200_MANALEECH) // 200%
				manaleech_mult += 2.0;

			if ((manaburn_mult > 0.0) && (attacker->client->magic < attacker->client->max_magic * 4)) {
				attacker->client->magic += (int) ceil(damage * manaburn_mult);
				if (attacker->client->magic > attacker->client->max_magic * 4) {
					attacker->client->magic = attacker->client->max_magic * 4;
				}
				gi.WriteByte (svc_muzzleflash);
				gi.WriteShort (targ-g_edicts);
				gi.WriteByte (MZ_NUKE4);
				gi.multicast (targ->s.origin, MULTICAST_PVS);
			}
			if (manaleech_mult > 0.0) {
				if (attacker->client->magic < attacker->client->max_magic * 4) {
					attacker->client->magic += (int) ceil(damage * manaleech_mult);
					if (attacker->client->magic > attacker->client->max_magic * 4) {
						attacker->client->magic = attacker->client->max_magic * 4;
					}
				}
				if (manaburn_mult == 0.0) {
					gi.WriteByte (svc_muzzleflash);
					gi.WriteShort (targ-g_edicts);
					gi.WriteByte (MZ_NUKE4);
					gi.multicast (targ->s.origin, MULTICAST_PVS);
				}
			}
		}
	}

	if (client && (damage > 0) && (targ->health > 0)) {
		int pre_damage = damage;
		int nosanc_damage = damage;
		int pre_magic = targ->client->magic;
		float res_boost = 0.15 * targ->client->pers.skill[45]; //Resistance boost
		float manaburn_mult = 0.0f;
		float manaleech_mult = 0.0f;
		if (targ->client->magic <= 0)
			res_boost = 0;

//Sanctuary aura
		if ((getAuraLevel(targ, 65) > 0) && (damage > 0)) {
			int slot = getAuraSlot(targ, 65);
			if (targ->client->aura_caster[slot]->client->magic > 0) {
				float bonus = getMagicBonuses(targ->client->aura_caster[slot], 65);
				float dmg_mult = 1.0;
				float cost_mult = 0.0;

				dmg_mult = (0.004 * targ->client->aura_level[slot] * (0.2 + bonus * 0.8));
				if (dmg_mult > 1)
					dmg_mult = 1.0;

				cost_mult = 0.002 * targ->client->aura_level[slot];
				if (targ->client->aura_level[slot] > 40) {
					cost_mult += 0.002 * (targ->client->aura_level[slot] - 40);
				}
				cost_mult *= ((float) (targ->client->aura_caster[slot]->client->max_magic + 800.0)) / 800.0;

				if (cost_mult * damage > targ->client->aura_caster[slot]->client->magic) {
					int dmgsave = (int) targ->client->aura_caster[slot]->client->magic / cost_mult;
					//gi.dprintf("%d %d %f %d %d\n", damage, dmgsave, cost_mult, targ->client->aura_caster[slot]->client->magic, (int) dmgsave * cost_mult);
					sasave += dmgsave * dmg_mult;
					damage -= dmgsave * dmg_mult;
					targ->client->aura_caster[slot]->client->magic -= dmgsave * cost_mult;
				} else {
					targ->client->aura_caster[slot]->client->magic -= cost_mult * damage;
					sasave += dmg_mult * damage;
					damage *= 1.0 - dmg_mult;
				}
				targ->client->aura_caster[slot]->client->magregentime = level.time + 1.0;
				gi.sound(targ, CHAN_ITEM, gi.soundindex("giex/magarm1.wav"), 0.5, ATTN_NORM, 0);
			}
		}

		rsave = 0;
		// Global (Damage resist)
		if (targ->client->pers.skill[46] > 0) {
			rsave += damage * 0.01 * targ->client->pers.skill[46];
		}

		// Bullet
		if ((targ->client->pers.skill[36] > 0) &&
			((mod == MOD_MACHINEGUN) || (mod == MOD_CHAINGUN))) {
			rsave += damage * 0.015 * targ->client->pers.skill[36] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		// Pellet
		else if ((targ->client->pers.skill[37] > 0) &&
			((mod == MOD_SHOTGUN) || (mod == MOD_SSHOTGUN))) {
			rsave += damage * 0.015 * targ->client->pers.skill[37] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		// Explosion
		else if ((targ->client->pers.skill[38] > 0) &&
			((mod == MOD_GRENADE) || (mod == MOD_G_SPLASH) ||
			(mod == MOD_ROCKET) || (mod == MOD_R_SPLASH) ||
			(mod == MOD_HANDGRENADE) || (mod == MOD_HG_SPLASH))) {
			rsave += damage * 0.015 * targ->client->pers.skill[38] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		// Energy
		else if ((targ->client->pers.skill[39] > 0) &&
			((mod == MOD_BLASTER) || (mod == MOD_HYPERBLASTER) ||
			(mod == MOD_LASERMINE))) {
			rsave += damage * 0.015 * targ->client->pers.skill[39] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		// High energy
		else if ((targ->client->pers.skill[40] > 0) &&
			((mod == MOD_RAILGUN) || (mod == MOD_BFG_LASER) ||
			(mod == MOD_BFG_BLAST) || (mod == MOD_BFG_EFFECT))) {
			rsave += damage * 0.015 * targ->client->pers.skill[40] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		// World and hit damage
		else if (targ->client->pers.skill[41] > 0) {
			if ((mod == MOD_WATER) || (mod == MOD_SLIME) || (mod == MOD_FALLING) ||
				(mod == MOD_LAVA) || (mod == MOD_CRUSH)) {
				rsave += damage * 0.1 * targ->client->pers.skill[41];
			} else if (mod == MOD_HIT) {
				rsave += damage * 0.015 * targ->client->pers.skill[41] * res_boost;
				targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
			}
		}
		// Blood magic
		else if ((targ->client->pers.skill[42] > 0) &&
			((mod == MOD_PLAGUEBOMB) || (mod == MOD_DRAIN) || (mod == MOD_SPORE))) {
			rsave += damage * 0.015 * targ->client->pers.skill[42] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		// Fire magic
		else if ((targ->client->pers.skill[43] > 0) &&
			((mod == MOD_INFERNO) || (mod == MOD_FIREBOLT) || (mod == MOD_FIREBALL) || (mod == MOD_CORPSEEXPLOSION))) {
			rsave += damage * 0.015 * targ->client->pers.skill[43] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		// Lightning magic
		else if ((targ->client->pers.skill[69] > 0) &&
			((mod == MOD_LIGHTNING) || (mod == MOD_SPARK) || (mod == MOD_BOLT))) {
			rsave += damage * 0.015 * targ->client->pers.skill[69] * res_boost;
			targ->client->magic -= RESBOOT_MAGUSE_MULT * ceil((pre_damage - damage) * res_boost);
		}
		if (rsave > 0) {
			//Anti-resist
			int arlvl = getAuraLevel(attacker, 84);
			if (arlvl > 0) {
				int slot = getAuraSlot(attacker, 84);
				if (attacker->client->aura_caster[slot]->client->magic > 0) {
					attacker->client->aura_caster[slot]->client->magic -= 0.1 * rsave;
					attacker->client->aura_caster[slot]->client->magregentime = level.time + 1.0;
					rsave *= 1 - (arlvl * 0.02);
				}
			}
			damage -= rsave;
			nosanc_damage -= rsave;
		}

		if (dflags & DAMAGE_10_MANABURN) // 10%
			manaburn_mult += 0.1;
		if (dflags & DAMAGE_25_MANABURN) // 25%
			manaburn_mult += 0.25;
		if (dflags & DAMAGE_50_MANABURN) // 50%
			manaburn_mult += 0.5;
		if (dflags & DAMAGE_100_MANABURN) // 100%
			manaburn_mult += 1.0;
		if (dflags & DAMAGE_200_MANABURN) // 200%
			manaburn_mult += 2.0;
		if (dflags & DAMAGE_400_MANABURN) // 400%
			manaburn_mult += 4.0;
		if (dflags & DAMAGE_50_MANALEECH) // 50%
			manaleech_mult += 0.5;
		if (dflags & DAMAGE_100_MANALEECH) // 100%
			manaleech_mult += 1.0;
		if (dflags & DAMAGE_200_MANALEECH) // 200%
			manaleech_mult += 2.0;

		if ((attacker->svflags & SVF_MONSTER) && (attacker->monsterinfo.ability & GIEX_MABILITY_MANABURN)) {
			manaburn_mult += 1.0;
		}

		if (manaburn_mult > 0.0) {
			targ->client->magic -= nosanc_damage * manaburn_mult;
			if (targ->client->magic < 0)
				targ->client->magic = 0;
			if ((attacker->client) && (attacker->client->magic < attacker->client->max_magic * 4)) {
				attacker->client->magic += nosanc_damage * manaburn_mult;
				if (attacker->client->magic > attacker->client->max_magic * 4) {
					attacker->client->magic = attacker->client->max_magic * 4;
				}
			}
			gi.WriteByte (svc_muzzleflash);
			gi.WriteShort (targ-g_edicts);
			gi.WriteByte (MZ_NUKE4);
			gi.multicast (targ->s.origin, MULTICAST_PVS);
		}
		if (manaleech_mult > 0.0) {
			if (attacker->client->magic < attacker->client->max_magic * 4) {
				attacker->client->magic += (int) ceil(nosanc_damage * manaleech_mult);
				if (attacker->client->magic > attacker->client->max_magic * 4) {
					attacker->client->magic = attacker->client->max_magic * 4;
				}
			}
			if (manaburn_mult == 0.0) {
				gi.WriteByte (svc_muzzleflash);
				gi.WriteShort (targ-g_edicts);
				gi.WriteByte (MZ_NUKE4);
				gi.multicast (targ->s.origin, MULTICAST_PVS);
			}
		}

		if ((pre_magic != targ->client->magic) && (targ->client->magregentime < level.time + 1.0)) {
			targ->client->magregentime = level.time + 1.0;
		}

		if (damage < 0) {
			damage = 0;
		}
	}

// figure momentum add
	if (!(dflags & DAMAGE_NO_KNOCKBACK)) {
		if ((knockback) && (targ->movetype != MOVETYPE_NONE) && (targ->movetype != MOVETYPE_BOUNCE) && (targ->movetype != MOVETYPE_PUSH) && (targ->movetype != MOVETYPE_STOP)) {
			vec3_t	kvel;
			float	mass;

			if (targ->mass < 50)
				mass = 50;
			else
				mass = targ->mass;

			if (targ->client  && attacker == targ)
				VectorScale (dir, 1600.0 * (float)knockback / mass, kvel);	// the rocket jump hack...
			else
				VectorScale (dir, 500.0 * (float)knockback / mass, kvel);

			VectorAdd (targ->velocity, kvel, targ->velocity);
		}
	}

	take = damage;
	save = 0;

	// check for godmode
	if ((targ->flags & FL_GODMODE) && !(dflags & DAMAGE_NO_PROTECTION) && (damage > 0)) {
		take = 0;
		save = damage;
		SpawnDamage (te_sparks, point, normal, save);
	}

	// check for invincibility
	if ((client && client->invincible_framenum > level.framenum ) && !(dflags & DAMAGE_NO_PROTECTION) && (damage > 0)) {
		if (targ->pain_debounce_time < level.time) {
			gi.sound(targ, CHAN_ITEM, gi.soundindex("items/protect4.wav"), 1, ATTN_NORM, 0);
			targ->pain_debounce_time = level.time + 2;
		}
		take = 0;
		save = damage;
	}

	if (take > 0) {
		if ((targ->client) && (targ->client->damage_time < level.time + 0.5 + take * 0.001)) {
			targ->client->damage_time = level.time + 0.5 + take * 0.001;
		}
		psave = CheckPowerArmor (targ, point, normal, take, dflags);
		take -= psave;

		asave = CheckArmor (targ, attacker, point, normal, take, te_sparks, dflags, mod, mod_magic);
		take -= asave;
	}

// do the damage
/*	if ((attacker->client) && (targ->svflags & SVF_MONSTER)) {
		if (take <= 0) {
			gi.dprintf("NO DAMAGE\n", take);
			_asm int 3;
		}
	}*/
	if (rsave > 0) {
		SpawnDamage (TE_SCREEN_SPARKS, point, normal, rsave);
	}
	if (sasave > 0) {
		SpawnDamage (TE_SHIELD_SPARKS, point, normal, sasave);
	}

	if ((take > 0) || ( (take < 0) && (targ->health < 2 * targ->max_health)) ) {
		targ->health -= take;
	}
	if ( (targ->health > 0) && ((take != 0) || (take + asave > 0)) ) {
		addExp(attacker, targ, take + asave); //Also give exp for killing armor
	}
	if (take != 0) {
		if ((targ->svflags & SVF_MONSTER) || (client))
			SpawnDamage (TE_BLOOD, point, normal, take);
		else
			SpawnDamage (te_sparks, point, normal, take);


		if ((attacker->client) && (mod != MOD_TELEFRAG)) /* && (targ->health > 0))*/ {
			if ((damage > 0) && (attacker->client->pers.skill[34] /*|| (attacker->client->pers.skills.classLevel[4] > 0)*/) && ((targ->health + take) > 0)) {
				int maxhealth = attacker->max_health * 0.75;
				maxhealth += 13.5 * pow(attacker->client->pers.skills.classLevel[4], 1.05);
				if (attacker->health < maxhealth) {
					float amount = 0;
					float mult = 0;

					//mult += 0.001 * pow(attacker->client->pers.skills.classLevel[4], 1.1); // Vampire class level bonus
					//mult *= 0.4 + 0.6 * ((float) attacker->client->pers.skills.classLevel[4] / (float) attacker->radius_dmg); // Penalty if not pure Vampire
					mult += 0.01 * attacker->client->pers.skill[34]; //From item powerups
					if (attacker->client->damage_time > level.time) {
						mult *= 0.25;
					}
					amount = take * mult;
					if ((mod == MOD_TELEFRAG) || (attacker == targ))
						amount = 0;
					attacker->client->pers.add_health += amount;
					if (attacker->health > maxhealth)
						attacker->health = maxhealth;
				}
			}
		}

		if (targ->health <= 0) {
			if ((targ->svflags & SVF_MONSTER) || (client))
				targ->flags |= FL_NO_KNOCKBACK;
			Killed (targ, inflictor, attacker, take, point);
			return take;
		}
	}

	if (take > 0) {
		if (targ->svflags & SVF_MONSTER) {
			edict_t *oldenemy = targ->enemy;
			if (targ->radius_dmg && (targ != attacker) && (attacker->takedamage) && (targ->monsterinfo.ability & GIEX_MABILITY_SHARDARMOR) && targ->monsterinfo.shardtime < (level.time - 0.1)) {
				vec3_t aim, end;
				float mult = level.time - targ->monsterinfo.shardtime;
				if (mult > 1.7)
					mult = 1.7;
				mult += 0.2;
				targ->monsterinfo.shardtime = level.time + 0.2;

				VectorMA(attacker->s.origin, 0.3, attacker->velocity, end);
				end[2] += attacker->viewheight;
				VectorSubtract (end, point, aim);

				if (targ->monsterinfo.ability & GIEX_MABILITY_DAMAGE) // Damage ability shouldn't affect Shard armor, halve mult
					mult *= 0.5;

				monster_fire_blaster (targ, point, aim, (int) ceil((16 + 10 * targ->monsterinfo.skill) * mult), 2200, MZ2_SOLDIER_BLASTER_1, EF_BLASTER);
				gi.sound(targ, CHAN_AUTO, gi.soundindex("giex/magarm2.wav"), 0.8, ATTN_NORM, 0);
			}
			M_ReactToDamage (targ, attacker);
			if (!(targ->monsterinfo.aiflags & AI_DUCKED) && (take)) {
				targ->pain_debounce_time = level.time + 2 + 0.1 * targ->monsterinfo.skill;
				if (oldenemy != NULL)
					targ->pain (targ, attacker, knockback, take);
			}
		} else if (client) {
			if (!(targ->flags & FL_GODMODE) && (take))
				targ->pain (targ, attacker, knockback, take);
		} else if (take) {
			if (targ->pain)
				targ->pain (targ, attacker, knockback, take);
		}
	}

	// add to the damage inflicted on a player this frame
	// the total will be turned into screen blends and view angle kicks
	// at the end of the frame
	if (client) {
		client->damage_parmor += psave;
		client->damage_armor += (asave + save);
		client->damage_blood += take;
		client->damage_knockback += knockback;
		VectorCopy (point, client->damage_from);
	}
	return take;
}