901 lines · 22.3 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <stdio.h>#include "../dat.h"#include "../fns.h"  /*=================check_dodge This is a support routine used when a client is firinga non-instant attack weapon.  It checks to see if amonster's dodge function should be called.=================*/static void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed){	vec3_t	end;	vec3_t	v;	trace_t	tr;	float	eta; 	// easy mode only ducks one quarter the time	if (skill->value == 0)	{		if (qrandom() > 0.25)			return;	}	VectorMA (start, 8192, dir, end);	tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT);	if ((tr.ent) && (tr.ent->svflags & SVF_MONSTER) && (tr.ent->health > 0) && (tr.ent->monsterinfo.dodge) && infront(tr.ent, self))	{		VectorSubtract (tr.endpos, start, v);		eta = (VectorLength(v) - tr.ent->maxs[0]) / speed;		tr.ent->monsterinfo.dodge (tr.ent, self, eta);	}}  /*=================fire_hit Used for all impact (hit/punch/slash) attacks=================*/qboolean fire_hit (edict_t *self, vec3_t aim, int damage, int kick){	trace_t		tr;	vec3_t		forward, right, up;	vec3_t		v;	vec3_t		point;	float		range;	vec3_t		dir; 	//see if enemy is in range	VectorSubtract (self->enemy->s.origin, self->s.origin, dir);	range = VectorLength(dir);	if (range > aim[0])		return false; 	if (aim[1] > self->mins[0] && aim[1] < self->maxs[0])	{		// the hit is straight on so back the range up to the edge of their bbox		range -= self->enemy->maxs[0];	}	else	{		// this is a side hit so adjust the "right" value out to the edge of their bbox		if (aim[1] < 0)			aim[1] = self->enemy->mins[0];		else			aim[1] = self->enemy->maxs[0];	} 	VectorMA (self->s.origin, range, dir, point); 	tr = gi.trace (self->s.origin, NULL, NULL, point, self, MASK_SHOT);	if (tr.fraction < 1)	{		if (!tr.ent->takedamage)			return false;		// if it will hit any client/monster then hit the one we wanted to hit		if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client))			tr.ent = self->enemy;	} 	AngleVectors(self->s.angles, forward, right, up);	VectorMA (self->s.origin, range, forward, point);	VectorMA (point, aim[1], right, point);	VectorMA (point, aim[2], up, point);	VectorSubtract (point, self->enemy->s.origin, dir); 	// do the damage	T_Damage (tr.ent, self, self, dir, point, vec3_origin, damage, kick/2, DAMAGE_NO_KNOCKBACK, MOD_HIT); 	if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))		return false; 	// do our special form of knockback here	VectorMA (self->enemy->absmin, 0.5, self->enemy->size, v);	VectorSubtract (v, point, v);	VectorNormalize (v);	VectorMA (self->enemy->velocity, kick, v, self->enemy->velocity);	if (self->enemy->velocity[2] > 0)		self->enemy->groundentity = NULL;	return true;}  /*=================fire_lead This is an internal support routine used for bullet/pellet based weapons.=================*/static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod){	trace_t		tr;	vec3_t		dir;	vec3_t		forward, right, up;	vec3_t		end;	float		r;	float		u;	vec3_t		water_start;	qboolean	water = false;	int			content_mask = MASK_SHOT | MASK_WATER; 	tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);	if (!(tr.fraction < 1.0))	{		vectoangles (aimdir, dir);		AngleVectors (dir, forward, right, up); 		r = crandom()*hspread;		u = crandom()*vspread;		VectorMA (start, 8192, forward, end);		VectorMA (end, r, right, end);		VectorMA (end, u, up, end); 		if (gi.pointcontents (start) & MASK_WATER)		{			water = true;			VectorCopy (start, water_start);			content_mask &= ~MASK_WATER;		} 		tr = gi.trace (start, NULL, NULL, end, self, content_mask); 		// see if we hit water		if (tr.contents & MASK_WATER)		{			int		color; 			water = true;			VectorCopy (tr.endpos, water_start); 			if (!VectorCompare (start, tr.endpos))			{				if (tr.contents & CONTENTS_WATER)				{					if (strcmp(tr.surface->name, "*brwater") == 0)						color = SPLASH_BROWN_WATER;					else						color = SPLASH_BLUE_WATER;				}				else if (tr.contents & CONTENTS_SLIME)					color = SPLASH_SLIME;				else if (tr.contents & CONTENTS_LAVA)					color = SPLASH_LAVA;				else					color = SPLASH_UNKNOWN; 				if (color != SPLASH_UNKNOWN)				{					gi.WriteByte (svc_temp_entity);					gi.WriteByte (TE_SPLASH);					gi.WriteByte (8);					gi.WritePosition (tr.endpos);					gi.WriteDir (tr.plane.normal);					gi.WriteByte (color);					gi.multicast (tr.endpos, MULTICAST_PVS);				} 				// change bullet's course when it enters water				VectorSubtract (end, start, dir);				vectoangles (dir, dir);				AngleVectors (dir, forward, right, up);				r = crandom()*hspread*2;				u = crandom()*vspread*2;				VectorMA (water_start, 8192, forward, end);				VectorMA (end, r, right, end);				VectorMA (end, u, up, end);			} 			// re-trace ignoring water this time			tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);		}	} 	// send gun puff / flash	if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))	{		if (tr.fraction < 1.0)		{			if (tr.ent->takedamage)			{				T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod);			}			else			{				if (strncmp (tr.surface->name, "sky", 3) != 0)				{					gi.WriteByte (svc_temp_entity);					gi.WriteByte (te_impact);					gi.WritePosition (tr.endpos);					gi.WriteDir (tr.plane.normal);					gi.multicast (tr.endpos, MULTICAST_PVS); 					if (self->client)						PlayerNoise(self, tr.endpos, PNOISE_IMPACT);				}			}		}	} 	// if went through water, determine where the end and make a bubble trail	if (water)	{		vec3_t	pos; 		VectorSubtract (tr.endpos, water_start, dir);		VectorNormalize (dir);		VectorMA (tr.endpos, -2, dir, pos);		if (gi.pointcontents (pos) & MASK_WATER)			VectorCopy (pos, tr.endpos);		else			tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER); 		VectorAdd (water_start, tr.endpos, pos);		VectorScale (pos, 0.5, pos); 		gi.WriteByte (svc_temp_entity);		gi.WriteByte (TE_BUBBLETRAIL);		gi.WritePosition (water_start);		gi.WritePosition (tr.endpos);		gi.multicast (pos, MULTICAST_PVS);	}}  /*=================fire_bullet Fires a single round.  Used for machinegun and chaingun.  Would be fine forpistols, rifles, etc....=================*/void fire_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod){	fire_lead (self, start, aimdir, damage, kick, TE_GUNSHOT, hspread, vspread, mod);}  /*=================fire_shotgun Shoots shotgun pellets.  Used by shotgun and super shotgun.=================*/void fire_shotgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod){	int		i; 	for (i = 0; i < count; i++)		fire_lead (self, start, aimdir, damage, kick, TE_SHOTGUN, hspread, vspread, mod);}  /*=================fire_blaster Fires a single blaster bolt.  Used by the blaster and hyper blaster.=================*/void blaster_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf){	int		mod; 	if (other == self->owner)		return; 	if (surf && (surf->flags & SURF_SKY))	{		G_FreeEdict (self);		return;	} 	if (self->owner->client)		PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); 	if (other->takedamage)	{		if (self->spawnflags & 1)			mod = MOD_HYPERBLASTER;		else			mod = MOD_BLASTER;		T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod);	}	else	{		gi.WriteByte (svc_temp_entity);		gi.WriteByte (TE_BLASTER);		gi.WritePosition (self->s.origin);		if (!plane)			gi.WriteDir (vec3_origin);		else			gi.WriteDir (plane->normal);		gi.multicast (self->s.origin, MULTICAST_PVS);	} 	G_FreeEdict (self);} void fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, qboolean hyper){	edict_t	*bolt;	trace_t	tr; 	VectorNormalize (dir); 	bolt = G_Spawn();	bolt->svflags = SVF_DEADMONSTER;	// yes, I know it looks weird that projectiles are deadmonsters	// what this means is that when prediction is used against the object	// (blaster/hyperblaster shots), the player won't be solid clipped against	// the object.  Right now trying to run into a firing hyperblaster	// is very jerky since you are predicted 'against' the shots.	VectorCopy (start, bolt->s.origin);	VectorCopy (start, bolt->s.old_origin);	vectoangles (dir, bolt->s.angles);	VectorScale (dir, speed, bolt->velocity);	bolt->movetype = MOVETYPE_FLYMISSILE;	bolt->clipmask = MASK_SHOT;	bolt->solid = SOLID_BBOX;	bolt->s.effects |= effect;	VectorClear (bolt->mins);	VectorClear (bolt->maxs);	bolt->s.modelindex = gi.modelindex ("models/objects/laser/tris.md2");	bolt->s.sound = gi.soundindex ("misc/lasfly.wav");	bolt->owner = self;	bolt->touch = blaster_touch;	bolt->nextthink = level.time + 2;	bolt->think = G_FreeEdict;	bolt->dmg = damage;	bolt->classname = "bolt";	if (hyper)		bolt->spawnflags = 1;	gi.linkentity (bolt); 	if (self->client)		check_dodge (self, bolt->s.origin, dir, speed); 	tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT);	if (tr.fraction < 1.0)	{		VectorMA (bolt->s.origin, -10, dir, bolt->s.origin);		bolt->touch (bolt, tr.ent, NULL, NULL);	}}	  /*=================fire_grenade=================*/static void Grenade_Explode (edict_t *ent){	vec3_t		origin;	int			mod; 	if (ent->owner->client)		PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); 	//FIXME: if we are onground then raise our Z just a bit since we are a point?	if (ent->enemy)	{		float	points;		vec3_t	v;		vec3_t	dir; 		VectorAdd (ent->enemy->mins, ent->enemy->maxs, v);		VectorMA (ent->enemy->s.origin, 0.5, v, v);		VectorSubtract (ent->s.origin, v, v);		points = ent->dmg - 0.5 * VectorLength (v);		VectorSubtract (ent->enemy->s.origin, ent->s.origin, dir);		if (ent->spawnflags & 1)			mod = MOD_HANDGRENADE;		else			mod = MOD_GRENADE;		T_Damage (ent->enemy, ent, ent->owner, dir, ent->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod);	} 	if (ent->spawnflags & 2)		mod = MOD_HELD_GRENADE;	else if (ent->spawnflags & 1)		mod = MOD_HG_SPLASH;	else		mod = MOD_G_SPLASH;	T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod); 	VectorMA (ent->s.origin, -0.02, ent->velocity, origin);	gi.WriteByte (svc_temp_entity);	if (ent->waterlevel)	{		if (ent->groundentity)			gi.WriteByte (TE_GRENADE_EXPLOSION_WATER);		else			gi.WriteByte (TE_ROCKET_EXPLOSION_WATER);	}	else	{		if (ent->groundentity)			gi.WriteByte (TE_GRENADE_EXPLOSION);		else			gi.WriteByte (TE_ROCKET_EXPLOSION);	}	gi.WritePosition (origin);	gi.multicast (ent->s.origin, MULTICAST_PHS); 	G_FreeEdict (ent);} static void Grenade_Touch (edict_t *ent, edict_t *other, cplane_t */*plane*/, csurface_t *surf){	if (other == ent->owner)		return; 	if (surf && (surf->flags & SURF_SKY))	{		G_FreeEdict (ent);		return;	} 	if (!other->takedamage)	{		if (ent->spawnflags & 1)		{			if (qrandom() > 0.5)				gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0);			else				gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0);		}		else		{			gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/grenlb1b.wav"), 1, ATTN_NORM, 0);		}		return;	} 	ent->enemy = other;	Grenade_Explode (ent);} void fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius){	edict_t	*grenade;	vec3_t	dir;	vec3_t	forward, right, up; 	vectoangles (aimdir, dir);	AngleVectors (dir, forward, right, up); 	grenade = G_Spawn();	VectorCopy (start, grenade->s.origin);	VectorScale (aimdir, speed, grenade->velocity);	VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity);	VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity);	VectorSet (grenade->avelocity, 300, 300, 300);	grenade->movetype = MOVETYPE_BOUNCE;	grenade->clipmask = MASK_SHOT;	grenade->solid = SOLID_BBOX;	grenade->s.effects |= EF_GRENADE;	VectorClear (grenade->mins);	VectorClear (grenade->maxs);	grenade->s.modelindex = gi.modelindex ("models/objects/grenade/tris.md2");	grenade->owner = self;	grenade->touch = Grenade_Touch;	grenade->nextthink = level.time + timer;	grenade->think = Grenade_Explode;	grenade->dmg = damage;	grenade->dmg_radius = damage_radius;	grenade->classname = "grenade"; 

Lines 1–500 of 901.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t