678 lines · 14.3 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <stdio.h>#include "../dat.h"#include "../fns.h" // defines #define DBALL_GOAL_TEAM1	0x0001#define DBALL_GOAL_TEAM2	0x0002 // globals edict_t *dball_ball_entity = NULL;int		dball_ball_startpt_count;int		dball_team1_goalscore;int		dball_team2_goalscore; cvar_t	*dball_team1_skin;cvar_t	*dball_team2_skin;cvar_t	*goallimit; // prototypes extern void EndDMLevel (void);extern void ClientUserinfoChanged (edict_t *ent, char *userinfo);extern void	SelectSpawnPoint (edict_t *ent, vec3_t origin, vec3_t angles);extern float PlayersRangeFromSpot (edict_t *spot); void DBall_BallDie (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);void DBall_BallRespawn (edict_t *self); // **************************// Game rules// ************************** int DBall_CheckDMRules (void){	if(goallimit && goallimit->value)	{		if(dball_team1_goalscore >= goallimit->value)			gi.bprintf (PRINT_HIGH, "Team 1 Wins.\n");		else if(dball_team2_goalscore >= goallimit->value)			gi.bprintf (PRINT_HIGH, "Team 2 Wins.\n");		else			return 0; 		EndDMLevel ();		return 1;	} 	return 0;} //==================//==================void DBall_ClientBegin (edict_t *ent){	int			team1, team2, unassigned;	edict_t		*other;	char		*p;	static char	value[512];	int			j; 	team1 = 0;	team2 = 0;	unassigned = 0; 	for (j = 1; j <= game.maxclients; j++)	{		other = &g_edicts[j];		if (!other->inuse)			continue;		if (!other->client)			continue;		if (other == ent)	// don't count the new player			continue;				strcpy(value, Info_ValueForKey (other->client->pers.userinfo, "skin"));		p = strchr(value, '/');		if (p)		{			if(!strcmp(dball_team1_skin->string, value))				team1++;			else if(!strcmp(dball_team2_skin->string, value))				team2++;			else				unassigned++;		}		else			unassigned++;	} 	if(team1 > team2)	{		gi.dprintf("assigned to team 2\n");		Info_SetValueForKey(ent->client->pers.userinfo, "skin", dball_team2_skin->string);	}	else	{		gi.dprintf("assigned to team 1\n");		Info_SetValueForKey(ent->client->pers.userinfo, "skin", dball_team1_skin->string);	}		ClientUserinfoChanged(ent, ent->client->pers.userinfo); 	if(unassigned)		gi.dprintf("%d unassigned players present!\n", unassigned);} //==================//==================void DBall_SelectSpawnPoint (edict_t *ent, vec3_t origin, vec3_t angles){	edict_t	*bestspot;	float	bestdistance, bestplayerdistance;	edict_t	*spot;	char	*spottype;	char	skin[512]; 	strcpy(skin, Info_ValueForKey (ent->client->pers.userinfo, "skin"));	if(!strcmp(dball_team1_skin->string, skin))		spottype = "dm_dball_team1_start";	else if(!strcmp(dball_team2_skin->string, skin))		spottype = "dm_dball_team2_start";	else		spottype = "info_player_deathmatch"; 	spot = NULL;	bestspot = NULL;	bestdistance = 0;	while ((spot = G_Find (spot, FOFS(classname), spottype)) != NULL)	{		bestplayerdistance = PlayersRangeFromSpot (spot); 		if (bestplayerdistance > bestdistance)		{			bestspot = spot;			bestdistance = bestplayerdistance;		}	} 	if (bestspot)	{		VectorCopy (bestspot->s.origin, origin);		origin[2] += 9;		VectorCopy (bestspot->s.angles, angles);		return;	} 	// if we didn't find an appropriate spawnpoint, just	// call the standard one.	SelectSpawnPoint(ent, origin, angles);} //==================//==================void DBall_GameInit (void){	// we don't want a minimum speed for friction to take effect.	// this will allow any knockback to move stuff.	sv_stopspeed->value = 0;	dball_team1_goalscore = 0;	dball_team2_goalscore = 0; 	dmflags->value = (int)dmflags->value | DF_NO_MINES | DF_NO_NUKES | DF_NO_STACK_DOUBLE | 						DF_NO_FRIENDLY_FIRE | DF_SKINTEAMS;		dball_team1_skin = gi.cvar ("dball_team1_skin", "male/ctf_r", 0);	dball_team2_skin = gi.cvar ("dball_team2_skin", "male/ctf_b", 0);	goallimit = gi.cvar ("goallimit", "0", 0);} //==================//==================void DBall_PostInitSetup (void){	edict_t		*e; 	e=NULL;	// turn teleporter destinations nonsolid.	while(e = G_Find (e, FOFS(classname), "misc_teleporter_dest"))	{		e->solid = SOLID_NOT;		gi.linkentity (e);	} 	// count the ball start points	dball_ball_startpt_count = 0;	e=NULL;	while(e = G_Find (e, FOFS(classname), "dm_dball_ball_start"))	{		dball_ball_startpt_count++;	} 	if(dball_ball_startpt_count == 0)		gi.dprintf("No Deathball start points!\n");} //==================// DBall_ChangeDamage - half damage between players. full if it involves//		the ball entity//==================int DBall_ChangeDamage (edict_t *targ, edict_t *attacker, int damage, int){	// cut player -> ball damage to 1	if (targ == dball_ball_entity)		return 1; 	// damage player -> player is halved	if (attacker != dball_ball_entity)		return damage / 2; 	return damage;} //==================//==================int DBall_ChangeKnockback (edict_t *targ, edict_t *, int knockback, int mod){	if(targ != dball_ball_entity)		return knockback;		if(knockback < 1)	{		// FIXME - these don't account for quad/double		if(mod == MOD_ROCKET)		// rocket			knockback = 70;		else if(mod == MOD_BFG_EFFECT)	// bfg			knockback = 90;		else	 		gi.dprintf ("zero knockback, mod %d\n", mod);	}	else	{		// FIXME - change this to an array?		switch(mod)		{			case MOD_BLASTER:				knockback *= 3;				break;			case MOD_SHOTGUN:				knockback = (knockback * 3) / 8;				break;			case MOD_SSHOTGUN:				knockback = knockback / 3;				break;			case MOD_MACHINEGUN:				knockback = (knockback * 3) / 2;				break;			case MOD_HYPERBLASTER:				knockback *= 4;				break;			case MOD_GRENADE:			case MOD_HANDGRENADE:			case MOD_PROX:			case MOD_G_SPLASH:			case MOD_HG_SPLASH:			case MOD_HELD_GRENADE:			case MOD_TRACKER:			case MOD_DISINTEGRATOR:				knockback /= 2;				break;			case MOD_R_SPLASH:				knockback = (knockback * 3) / 2;				break;			case MOD_RAILGUN:			case MOD_HEATBEAM:				knockback /= 3;				break;		}	} //	gi.dprintf("mod: %d    knockback: %d\n", mod, knockback);	return knockback;} // **************************// Goals// ************************** void DBall_GoalTouch (edict_t *self, edict_t *other, cplane_t *, csurface_t *){	int		team_score;	int		scorechange;	int		j;	char	value[512];	char	*p;	edict_t	*ent; 	if(other != dball_ball_entity)		return; 	self->health = self->max_health; 	// determine which team scored, and bump the team score	if(self->spawnflags & DBALL_GOAL_TEAM1)	{		dball_team1_goalscore += self->wait;				team_score = 1;	}	else	{		dball_team2_goalscore += self->wait;				team_score = 2;	} 	// bump the score for everyone on the correct team.	for (j = 1; j <= game.maxclients; j++)	{		ent = &g_edicts[j];		if (!ent->inuse)			continue;		if (!ent->client)			continue;				if (ent == other->enemy)			scorechange = self->wait + 5;		else			scorechange = self->wait; 		strcpy(value, Info_ValueForKey (ent->client->pers.userinfo, "skin"));		p = strchr(value, '/');		if (p)		{			if(!strcmp(dball_team1_skin->string, value))			{				if(team_score == 1)					ent->client->resp.score += scorechange;				else if(other->enemy == ent)					ent->client->resp.score -= scorechange;			}			else if(!strcmp(dball_team2_skin->string, value))			{				if(team_score == 2)					ent->client->resp.score += scorechange;				else if(other->enemy == ent)					ent->client->resp.score -= scorechange;			}			else				gi.dprintf("unassigned player!!!!\n");		}	} 	if(other->enemy)		gi.dprintf("score for team %d by %s\n", team_score, other->enemy->client->pers.netname);	else		gi.dprintf("score for team %d by someone\n", team_score); 	DBall_BallDie (other, other->enemy, other->enemy, 0, vec3_origin); 	G_UseTargets (self, other);} // **************************// Ball// ************************** edict_t *PickBallStart (edict_t *){	int		which, current;	edict_t	*e; 	which = ceil(qrandom() * dball_ball_startpt_count);	e = NULL;	current = 0; 	while(e = G_Find (e, FOFS(classname), "dm_dball_ball_start"))	{		current++;		if(current == which)			return e;	} 	if(current == 0)		gi.dprintf("No ball start points found!\n"); 	return G_Find(NULL, FOFS(classname), "dm_dball_ball_start");} //==================// DBall_BallTouch - if the ball hit another player, hurt them//==================void DBall_BallTouch (edict_t *ent, edict_t *other, cplane_t *, csurface_t *){	vec3_t	dir;	float	dot;	float	speed; 	if(other->takedamage == DAMAGE_NO)		return; 	// hit a player	if(other->client) 	{		if(ent->velocity[0] || ent->velocity[1] || ent->velocity[2])		{			speed = VectorLength(ent->velocity); 			VectorSubtract(ent->s.origin, other->s.origin, dir);			dot = DotProduct(dir, ent->velocity); 			if(dot > 0.7)			{				T_Damage (other, ent, ent, vec3_origin, ent->s.origin, vec3_origin, 						speed/10, speed/10, 0, MOD_DBALL_CRUSH);			}		}	}} //==================// DBall_BallPain//==================void DBall_BallPain (edict_t *self, edict_t *other, float, int){	self->enemy = other;	self->health = self->max_health;//	if(other->classname)//		gi.dprintf("hurt by %s -- %d\n", other->classname, self->health);} void DBall_BallDie (edict_t *self, edict_t *, edict_t *, int, vec3_t){	// do the splash effect	gi.WriteByte (svc_temp_entity);	gi.WriteByte (TE_DBALL_GOAL);	gi.WritePosition (self->s.origin);	gi.multicast (self->s.origin, MULTICAST_PVS); 	VectorClear(self->s.angles);	VectorClear(self->velocity);	VectorClear(self->avelocity); 	// make it invisible and desolid until respawn time	self->solid = SOLID_NOT;//	self->s.modelindex = 0;	self->think = DBall_BallRespawn;	self->nextthink = level.time + 2;	gi.linkentity(self); } void DBall_BallRespawn (edict_t *self){	edict_t		*start; 	// do the splash effect	gi.WriteByte (svc_temp_entity);	gi.WriteByte (TE_DBALL_GOAL);	gi.WritePosition (self->s.origin);	gi.multicast (self->s.origin, MULTICAST_PVS); 	// move the ball and stop it	start = PickBallStart(self);	if(start)	{		VectorCopy(start->s.origin, self->s.origin);		VectorCopy(start->s.origin, self->s.old_origin);	} 	VectorClear(self->s.angles);	VectorClear(self->velocity);	VectorClear(self->avelocity);		self->solid = SOLID_BBOX;	self->s.modelindex = gi.modelindex ("models/objects/dball/tris.md2");	self->s.event = EV_PLAYER_TELEPORT;	self->groundentity = NULL; 	// kill anything at the destination	KillBox (self); 	gi.linkentity (self);} // ************************// SPEED CHANGES// ************************ #define DBALL_SPEED_ONEWAY		1 void DBall_SpeedTouch (edict_t *self, edict_t *other, cplane_t *, csurface_t *){	float	dot;	vec3_t	vel; 	if(other != dball_ball_entity)		return; 	if(self->timestamp >= level.time)		return; 	if(VectorLength(other->velocity) < 1)		return; 	if(self->spawnflags & DBALL_SPEED_ONEWAY)	{		VectorCopy (other->velocity, vel);		VectorNormalize (vel);

Lines 1–500 of 678.

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