Пример #1
0
Файл: eavy.c Проект: qbism/tmg
void EAVYSetupFlagSpots(void)
{
    edict_t *ent, *spot;

    spot = G_Find (NULL, FOFS(classname), "misc_ctf_small_banner");
    if (!spot && ctf->value)
    {
        ent = G_Find (NULL, FOFS(classname), "info_player_team1");
        spot = G_Find (NULL, FOFS(classname), "info_player_team2");
        if (!ent && !spot)
        {
            ent = G_Find (NULL, FOFS(classname), "item_flag_team1");
            spot = G_Spawn ();
            spot->classname = "misc_ctf_small_banner";
            spot->spawnflags = 0;
            VectorCopy (ent->s.origin, spot->s.origin);
            ED_CallSpawn (spot);
            EAVYSpawnTeamNearFlag (ent);

            ent = G_Find (NULL, FOFS(classname), "item_flag_team2");
            spot = G_Spawn ();
            spot->classname = "misc_ctf_small_banner";
            spot->spawnflags = 1;
            VectorCopy (ent->s.origin, spot->s.origin);
            ED_CallSpawn (spot);
            EAVYSpawnTeamNearFlag (ent);



            EAVYSpawnTeamNearFlagCheck();
        }
    }
}
Пример #2
0
Файл: eavy.c Проект: qbism/tmg
void EAVYSpawnFlags(void)
{
    edict_t *redflag, *blueflag;

    redflag = G_Find (NULL, FOFS(classname), "item_flag_team1");
    blueflag = G_Find (NULL, FOFS(classname), "item_flag_team2");

    if (ctf->value && !redflag)
    {
        redflag = G_Find (NULL, FOFS(classname), "info_player_deathmatch");
        redflag = EAVYFindFarthestFlagPosition(redflag);
        if (!redflag)
            redflag = G_Find (NULL, FOFS(classname), "info_player_start");
        if (redflag)
        {
            redflag->classname = "item_flag_team1";
            ED_CallSpawn (redflag);
        }
    }

    if (redflag && !blueflag)
    {
        blueflag = EAVYFindFarthestFlagPosition(redflag);
        if (blueflag)
        {
            blueflag->classname = "item_flag_team2";
            ED_CallSpawn (blueflag);
        }
    }

    if (ctf->value && !blueflag)
        gi.dprintf ("EAVY.EAVYSpawnFlags = FAILED!\n");

}
Пример #3
0
/*
void medic_dodge (edict_t *self, edict_t *attacker, float eta, trace_t *tr)
{

	if (random() > 0.25)
		return;

	if (!self->enemy)
		self->enemy = attacker;

	self->monsterinfo.currentmove = &medic_move_duck;

//===========
//PMM - rogue rewrite of dodge code.
	float	r;
	float	height;
	int		shooting = 0;

	// this needs to be before the AI_MEDIC check, because
	//   a) if AI_MEDIC is set, we should have an enemy anyway and
	//   b) FoundTarget calls medic_run, which can set AI_MEDIC
	if (!self->enemy)
	{
		self->enemy = attacker;
		FoundTarget (self);
	}

//	don't dodge if you're healing
	if (self->monsterinfo.aiflags & AI_MEDIC)
		return;

	// PMM - don't bother if it's going to hit anyway; fix for weird in-your-face etas (I was
	// seeing numbers like 13 and 14)
	if ((eta < 0.1) || (eta > 5))
		return;

	r = random();
	if (r > (0.25*((skill->value)+1)))
		return;

	if ((self->monsterinfo.currentmove == &medic_move_attackHyperBlaster) ||
		(self->monsterinfo.currentmove == &medic_move_attackCable) ||
		(self->monsterinfo.currentmove == &medic_move_attackBlaster))
	{
		shooting = 1;
	}
	if (self->monsterinfo.aiflags & AI_DODGING)
	{
		height = self->absmax[2];
	}
	else
	{
		height = self->absmax[2]-32-1;  // the -1 is because the absmax is s.origin + maxs + 1
	}

	// check to see if it makes sense to duck
	if (tr->endpos[2] <= height)
	{
		vec3_t right, diff;
		if (shooting)
		{
			self->monsterinfo.attack_state = AS_SLIDING;
			return;
		}
		AngleVectors (self->s.angles, NULL, right, NULL);
		VectorSubtract (tr->endpos, self->s.origin, diff);
		if (DotProduct (right, diff) < 0)
		{
			self->monsterinfo.lefty = 1;
		}
		// if it doesn't sense to duck, try to strafe away
		monster_done_dodge (self);
		self->monsterinfo.currentmove = &medic_move_run;
		self->monsterinfo.attack_state = AS_SLIDING;
		return;
	}

	if (skill->value == 0)
	{
		self->monsterinfo.currentmove = &medic_move_duck;
		// PMM - stupid dodge
		self->monsterinfo.duck_wait_time = level.time + eta + 1;
		self->monsterinfo.aiflags |= AI_DODGING;
		return;
	}

	if (!shooting)
	{
		self->monsterinfo.currentmove = &medic_move_duck;
		self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
		self->monsterinfo.aiflags |= AI_DODGING;
	}
	return;

//PMM
//===========

}
*/
void MedicCommanderCache (void)
{
	edict_t	*newEnt;
	int	modelidx;
	int i;

	//FIXME - better way to do this?  this is quick and dirty
	for (i=0; i < 7; i++)
	{
		newEnt = G_Spawn();

		VectorCopy(vec3_origin, newEnt->s.origin);
		VectorCopy(vec3_origin, newEnt->s.angles);
		newEnt->classname = ED_NewString (reinforcements[i]);
		
		newEnt->monsterinfo.aiflags |= AI_DO_NOT_COUNT;

		ED_CallSpawn(newEnt);
		// FIXME - could copy mins/maxs into reinforcements from here
		G_FreeEdict (newEnt);
	}

	modelidx = gi.modelindex("models/items/spawngro/tris.md2");
	modelidx = gi.modelindex("models/items/spawngro2/tris.md2");
}
Пример #4
0
int LoadFlagsFromFile (char *mapname)
{
	FILE *fp;
	char buf[1024], *s;
//	int len;
	int i;
	edict_t *ent;
	vec3_t position;

	sprintf (buf, "%s/tng/%s.flg", GAMEVERSION, mapname);
	fp = fopen (buf, "r");
	if (!fp)
	{
		gi.dprintf ("Warning: No flag definition file for map %s.\n", mapname);
		return 0;
	}

	// FIXME: remove this functionality completely in the future
	gi.dprintf ("Warning: .flg files are deprecated, use .ctf ones for more control!\n");

	i = 0;
	while (fgets(buf, 1000, fp) != NULL)
	{
		//first remove trailing spaces
		s = buf+strlen(buf)-1;
		for (; *s && (*s == '\r' || *s == '\n' || *s == ' '); s--)
			*s = '\0';

		//check if it's a valid line
		if (strlen(buf) >= 5 && strncmp(buf, "#", 1) && strncmp(buf, "//", 2) && i < 2)
		{
			//a little bit dirty... :)
			if (sscanf(buf, "<%f %f %f>", &position[0], &position[1], &position[2]) != 3)
				continue;

			ent = G_Spawn ();

			ent->spawnflags &=
				~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD |
				SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH);

			VectorCopy(position, ent->s.origin);

			if (!i)	// Red Flag
				ent->classname = ED_NewString ("item_flag_team1");
			else	// Blue Flag
				ent->classname = ED_NewString ("item_flag_team2");

			ED_CallSpawn (ent);
			i++;
		}
	}

	fclose (fp);

	if(i < 2)
		return (0);

	return (1);
}
Пример #5
0
static void G_ParseString(void)
{
    const char  *entities = level.entstring;
    edict_t     *ent;
    int         inhibit = 0;
    char        *token;

// parse ents
    while (1) {
        // parse the opening brace
        token = COM_Parse(&entities);
        if (!entities)
            break;
        if (token[0] != '{')
            gi.error("%s: found %s when expecting {", __func__, token);

        ent = G_Spawn();
        ED_ParseEdict(&entities, ent);

        // remove things from different skill levels or deathmatch
        if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) {
            G_FreeEdict(ent);
            inhibit++;
            continue;
        }

        ent->spawnflags &= ~INHIBIT_MASK;

        ED_CallSpawn(ent);
    }

    gi.dprintf("%i entities inhibited\n", inhibit);

}
Пример #6
0
edict_t *
DoRandomRespawn(edict_t *ent)
{
	edict_t *newEnt;
	char *classname;

	if (!ent)
	{
		return NULL;
	}

	classname = FindSubstituteItem(ent);

	if (classname == NULL)
	{
		return NULL;
	}

	gi.unlinkentity(ent);

	newEnt = G_Spawn();
	newEnt->classname = classname;
	VectorCopy(ent->s.origin, newEnt->s.origin);
	VectorCopy(ent->s.old_origin, newEnt->s.old_origin);
	VectorCopy(ent->mins, newEnt->mins);
	VectorCopy(ent->maxs, newEnt->maxs);

	VectorSet(newEnt->gravityVector, 0, 0, -1);

	ED_CallSpawn(newEnt);

	newEnt->s.renderfx |= RF_IR_VISIBLE;

	return newEnt;
}
void Pet_Create (edict_t *ent, char * szClass, const char * name)
{
	edict_t * pet;
	vec3_t	offset;
	vec3_t	forward, right;
	vec3_t	start;

	if (ent->svflags & SVF_NOCLIENT)
		return;
	if (ent->client->PetStrength > petquota->value + 200 * deathmatch->value)
		return;
	if (ent->client->PetCount > petquota->value/50)
		return;


	pet = G_Spawn();
	pet->classname = szClass;
	pet->monsterinfo.PetOwner = ent;
	pet->monsterinfo.TargetCounter = 0;
	pet->monsterinfo.PetState = PET_DEFAULT;
	strcpy(pet->monsterinfo.name, name);

	VectorSet(offset, 40, 40, ent->viewheight-8);
	AngleVectors (ent->client->v_angle, forward, right, NULL);
	P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
	
	
	pet->spawnflags = 69;
	VectorCopy(start, pet->s.origin);
	VectorCopy(ent->s.angles, pet->s.angles);
	ED_CallSpawn(pet);


	// copied from KillBox
	{
		trace_t		tr;
		// unlink to make sure it can't possibly interfere with KillBox
		gi.unlinkentity (pet);
		tr = gi.trace (pet->s.origin, pet->mins, pet->maxs, pet->s.origin, NULL, MASK_PLAYERSOLID);
		if (tr.fraction < 1.0)
		{
			G_FreeEdict(pet);
			return;
		}
		gi.linkentity (pet);
	}

	if (!strcmp(szClass, "monster_decoy"))
	{
		//Use same model and skin as the person creating decoy
		pet->model = ent->model;
		pet->s.skinnum = ent->s.skinnum;
		pet->s.modelindex = ent->s.modelindex;
		pet->s.modelindex2 = ent->s.modelindex;
	}

	ent->client->PetCount++;
	ent->client->PetStrength += pet->max_health;
}
Пример #8
0
Файл: eavy.c Проект: qbism/tmg
void EAVYSpawnTeamNearFlagCheck(void)
{
    edict_t *flag, *spot = NULL;
    float   dist;
    vec3_t  v;

    flag = G_Find (NULL, FOFS(classname), "item_flag_team1");
    while(spot = G_Find (spot, FOFS(classname), "info_player_team2"))
    {
        VectorSubtract (spot->s.origin, flag->s.origin, v);
        dist = VectorLength (v);
        if (EAVY_RESTRICTED_RADIUS > dist)
        {
            spot->classname = "info_player_deathmatch";
            spot->svflags &= ~SVF_NOCLIENT;
            spot->s.effects &= ~EF_COLOR_SHELL;
            spot->s.renderfx &= ~RF_SHELL_BLUE;
            ED_CallSpawn (spot);

        }
    }
    flag = G_Find (NULL, FOFS(classname), "item_flag_team2");
    while(spot = G_Find (spot, FOFS(classname), "info_player_team1"))
    {
        VectorSubtract (spot->s.origin, flag->s.origin, v);
        dist = VectorLength (v);
        if (EAVY_RESTRICTED_RADIUS > dist)
        {
            spot->classname = "info_player_deathmatch";
            spot->svflags &= ~SVF_NOCLIENT;
            spot->s.effects &= ~EF_COLOR_SHELL;
            spot->s.renderfx &= ~RF_SHELL_RED;
            ED_CallSpawn (spot);

        }
    }
}
Пример #9
0
void use_target_spawner (edict_t *self, edict_t *other, edict_t *activator)
{
	edict_t	*ent;

	ent = G_Spawn();
	ent->classname = self->target;
	VectorCopy (self->s.origin, ent->s.origin);
	VectorCopy (self->s.angles, ent->s.angles);
	ED_CallSpawn (ent);
	gi.unlinkentity (ent);
	KillBox (ent);
	gi.linkentity (ent);
	if (self->speed)
		VectorCopy (self->movedir, ent->velocity);
}
Пример #10
0
qboolean SpawnZ(gitem_t *item, edict_t *spot)
{
	edict_t	*ent;
	vec3_t	forward;
	vec3_t  angles;
	vec3_t start;
	vec3_t end;
	trace_t tr;
	int ang = 0;
	int startAng = 0;

	ent = G_Spawn();

	ent->classname = item->classname;
	VectorSet (ent->mins, -15, -15, -15);
	VectorSet (ent->maxs, 15, 15, 15);
	ent->solid = SOLID_TRIGGER;
	ent->movetype = MOVETYPE_BOUNCE;
	ED_CallSpawn(ent);

	startAng = rand() % 360;
	VectorCopy(spot->s.origin, start);
	start[2] += 16;

	for (ang = startAng; ang < startAng + 360; ang += 15)
	{
		angles[0] = 0;
		angles[1] = ang;
		angles[2] = 0;

		AngleVectors (angles, forward, NULL, NULL);
		VectorMA(start, 128, forward, end);

		tr = gi.trace(start, ent->mins, ent->maxs, end, NULL, MASK_SHOT);
		if (tr.fraction < 1.0)
			continue;

		VectorCopy(end, ent->s.origin);
		gi.linkentity(ent);
		return true;
	}
	G_FreeEdict(ent);
	return false;
}
Пример #11
0
Файл: eavy.c Проект: qbism/tmg
void EAVYSpawnTeamNearFlag(edict_t *flag)
{
    edict_t *spot = NULL;
    float   dist;
    vec3_t  v;

    while(spot = G_Find (spot, FOFS(classname), "info_player_deathmatch"))
    {
        VectorSubtract (spot->s.origin, flag->s.origin, v);
        dist = VectorLength (v);
        if (EAVY_RESTRICTED_RADIUS > dist)
        {
            if (!strcmp(flag->classname, "item_flag_team1"))
                spot->classname = "info_player_team1";
            if (!strcmp(flag->classname, "item_flag_team2"))
                spot->classname = "info_player_team2";
            spot->svflags |= SVF_NOCLIENT;
            spot->solid = SOLID_NOT;
            ED_CallSpawn (spot);
        }
    }
}
Пример #12
0
// Lazarus: Rocket_Evade tells monsters to get da hell outta da way
void Rocket_Evade (edict_t *rocket, vec3_t	dir, float speed)
{
	float	rocket_dist, best_r, best_yaw, dist, r;
	float	time;
	float	dot;
	float	yaw;
	int		i;
	edict_t	*ent=NULL;
	trace_t	tr;
	vec3_t	hitpoint;
	vec3_t	forward, pos, best_pos;
	vec3_t	rocket_vec, vec;

	// Find out what rocket will hit, assuming everything remains static
	VectorMA(rocket->s.origin,8192,dir,rocket_vec);
	tr = gi.trace(rocket->s.origin,rocket->mins,rocket->maxs,rocket_vec,rocket,MASK_SHOT);
	VectorCopy(tr.endpos,hitpoint);
	VectorSubtract(hitpoint,rocket->s.origin,vec);
	dist = VectorLength(vec);
	time = dist / speed;

	while ((ent = findradius(ent, hitpoint, rocket->dmg_radius)) != NULL)
	{
		if (!ent->inuse)
			continue;
		if (!(ent->svflags & SVF_MONSTER))
			continue;
		if (!ent->takedamage)
			continue;
		if (ent->health <= 0)
			continue;
		if (!ent->monsterinfo.run)	// takes care of turret_driver
			continue;
		if (rocket->owner == ent)
			continue;

		VectorSubtract(hitpoint,ent->s.origin,rocket_vec);
		rocket_dist = VectorNormalize(rocket_vec);

		// Not much hope in evading if distance is < 1K or so.
		if(rocket_dist < 1024)
			continue;

		// Find best escape route.
		best_r = 9999;
		for(i=0; i<8; i++)
		{
			yaw = anglemod( i*45 );
			forward[0] = cos( DEG2RAD(yaw) );
			forward[1] = sin( DEG2RAD(yaw) );
			forward[2] = 0;
			dot = DotProduct(forward,dir);
			if((dot > 0.96) || (dot < -0.96))
				continue;
			// Estimate of required distance to run. This is conservative.
			r = rocket->dmg_radius + rocket_dist*DotProduct(forward,rocket_vec) + ent->size[0] + 16;
			if( r < best_r )
			{
				VectorMA(ent->s.origin,r,forward,pos);
				tr = gi.trace(ent->s.origin,ent->mins,ent->maxs,pos,ent,MASK_MONSTERSOLID);
				if(tr.fraction < 1.0)
					continue;
				best_r = r;
				best_yaw = yaw;
				VectorCopy(tr.endpos,best_pos);
			}
		}
		if(best_r < 9000)
		{
			edict_t	*thing = SpawnThing();
			VectorCopy(best_pos,thing->s.origin);
			thing->touch_debounce_time = level.time + time;
			thing->target_ent = ent;
			ED_CallSpawn(thing);
			ent->ideal_yaw  = best_yaw;
			ent->movetarget = ent->goalentity = thing;
			ent->monsterinfo.aiflags &= ~AI_SOUND_TARGET;
			ent->monsterinfo.aiflags |= (AI_CHASE_THING | AI_EVADE_GRENADE);
			ent->monsterinfo.run(ent);
		}
	}
}
Пример #13
0
/*
==============
SpawnEntities

Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
==============
*/
void SpawnEntities (char *mapname, char *entities, char *spawnpoint)
{
	edict_t		*ent;
	int			inhibit;
	char		*com_token;
	int			i;
	float		skill_level;

	skill_level = floor (skill->value);
	if (skill_level < 0)
		skill_level = 0;
	if (skill_level > 3)
		skill_level = 3;
	if (skill->value != skill_level)
		gi.cvar_forceset("skill", va("%f", skill_level));

	SaveClientData ();

	gi.FreeTags (TAG_LEVEL);

	memset (&level, 0, sizeof(level));
	memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0]));

	strncpy (level.mapname, mapname, sizeof(level.mapname)-1);
	strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1);

	// set client fields on player ents
	for (i=0 ; i<game.maxclients ; i++)
		g_edicts[i+1].client = game.clients + i;

	ent = NULL;
	inhibit = 0;

// parse ents
	while (1)
	{
		// parse the opening brace	
		com_token = COM_Parse (&entities);
		if (!entities)
			break;
		if (com_token[0] != '{')
			gi.error ("ED_LoadFromFile: found %s when expecting {",com_token);

		if (!ent)
			ent = g_edicts;
		else
			ent = G_Spawn ();
		entities = ED_ParseEdict (entities, ent);

		// yet another map hack
		if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27"))
			ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;

		// remove things (except the world) from different skill levels or deathmatch
		if (ent != g_edicts)
		{
			if (deathmatch->value)
			{
				if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH )
				{
					G_FreeEdict (ent);	
					inhibit++;
					continue;
				}
			}
			else
			{
				if ( /* ((coop->value) && (ent->spawnflags & SPAWNFLAG_NOT_COOP)) || */
					((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
					((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
					(((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))
					)
					{
						G_FreeEdict (ent);	
						inhibit++;
						continue;
					}
			}

			ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH);
		}

		ED_CallSpawn (ent);
	}	

	gi.dprintf ("%i entities inhibited\n", inhibit);

#ifdef DEBUG
	i = 1;
	ent = EDICT_NUM(i);
	while (i < globals.num_edicts) {
		if (ent->inuse != 0 || ent->inuse != 1)
			Com_DPrintf("Invalid entity %d\n", i);
		i++, ent++;
	}
#endif

	G_FindTeams ();

	PlayerTrail_Init ();
}
Пример #14
0
/*
==============
SpawnEntities

Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
==============
*/
void SpawnEntities (char *mapname, char *entities, char *spawnpoint)
{
	edict_t *ent = NULL;
	int inhibit = 0;
	char *com_token;
	int i;
	float skill_level;
	//AQ2:TNG New Location Code
	char locfile[MAX_QPATH], line[256];
	FILE *f;
	int readmore, x, y, z, rx, ry, rz, count;
	char *locationstr, *param;
	cvar_t *game_cvar;
	int u;
	//    placedata_t temp;


	// Reset teamplay stuff
	for(i = TEAM1; i < TEAM_TOP; i++)
	{
		teams[i].score = teams[i].total = 0;
		teams[i].ready = teams[i].locked = 0;
		teams[i].pauses_used = teams[i].wantReset = 0;
		gi.cvar_forceset(teams[i].teamscore->name, "0");
	}

	matchtime = 0;
	day_cycle_at = 0;
	team_round_going = team_game_going = team_round_countdown = 0;
	lights_camera_action = holding_on_tie_check = 0;
	timewarning = fragwarning = 0;

	teamCount = 2;

	if (ctf->value)
	{
		// Make sure teamplay is enabled
		if (!teamplay->value)
		{
			gi.dprintf ("CTF Enabled - Forcing teamplay on\n");
			gi.cvar_forceset(teamplay->name, "1");
		}
		if (use_3teams->value)
		{
			gi.dprintf ("CTF Enabled - Forcing 3Teams off\n");
			gi.cvar_forceset(use_3teams->name, "0");
		}
		if(teamdm->value)
		{
			gi.dprintf ("CTF Enabled - Forcing Team DM off\n");
			gi.cvar_forceset(teamdm->name, "0");
		}
		if (use_tourney->value)
		{
			gi.dprintf ("CTF Enabled - Forcing Tourney off\n");
			gi.cvar_forceset(use_tourney->name, "0");
		}
		if (!((int) (dmflags->value) & DF_NO_FRIENDLY_FIRE))
		{
			gi.dprintf ("CTF Enabled - Forcing Friendly Fire off\n");
			gi.cvar_forceset(dmflags->name, va("%i", (int)dmflags->value | DF_NO_FRIENDLY_FIRE));
		}
		strcpy(teams[TEAM1].name, "RED");
		strcpy(teams[TEAM2].name, "BLUE");
		strcpy(teams[TEAM1].skin, "male/ctf_r");
		strcpy(teams[TEAM2].skin, "male/ctf_b");
		strcpy(teams[TEAM1].skin_index, "../players/male/ctf_r_i");
		strcpy(teams[TEAM2].skin_index, "../players/male/ctf_b_i");
		if(ctf->value == 2)
			gi.cvar_forceset(ctf->name, "1"); //for now
	}
	else if(teamdm->value)
	{
		if (!teamplay->value)
		{
			gi.dprintf ("Team Deathmatch Enabled - Forcing teamplay on\n");
			gi.cvar_forceset(teamplay->name, "1");
		}
		if (use_3teams->value)
		{
			gi.dprintf ("Team Deathmatch Enabled - Forcing 3Teams off\n");
			gi.cvar_forceset(use_3teams->name, "0");
		}
		if (use_tourney->value)
		{
			gi.dprintf ("Team Deathmatch Enabled - Forcing Tourney off\n");
			gi.cvar_forceset(use_tourney->name, "0");
		}
	}
	else if (use_3teams->value)
	{
		teamCount = 3;
		if (!teamplay->value)
		{
			gi.dprintf ("3 Teams Enabled - Forcing teamplay on\n");
			gi.cvar_forceset(teamplay->name, "1");
		}
		if (use_tourney->value)
		{
			gi.dprintf ("3 Teams Enabled - Forcing Tourney off\n");
			gi.cvar_forceset(use_tourney->name, "0");
		}
		if (!use_oldspawns->value)
		{
			gi.dprintf ("3 Teams Enabled - Forcing use_oldspawns on\n");
			gi.cvar_forceset(use_oldspawns->name, "1");
		}
	}
	else if (matchmode->value)
	{
		if (!teamplay->value)
		{
			gi.dprintf ("Matchmode Enabled - Forcing teamplay on\n");
			gi.cvar_forceset(teamplay->name, "1");
		}
		if (use_tourney->value)
		{
			gi.dprintf ("Matchmode Enabled - Forcing Tourney off\n");
			gi.cvar_forceset(use_tourney->name, "0");
		}
	}
	else if (use_tourney->value)
	{
		if (!teamplay->value)
		{
			gi.dprintf ("Tourney Enabled - Forcing teamplay on\n");
			gi.cvar_forceset(teamplay->name, "1");
		}
	}

	skill_level = floor (skill->value);
	if (skill_level < 0)
		skill_level = 0;
	if (skill_level > 3)
		skill_level = 3;
	if (skill->value != skill_level)
		gi.cvar_forceset ("skill", va("%f", skill_level));

	SaveClientData ();

	gi.FreeTags (TAG_LEVEL);

	memset (&level, 0, sizeof (level));
	memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0]));

	Q_strncpyz(level.mapname, mapname, sizeof(level.mapname));
	Q_strncpyz(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint));

	// set client fields on player ents
	for (i = 0; i < game.maxclients; i++)
		g_edicts[i + 1].client = game.clients + i;

	// parse ents
	while (1)
	{
		// parse the opening brace      
		com_token = COM_Parse (&entities);
		if (!entities)
			break;

		if (com_token[0] != '{')
			gi.error ("ED_LoadFromFile: found %s when expecting {", com_token);

		if (!ent)
			ent = g_edicts;
		else
			ent = G_Spawn ();
		entities = ED_ParseEdict (entities, ent);

		// yet another map hack
		if (!Q_stricmp (level.mapname, "command")
			&& !Q_stricmp (ent->classname, "trigger_once")
			&& !Q_stricmp (ent->model, "*27"))
			ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;

		// remove things (except the world) from different skill levels or deathmatch
		if (ent != g_edicts)
		{
			if (deathmatch->value)
			{
				if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH)
				{
					G_FreeEdict (ent);
					inhibit++;
					continue;
				}
			}
			else
			{
				if (		/* ((coop->value) && (ent->spawnflags & SPAWNFLAG_NOT_COOP)) || */
					((skill->value == 0)
					&& (ent->spawnflags & SPAWNFLAG_NOT_EASY))
					|| ((skill->value == 1)
					&& (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM))
					|| (((skill->value == 2) || (skill->value == 3))
					&& (ent->spawnflags & SPAWNFLAG_NOT_HARD)))
					{
					G_FreeEdict (ent);
					inhibit++;
					continue;
				}
			}
			ent->spawnflags &=
			~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD |
			SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH);
		}

		ED_CallSpawn (ent);
	}

	gi.dprintf ("%i entities inhibited\n", inhibit);

	// AQ2:TNG Igor adding .flg files

	// CTF configuration
	if(ctf->value)
	{
		if(!CTFLoadConfig(level.mapname))
		{
			if ((!G_Find(NULL, FOFS (classname), "item_flag_team1") ||
				 !G_Find(NULL, FOFS (classname), "item_flag_team2")))
			{
				gi.dprintf ("No native CTF map, loading flag positions from file\n");
				if (LoadFlagsFromFile (level.mapname))
					ChangePlayerSpawns ();
			}
		}
	}
	
	// AQ2:TNG End adding .flg files

	G_FindTeams ();

	PlayerTrail_Init ();

	// TNG:Freud - Ghosts
	num_ghost_players = 0;

	//FIREBLADE
	if (!teamplay->value || teamdm->value || ctf->value == 2)
	{
		//FIREBLADE
		//zucc for special items
		SetupSpecSpawn ();
	}
	else if (teamplay->value)
	{
		GetSpawnPoints ();
		//TNG:Freud - New spawning system
		if(!use_oldspawns->value)
			NS_GetSpawnPoints();
	}

	//AQ2:TNG Slicer - New location  code
	memset (ml_build, 0, sizeof (ml_build));
	memset (ml_creator, 0, sizeof (ml_creator));


	game_cvar = gi.cvar ("game", "", 0);

	if (!*game_cvar->string)
		Com_sprintf(locfile, sizeof(locfile), "%s/tng/%s.aqg", GAMEVERSION, level.mapname);
	else
		Com_sprintf(locfile, sizeof(locfile), "%s/tng/%s.aqg", game_cvar->string, level.mapname);

	f = fopen (locfile, "rt");
	if (!f)
	{
		ml_count = 0;
		gi.dprintf ("No location file for %s\n", level.mapname);
		return;
	}

	gi.dprintf ("Location file: %s\n", level.mapname);

	readmore = 1;
	count = 0;

	while (readmore)
	{
		readmore = (fgets (line, 256, f) != NULL);
		param = strtok (line, " :\r\n\0");
		if (line[0] == '#' && line[2] == 'C')
		{
			u = 0;
			for (i = 10; line[i] != '\n'; i++)
			{
				if (line[i] == '\r') continue;
					ml_creator[u] = line[i];
				u++;
			}
		}
		if (line[0] == '#' && line[2] == 'B')
		{
			u = 0;
			for (i = 8; line[i] != '\n'; i++)
			{
				if (line[i] != ' ' && line[i] != '\r')
				{
					ml_build[u] = line[i];
					u++;
				}
			}
		}
		ml_build[5] = 0;
		ml_creator[100] = 0;

		// TODO: better support for file comments
		if (!param || param[0] == '#')
			continue;

		x = atoi (param);

		param = strtok (NULL, " :\r\n\0");
		if (!param)
			continue;
		y = atoi (param);

		param = strtok (NULL, " :\r\n\0");
		if (!param)
			continue;
		z = atoi (param);

		param = strtok (NULL, " :\r\n\0");
		if (!param)
			continue;
		rx = atoi (param);

		param = strtok (NULL, " :\r\n\0");
		if (!param)
			continue;
		ry = atoi (param);

		param = strtok (NULL, " :\r\n\0");
		if (!param)
			continue;
		rz = atoi (param);

		param = strtok (NULL, "\r\n\0");
		if (!param)
			continue;
		locationstr = param;

		locationbase[count].x = x;
		locationbase[count].y = y;
		locationbase[count].z = z;
		locationbase[count].rx = rx;
		locationbase[count].ry = ry;
		locationbase[count].rz = rz;
		Q_strncpyz (locationbase[count].desc, locationstr, sizeof(locationbase[count].desc));

		count++;

		if (count >= MAX_LOCATIONS_IN_BASE)
		{
			gi.dprintf ("Cannot read more than %d locations.\n", MAX_LOCATIONS_IN_BASE);
			break;
		}
	}

	ml_count = count;
	fclose (f);
	gi.dprintf ("Found %d locations.\n", count);

}
Пример #15
0
void Grenade_Evade (edict_t *monster)
{
	edict_t	*grenade;
	vec3_t	grenade_vec;
	float	grenade_dist, best_r, best_yaw, r;
	float	yaw;
	int		i;
	vec3_t	forward;
	vec3_t	pos, best_pos;
	trace_t	tr;

	// We assume on entry here that monster is alive and that he's not already
	// AI_CHASE_THING
	grenade = world->next_grenade;
	while(grenade)
	{
		// we only care about grenades on the ground
		if(grenade->inuse && grenade->groundentity)
		{
			// if it ain't in the PVS, it can't hurt us (I think?)
			if(gi.inPVS(grenade->s.origin,monster->s.origin))
			{
				VectorSubtract(grenade->s.origin,monster->s.origin,grenade_vec);
				grenade_dist = VectorNormalize(grenade_vec);
				if(grenade_dist <= grenade->dmg_radius)
					break;
			}
		}
		grenade = grenade->next_grenade;
	}
	if(!grenade)
		return;
	// Find best escape route.
	best_r = 9999;
	for(i=0; i<8; i++)
	{
		yaw = anglemod( i*45 );
		forward[0] = cos( DEG2RAD(yaw) );
		forward[1] = sin( DEG2RAD(yaw) );
		forward[2] = 0;
		// Estimate of required distance to run. This is conservative.
		r = grenade->dmg_radius + grenade_dist*DotProduct(forward,grenade_vec) + monster->size[0] + 16;
		if( r < best_r )
		{
			VectorMA(monster->s.origin,r,forward,pos);
			tr = gi.trace(monster->s.origin,monster->mins,monster->maxs,pos,monster,MASK_MONSTERSOLID);
			if(tr.fraction < 1.0)
				continue;
			best_r = r;
			best_yaw = yaw;
			VectorCopy(tr.endpos,best_pos);
		}
	}
	if(best_r < 9000)
	{
		edict_t	*thing = SpawnThing();
		VectorCopy(best_pos,thing->s.origin);
		thing->touch_debounce_time = grenade->nextthink;
		thing->target_ent = monster;
		ED_CallSpawn(thing);
		monster->ideal_yaw  = best_yaw;
		monster->movetarget = monster->goalentity = thing;
		monster->monsterinfo.aiflags &= ~AI_SOUND_TARGET;
		monster->monsterinfo.aiflags |= (AI_CHASE_THING | AI_EVADE_GRENADE);
		monster->monsterinfo.run(monster);
		monster->next_grenade = grenade;
	}
}
Пример #16
0
void
medic_cable_attack(edict_t *self)
{
	vec3_t offset, start, end, f, r;
	trace_t tr;
	vec3_t dir, angles;
	float distance;

	if (!self)
	{
		return;
	}

	if (!self->enemy->inuse)
	{
		return;
	}

	AngleVectors(self->s.angles, f, r, NULL);
	VectorCopy(medic_cable_offsets[self->s.frame - FRAME_attack42], offset);
	G_ProjectSource(self->s.origin, offset, f, r, start);

	/* check for max distance */
	VectorSubtract(start, self->enemy->s.origin, dir);
	distance = VectorLength(dir);

	if (distance > 256)
	{
		return;
	}

	/* check for min/max pitch */
	vectoangles(dir, angles);

	if (angles[0] < -180)
	{
		angles[0] += 360;
	}

	if (fabs(angles[0]) > 45)
	{
		return;
	}

	tr = gi.trace(start, NULL, NULL, self->enemy->s.origin, self, MASK_SHOT);

	if ((tr.fraction != 1.0) && (tr.ent != self->enemy))
	{
		return;
	}

	if (self->s.frame == FRAME_attack43)
	{
		gi.sound(self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
	}
	else if (self->s.frame == FRAME_attack50)
	{
		self->enemy->spawnflags = 0;
		self->enemy->monsterinfo.aiflags = 0;
		self->enemy->target = NULL;
		self->enemy->targetname = NULL;
		self->enemy->combattarget = NULL;
		self->enemy->deathtarget = NULL;
		self->enemy->owner = self;
		ED_CallSpawn(self->enemy);
		self->enemy->owner = NULL;

		if (self->enemy->think)
		{
			self->enemy->nextthink = level.time;
			self->enemy->think(self->enemy);
		}

		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;

		if (self->oldenemy && self->oldenemy->client)
		{
			self->enemy->enemy = self->oldenemy;
			FoundTarget(self->enemy);
		}
	}
	else
	{
		if (self->s.frame == FRAME_attack44)
		{
			gi.sound(self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
		}
	}

	/* adjust start for beam origin being in middle of a segment */
	VectorMA(start, 8, f, start);

	/* adjust end z for end spot since the monster is currently dead */
	VectorCopy(self->enemy->s.origin, end);
	end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2;

	gi.WriteByte(svc_temp_entity);
	gi.WriteByte(TE_MEDIC_CABLE_ATTACK);
	gi.WriteShort(self - g_edicts);
	gi.WritePosition(start);
	gi.WritePosition(end);
	gi.multicast(self->s.origin, MULTICAST_PVS);
}
Пример #17
0
/*
==============
SpawnEntities

Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
==============
*/
void SpawnEntities (const char *mapname, char *entities, const char *spawnpoint)
{
	edict_t		*ent;
	int			inhibit;
	const char	*com_token;
	int			i;
	float		skill_level;
	int oldmaxent;

	skill_level = floor (skill->value);
	if (skill_level < 0)
		skill_level = 0;
	if (skill_level > 3)
		skill_level = 3;
	if (skill->value != skill_level)
		gi.cvar_forceset("skill", va("%f", skill_level));

	SaveClientData ();

	gi.FreeTags (TAG_LEVEL);

	memset (&level, 0, sizeof(level));
	memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0]));

	strncpy (level.mapname, mapname, sizeof(level.mapname)-1);
	strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1);

	// set client fields on player ents
	for (i=0 ; i<game.maxclients ; i++)
		g_edicts[i+1].client = game.clients + i;

	ent = NULL;
	inhibit = 0;

	// parse ents
	while (1)
	{
		// parse the opening brace	
		com_token = COM_Parse (&entities);
		if (!entities)
			break;
		if (com_token[0] != '{')
			gi.error ("ED_LoadFromFile: found %s when expecting {",com_token);

		if (!ent)
			ent = g_edicts;
		else
			ent = G_Spawn ();
		ent->spawnflags2 = 0;
		entities = ED_ParseEdict (entities, ent);

		// yet another map hack
		if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27"))
			ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;

		// remove things (except the world) from different skill levels or deathmatch
		if (ent != g_edicts)
		{
			if (deathmatch->value)
			{
				if ( (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) || (ent->spawnflags2 & SPAWNFLAG2_NOT_SINGLE) )
				{
					G_FreeEdict (ent);	
					inhibit++;
					continue;
				}
			}
#if 0 // FIXME: DG: coop stuff from rogue
			else if (coop->value)
			{
				if (ent->spawnflags & SPAWNFLAG_NOT_COOP)
				{
					G_FreeEdict(ent);
					inhibit++;
					continue;
				}

				/* stuff marked !easy & !med & !hard are coop only, all levels */
				if (!((ent->spawnflags & SPAWNFLAG_NOT_EASY) &&
					  (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM) &&
					  (ent->spawnflags & SPAWNFLAG_NOT_HARD)))
				{
					if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
						((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
						(((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)))
					{
						G_FreeEdict(ent);
						inhibit++;
						continue;
					}
				}
			}
#endif // 0
			else
			{
				if (((!coop->value) && (ent->spawnflags2 & SPAWNFLAG2_NOT_SINGLE)) ||
						((coop->value) && (ent->spawnflags2 & SPAWNFLAG2_NOT_COOP)) ||
					((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
					((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
					(((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))
					)
					{
						G_FreeEdict (ent);	
						inhibit++;
						continue;
					}
			}

			ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH);
		}

		ED_CallSpawn (ent);
	}	

	oldmaxent = globals.num_edicts;

	gi.dprintf("%i entities created\n", globals.num_edicts);
	gi.dprintf ("%i entities inhibited\n", inhibit);

	G_FindTeams ();

	PlayerTrail_Init ();

	Z_SpawnDMItems();
}
Пример #18
0
void medic_cable_attack (edict_t *self)
{
	vec3_t	offset, start, end, f, r;
	trace_t	tr;
	vec3_t	dir;
//	vec3_t  angles;
	float	distance;

	if ((!self->enemy) || (!self->enemy->inuse) || (self->enemy->s.effects & EF_GIB))
	{
//		if ((g_showlogic) && (g_showlogic->value))
//			gi.dprintf ("medic_commander - aborting heal due to target's disappearance\n");
		abortHeal (self, true, false, false);
		return;
	}

	// see if our enemy has changed to a client, or our target has more than 0 health,
	// abort it .. we got switched to someone else due to damage
	if ((self->enemy->client) || (self->enemy->health > 0))
	{
		abortHeal (self, true, false, false);
		return;
	}
	AngleVectors (self->s.angles, f, r, NULL);
	VectorCopy (medic_cable_offsets[self->s.frame - FRAME_attack42], offset);
	G_ProjectSource (self->s.origin, offset, f, r, start);

	// check for max distance
	// not needed, done in checkattack
	// check for min distance
	VectorSubtract (start, self->enemy->s.origin, dir);
	distance = VectorLength(dir);
	if (distance < MEDIC_MIN_DISTANCE)
	{
//		if ((g_showlogic) && (g_showlogic->value))
//			gi.dprintf ("medic_commander - aborting heal due to proximity to target ");
		abortHeal (self, true, true, false );
		return;
	}
//	if ((g_showlogic)&&(g_showlogic->value))
//		gi.dprintf ("distance to target is %f\n", distance);
//	if (distance > 300)
//		return;

	// check for min/max pitch
	// PMM -- took out since it doesn't look bad when it fails
//	vectoangles (dir, angles);
//	if (angles[0] < -180)
//		angles[0] += 360;
//	if (fabs(angles[0]) > 45)
//	{
//		if ((g_showlogic) && (g_showlogic->value))
//			gi.dprintf ("medic_commander - aborting heal due to bad angle\n");
//		abortHeal(self);
//		return;
//	}

	tr = gi.trace (start, NULL, NULL, self->enemy->s.origin, self, MASK_SOLID);
	if (tr.fraction != 1.0 && tr.ent != self->enemy)
	{
		if (tr.ent == world)
		{
			// give up on second try
			if (self->monsterinfo.medicTries > 1)
			{
				abortHeal (self, true, false, true);
				return;
			}
			self->monsterinfo.medicTries++;
			cleanupHeal (self, 1);
			return;
		}
//		if ((g_showlogic) && (g_showlogic->value))
//			gi.dprintf ("medic_commander - aborting heal due to beamus interruptus\n");
		abortHeal (self, true, false, false);
		return;
	}

	if (self->s.frame == FRAME_attack43)
	{
		// PMM - commander sounds
		if (self->mass == 400)
			gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
		else
			gi.sound (self->enemy, CHAN_AUTO, commander_sound_hook_hit, 1, ATTN_NORM, 0);

		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
		self->enemy->takedamage = DAMAGE_NO;
		M_SetEffects (self->enemy);
	}
	else if (self->s.frame == FRAME_attack50)
	{
		vec3_t	maxs;
		self->enemy->spawnflags = 0;
		self->enemy->monsterinfo.aiflags = 0;
		self->enemy->target = NULL;
		self->enemy->targetname = NULL;
		self->enemy->combattarget = NULL;
		self->enemy->deathtarget = NULL;
		self->enemy->monsterinfo.healer = self;

		VectorCopy (self->enemy->maxs, maxs);
		maxs[2] += 48;   // compensate for change when they die

		tr = gi.trace (self->enemy->s.origin, self->enemy->mins, maxs, self->enemy->s.origin, self->enemy, MASK_MONSTERSOLID);
		if (tr.startsolid || tr.allsolid)
		{
//			if ((g_showlogic) && (g_showlogic->value))
//				gi.dprintf ("Spawn point obstructed, aborting heal!\n");
			abortHeal (self, true, true, false);
			return;
		} 
		else if (tr.ent != world)
		{
//			if ((g_showlogic) && (g_showlogic->value))
//				gi.dprintf("heal in entity %s\n", tr.ent->classname);
			abortHeal (self, true, true, false);
			return;
		}
/*		else if (tr.ent == world)
		{
			if ((g_showlogic) && (g_showlogic->value))
				gi.dprintf ("heal in world, aborting!\n");
			abortHeal (self, 1);
			return;
		}
*/		else
		{
			self->enemy->monsterinfo.aiflags |= AI_DO_NOT_COUNT;
			ED_CallSpawn (self->enemy);

			if (self->enemy->think)
			{
				self->enemy->nextthink = level.time;
				self->enemy->think (self->enemy);
			}
	//		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
			self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING;
			self->enemy->monsterinfo.aiflags |= AI_IGNORE_SHOTS|AI_DO_NOT_COUNT;
			// turn off flies
			self->enemy->s.effects &= ~EF_FLIES;
			self->enemy->monsterinfo.healer = NULL;

			if ((self->oldenemy) && (self->oldenemy->inuse) && (self->oldenemy->health > 0))
			{
//				if ((g_showlogic) && (g_showlogic->value))
//					gi.dprintf ("setting heal target's enemy to %s\n", self->oldenemy->classname);
				self->enemy->enemy = self->oldenemy;
//				HuntTarget (self->enemy);
				FoundTarget (self->enemy);
			}
			else
			{
//				if (g_showlogic && g_showlogic->value)
//					gi.dprintf ("no valid enemy to set!\n");
				self->enemy->enemy = NULL;
				if (!FindTarget (self->enemy))
				{
					// no valid enemy, so stop acting
					self->enemy->monsterinfo.pausetime = level.time + 100000000;
					self->enemy->monsterinfo.stand (self->enemy);
				}
				self->enemy = NULL;
				self->oldenemy = NULL;
				if (!FindTarget (self))
				{
					// no valid enemy, so stop acting
					self->monsterinfo.pausetime = level.time + 100000000;
					self->monsterinfo.stand (self);
					return;
				}
			}
		}
	}
	else
	{
		if (self->s.frame == FRAME_attack44)
			// PMM - medic commander sounds
			if (self->mass == 400)
				gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
			else
				gi.sound (self, CHAN_WEAPON, commander_sound_hook_heal, 1, ATTN_NORM, 0);
	}

	// adjust start for beam origin being in middle of a segment
	VectorMA (start, 8, f, start);

	// adjust end z for end spot since the monster is currently dead
	VectorCopy (self->enemy->s.origin, end);
	end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2;

	gi.WriteByte (svc_temp_entity);
	gi.WriteByte (TE_MEDIC_CABLE_ATTACK);
	gi.WriteShort (self - g_edicts);
	gi.WritePosition (start);
	gi.WritePosition (end);
	gi.multicast (self->s.origin, MULTICAST_PVS);
}
Пример #19
0
void medic_cable_attack (edict_t *self)
{
	vec3_t	offset, start, end, f, r;
	trace_t	tr;
	vec3_t	dir;
	float	distance;

	if ((!self->enemy) || (!self->enemy->inuse) || (self->enemy->svflags & SVF_GIB))
	{
		//gi.dprintf ("medic_cable_attack: aborting heal due to target being removed or gibbed\n");
		abortHeal (self,false);
		return;
	}

	//Knightmare- don't heal insanes or actors or critters
	if (!strcmp (self->enemy->classname, "misc_insane") || !strcmp (self->enemy->classname, "misc_actor")
		|| !strcmp (self->enemy->classname, "monster_mutant") || !strcmp (self->enemy->classname, "monster_flipper")) 
	{
		//gi.dprintf ("medic_cable_attack: not healing insane or actor or critter\n");
		abortHeal (self, true);
		return;
	}

	// Lazarus: check embeddment
	if (embedded(self->enemy))
	{
		//gi.dprintf ("medic_cable_attack: dead monster embedded in solid, aborting heal\n");
		abortHeal (self,false);
		return;
	}

	// see if our enemy has changed to a client, or our target has more than 0 health,
	// abort it .. we got switched to someone else due to damage
	if ((self->enemy->client) || (self->enemy->health > 0))
	{
		//gi.dprintf ("medic_cable_attack: aborting heal due to target health > 0 or client\n");
		abortHeal (self,false);
		return;
	}

	AngleVectors (self->s.angles, f, r, NULL);
	VectorCopy (medic_cable_offsets[self->s.frame - FRAME_attack42], offset);
	G_ProjectSource (self->s.origin, offset, f, r, start);

	// check for max distance
	// Lazarus: Not needed, done in checkattack
	// check for min distance
	VectorSubtract (self->enemy->s.origin, start, dir);
	distance = VectorLength(dir);
	if (distance < MEDIC_MIN_DISTANCE)
	{
		//gi.dprintf("medic_cable_attack: MEDIC_MIN_DISTANCE\n");
		abortHeal (self,false);
		return;
	}

	// Lazarus: Check for enemy behind muzzle... don't do these guys, 'cause usually this
	// results in monster entanglement
	VectorNormalize(dir);
	if(DotProduct(dir,f) < 0.)
	{
		//gi.dprintf ("medic_cable_attack: aborting heal due to possible entanglment\n");
		abortHeal (self,false);
		return;
	}

	// check for min/max pitch
	// Rogue takes this out... makes medic more likely to heal and 
	// comments say "doesn't look bad when it fails"... we'll see
/*	vectoangles (dir, angles);
	if (angles[0] < -180)
		angles[0] += 360;
	if (fabs(angles[0]) > 45)
		return; */

	tr = gi.trace (start, NULL, NULL, self->enemy->s.origin, self, MASK_SHOT);
	if (tr.fraction != 1.0 && tr.ent != self->enemy)
	{
		if (tr.ent == world)
		{
			// give up on second try
			if (self->monsterinfo.medicTries > 1)
			{
				abortHeal (self,true);
				return;
			}
			self->monsterinfo.medicTries++;
			cleanupHeal (self, 1);
			return;
		}
		abortHeal (self,false);
		return;
	}

	if (self->s.frame == FRAME_attack43)
	{
		gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
		M_SetEffects(self->enemy);
	}
	else if (self->s.frame == FRAME_attack50)
	{
		self->enemy->spawnflags &= SF_MONSTER_NOGIB;
		self->enemy->monsterinfo.aiflags = 0;
		self->enemy->target = NULL;
		self->enemy->targetname = NULL;
		self->enemy->combattarget = NULL;
		self->enemy->deathtarget = NULL;
		self->enemy->owner = self;
		// Lazarus: reset initially dead monsters to use the INVERSE of their
		// initial health, and force gib_health to default value
		if(self->enemy->max_health < 0)
		{
			self->enemy->max_health = -self->enemy->max_health;
			self->enemy->gib_health = 0;
		}
		self->enemy->health = self->enemy->max_health;
		self->enemy->takedamage = DAMAGE_AIM;
		self->enemy->flags &= ~FL_NO_KNOCKBACK;
		self->enemy->pain_debounce_time = 0;
		self->enemy->damage_debounce_time = 0;
		self->enemy->deadflag = DEAD_NO;
		if(self->enemy->s.effects & EF_FLIES)
			M_FliesOff(self->enemy);
		ED_CallSpawn (self->enemy);
		self->enemy->monsterinfo.healer = NULL;
		self->enemy->owner = NULL;

		// Knightmare- disable deadmonster_think
		if (self->enemy->postthink)
			self->enemy->postthink = NULL;

		if (self->enemy->think)
		{
			self->enemy->nextthink = level.time;
			self->enemy->think (self->enemy);
		}
		self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING;
		M_SetEffects(self->enemy);
		if (self->oldenemy && self->oldenemy->client)
		{
			self->enemy->enemy = self->oldenemy;
			FoundTarget (self->enemy);
		}
		else
		{
			// Lazarus: this should make oblivious monsters 
			// find player again
			self->enemy->enemy = NULL;
		}
	}
	else
	{
		if (self->s.frame == FRAME_attack44)
			gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
	}

	// adjust start for beam origin being in middle of a segment
	// Lazarus: This isn't right... this causes cable start point to be well above muzzle
	//          when target is closeby. f should be vector from muzzle to target, not
	//          the forward viewing direction. PLUS... 8 isn't right... the model is
	//          actually 32 units long, so use 16.. fixed below.
//	VectorMA (start, 8, f, start);

	//Knightmare- if enemy went away, like after returning from another level, return
	if (!self->enemy)
		return;

	// adjust end z for end spot since the monster is currently dead
	VectorCopy (self->enemy->s.origin, end);
	end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2;

	// Lazarus fix
	VectorSubtract(end,start,f);
	VectorNormalize(f);
	VectorMA(start,16,f,start);

	gi.WriteByte (svc_temp_entity);
	gi.WriteByte (TE_MEDIC_CABLE_ATTACK);
	gi.WriteShort (self - g_edicts);
	gi.WritePosition (start);
	gi.WritePosition (end);
	gi.multicast (self->s.origin, MULTICAST_PVS);
}
Пример #20
0
void LoadTransitionEnts()
{
	if(developer->value)
		gi.dprintf("==== LoadTransitionEnts ====\n");
	if(game.transition_ents)
	{
		char		t_file[_MAX_PATH];
		int			i, j;
		FILE		*f;
		vec3_t		v_spawn;
		edict_t		*ent;
		edict_t		*spawn;
		
		VectorClear(v_spawn);
		if(strlen(game.spawnpoint))
		{
			spawn = G_Find(NULL,FOFS(targetname),game.spawnpoint);
			while(spawn)
			{
				if(!Q_stricmp(spawn->classname,"info_player_start"))
				{
					VectorCopy(spawn->s.origin,v_spawn);
					break;
				}
				spawn = G_Find(spawn,FOFS(targetname),game.spawnpoint);
			}
		}
		trans_ent_filename (t_file);
		f = fopen(t_file,"rb");
		if(!f)
			gi.error("LoadTransitionEnts: Cannot open %s\n",t_file);
		else
		{
			for(i=0; i<game.transition_ents; i++)
			{
				ent = G_Spawn();
				ReadEdict(f,ent);
				// Correction for monsters with health EXACTLY 0
				// If we don't do this, spawn function will bring
				// 'em back to life
				if(ent->svflags & SVF_MONSTER)
				{
					if(!ent->health)
					{
						ent->health = -1;
						ent->deadflag = DEAD_DEAD;
					}
					else if(ent->deadflag == DEAD_DEAD)
					{
						ent->health = min(ent->health,-1);
					}
				}
				VectorAdd(ent->s.origin,v_spawn,ent->s.origin);
				VectorCopy(ent->s.origin,ent->s.old_origin);
				ED_CallSpawn (ent);
				if(ent->owner_id)
				{
					if(ent->owner_id < 0)
					{
						ent->owner = &g_edicts[-ent->owner_id];
					}
					else
					{
						// We KNOW owners precede owned ents in the 
						// list because of the way it was constructed
						ent->owner = NULL;
						for(j=game.maxclients+1; j<globals.num_edicts && !ent->owner; j++)
						{
							if(ent->owner_id == g_edicts[j].id)
								ent->owner = &g_edicts[j];
						}
					}
					ent->owner_id = 0;
				}
				ent->s.renderfx |= RF_IR_VISIBLE;
			}
			fclose(f);
		}
	}
}
Пример #21
0
/*
==============
SpawnEntities

Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
==============
*/
void G_SpawnEntities(const char *mapname, const char *entities, const char *spawnpoint)
{
    edict_t     *ent;
    gclient_t   *client;
    int         i;
    client_persistant_t pers;
    char        *token;
    char        playerskin[MAX_QPATH];

#if USE_SQLITE
    G_OpenDatabase();
    G_LogClients();
#endif

    gi.FreeTags(TAG_LEVEL);

    memset(&level, 0, sizeof(level));
    memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0]));

    Q_strlcpy(level.mapname, mapname, sizeof(level.mapname));

    G_LoadScores();

    // set client fields on player ents
    for (i = 0; i < game.maxclients; i++) {
        ent = &g_edicts[i + 1];
        client = &game.clients[i];
        ent->client = client;
        ent->inuse = qfalse;

        if (!client->pers.connected) {
            continue;
        }

        // clear everything but the persistant data
        pers = client->pers;
        memset(client, 0, sizeof(*client));
        client->pers = pers;
        client->edict = ent;
        client->clientNum = i;
        client->pers.connected = CONN_CONNECTED;

        // combine name and skin into a configstring
        Q_concat(playerskin, sizeof(playerskin),
                 client->pers.netname, "\\", client->pers.skin, NULL);
        gi.configstring(CS_PLAYERSKINS + i, playerskin);
        gi.configstring(CS_PLAYERNAMES + i, client->pers.netname);
    }

    // parse worldspawn
    token = COM_Parse(&entities);
    if (!entities)
        gi.error("%s: empty entity string", __func__);
    if (token[0] != '{')
        gi.error("%s: found %s when expecting {", __func__, token);

    ent = g_edicts;
    ED_ParseEdict(&entities, ent);

    ED_CallSpawn(ent);

    level.entstring = entities;

    G_ParseString();
    G_FindTeams();
    //G_UpdateItemBans();

    // find spawnpoints
    ent = NULL;
    while ((ent = G_Find(ent, FOFS(classname), "info_player_deathmatch")) != NULL) {
        level.spawns[level.numspawns++] = ent;
        if (level.numspawns == MAX_SPAWNS) {
            break;
        }
    }
    gi.dprintf("%d spawn points\n", level.numspawns);
}
Пример #22
0
/*
==============
SpawnEntities

Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
==============
*/
void SpawnEntities (char *mapname, char *entities, char *spawnpoint)
{
	edict_t		*ent;
	int			inhibit;
	char		*com_token;
	int			i;
	float		skill_level;
	extern int	max_modelindex;
	extern int	max_soundindex;
	extern int	lastgibframe;

	if (developer->value)
		gi.dprintf("====== SpawnEntities ========\n");
	skill_level = floor (skill->value);
	if (skill_level < 0)
		skill_level = 0;
	if (skill_level > 3)
		skill_level = 3;
	if (skill->value != skill_level)
		gi.cvar_forceset("skill", va("%f", skill_level));

	SaveClientData ();

	gi.FreeTags (TAG_LEVEL);

	memset (&level, 0, sizeof(level));
	memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0]));
	// Lazarus: these are used to track model and sound indices
	//          in g_main.c:
	max_modelindex = 0;
	max_soundindex = 0;

	// Lazarus: last frame a gib was spawned in
	lastgibframe = 0;

	strncpy (level.mapname, mapname, sizeof(level.mapname)-1);
	strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1);

	// set client fields on player ents
	for (i=0 ; i<game.maxclients ; i++)
		g_edicts[i+1].client = game.clients + i;

	ent = NULL;
	inhibit = 0;

	// Knightamre- load the entity alias script file
	LoadAliasData();
	//gi.dprintf ("Size of alias data: %i\n", alias_data_size);

// parse ents
	while (1)
	{
		// parse the opening brace	
		com_token = COM_Parse (&entities);
		if (!entities)
			break;
		if (com_token[0] != '{')
			gi.error ("ED_LoadFromFile: found %s when expecting {",com_token);

		if (!ent)
			ent = g_edicts;
		else
			ent = G_Spawn ();
		entities = ED_ParseEdict (entities, ent);

		// yet another map hack
		if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27"))
			ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;

		// remove things (except the world) from different skill levels or deathmatch
		if (ent != g_edicts)
		{
			if (deathmatch->value)
			{
				if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH )
				{
					G_FreeEdict (ent);	
					inhibit++;
					continue;
				}
			}
			else if (coop->value) // Knightmare added- not in coop flag support
			{
				if ( ent->spawnflags & SPAWNFLAG_NOT_COOP )
				{
					G_FreeEdict (ent);	
					inhibit++;
					continue;
				}

				// NOT_EASY && NOT_MEDIUM && NOT_HARD && NOT_DM == COOP_ONLY
				if ( (ent->spawnflags & SPAWNFLAG_NOT_EASY)
					&& (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)
					&& (ent->spawnflags & SPAWNFLAG_NOT_HARD)
					&& (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) )
					goto removeflags;

				if( ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
					((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
					((skill->value >= 2) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) )
					{
						G_FreeEdict (ent);	
						inhibit++;
						continue;
					}
			}
			else // single player
			{
				if( ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
					((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
					((skill->value >= 2) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) )
					{
						G_FreeEdict (ent);	
						inhibit++;
						continue;
					}
			}
removeflags:
			// Knightmare- remove no coop flag
			ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_DEATHMATCH|SPAWNFLAG_NOT_COOP);
		}

		ED_CallSpawn (ent);
		ent->s.renderfx |= RF_IR_VISIBLE; // ir goggles flag
	}	

	// Knightmare- unload the alias script file
	if (alias_data) { // If no alias file was loaded, don't bother
#ifdef KMQUAKE2_ENGINE_MOD // use new engine function instead
		gi.FreeFile(alias_data);
#else
		if (alias_from_pak)
			gi.TagFree(alias_data);
		else
			free(&alias_data);
#endif
	}

	// Knightmare- unload the replacement entity data
/*	if (newents) // If no alias file was loaded, don't bother
#ifdef KMQUAKE2_ENGINE_MOD // use new engine function instead
		gi.FreeFile(newents);
#else
		free(&newents);
#endif*/

	gi.dprintf ("%i entities inhibited\n", inhibit);

#ifdef DEBUG
	i = 1;
	ent = EDICT_NUM(i);
	while (i < globals.num_edicts) {
		if (ent->inuse != 0 || ent->inuse != 1)
			Com_DPrintf("Invalid entity %d\n", i);
		i++, ent++;
	}
#endif

	G_FindTeams ();

	// DWH
	G_FindCraneParts();

	// Get origin offsets (mainly for brush models w/o origin brushes)
	for (i=1, ent=g_edicts+i ; i < globals.num_edicts ; i++,ent++)
	{
		VectorAdd(ent->absmin,ent->absmax,ent->origin_offset);
		VectorScale(ent->origin_offset,0.5,ent->origin_offset);
		VectorSubtract(ent->origin_offset,ent->s.origin,ent->origin_offset);
	}

	// end DWH

	PlayerTrail_Init ();

//ZOID
	CTFSpawn();
	// Knightmare added
	if (deathmatch->value && !ctf->value)
		CTFSetupTechSpawn();	
//ZOID

	if (!deathmatch->value)
		SetupHintPaths();

	for(i=1, ent=g_edicts+i; i < globals.num_edicts; i++, ent++)
	{
		if(!ent->movewith)
			continue;
		if(ent->movewith_ent)
			continue;
		ent->movewith_ent = G_Find(NULL,FOFS(targetname),ent->movewith);
		// Make sure that we can really "movewith" this guy. This check
		// allows us to have movewith parent with same targetname as
		// other entities
		while(ent->movewith_ent &&
			(Q_stricmp(ent->movewith_ent->classname,"func_train")     &&
			 Q_stricmp(ent->movewith_ent->classname,"model_train")    &&
			 Q_stricmp(ent->movewith_ent->classname,"func_door")      &&
			 Q_stricmp(ent->movewith_ent->classname,"func_vehicle")   &&
			 Q_stricmp(ent->movewith_ent->classname,"func_tracktrain")  ))
			 ent->movewith_ent = G_Find(ent->movewith_ent,FOFS(targetname),ent->movewith);
		if(ent->movewith_ent)
			movewith_init(ent->movewith_ent);
	}

/*	for(i=1, ent=g_edicts+i; i < globals.num_edicts; i++, ent++)
	{
		gi.dprintf("%s:%s - movewith=%s, movewith_ent=%s:%s, movewith_next=%s:%s\n====================\n",
			ent->classname, (ent->targetname ? ent->targetname : "noname"),
			(ent->movewith ? ent->movewith : "N/A"),
			(ent->movewith_ent ? ent->movewith_ent->classname : "N/A"),
			(ent->movewith_ent ? (ent->movewith_ent->targetname ? ent->movewith_ent->targetname : "noname") : "N/A"),
			(ent->movewith_next ? ent->movewith_next->classname : "N/A"),
			(ent->movewith_next ? (ent->movewith_next->targetname ? ent->movewith_next->targetname : "noname") : "N/A"));

	} */

	if(game.transition_ents)
		LoadTransitionEnts();

	actor_files();

}
Пример #23
0
/*
 * Creates a server's entity / program execution context by
 * parsing textual entity definitions out of an ent file.
 */
void
SpawnEntities(const char *mapname, char *entities, const char *spawnpoint)
{
	edict_t *ent;
	int inhibit;
	const char *com_token;
	int i;
	float skill_level;
	static qboolean monster_count_city3 = false;

	if (!mapname || !entities || !spawnpoint)
	{
		return;
	}

	skill_level = floor(skill->value);

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

	if (skill_level > 3)
	{
		skill_level = 3;
	}

	if (skill->value != skill_level)
	{
		gi.cvar_forceset("skill", va("%f", skill_level));
	}

	SaveClientData();

	gi.FreeTags(TAG_LEVEL);

	memset(&level, 0, sizeof(level));
	memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0]));

	Q_strlcpy(level.mapname, mapname, sizeof(level.mapname));
	Q_strlcpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint));

	/* set client fields on player ents */
	for (i = 0; i < game.maxclients; i++)
	{
		g_edicts[i + 1].client = game.clients + i;
	}

	ent = NULL;
	inhibit = 0;

	/* parse ents */
	while (1)
	{
		/* parse the opening brace */
		com_token = COM_Parse(&entities);

		if (!entities)
		{
			break;
		}

		if (com_token[0] != '{')
		{
			gi.error("ED_LoadFromFile: found %s when expecting {", com_token);
		}

		if (!ent)
		{
			ent = g_edicts;
		}
		else
		{
			ent = G_Spawn();
		}

		entities = ED_ParseEdict(entities, ent);

		/* yet another map hack */
		if (!Q_stricmp(level.mapname, "command") &&
			!Q_stricmp(ent->classname, "trigger_once") &&
		   	!Q_stricmp(ent->model, "*27"))
		{
			ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;
		}

		/*
		 * The 'monsters' count in city3.bsp is wrong.
		 * There're two monsters triggered in a hidden
		 * and unreachable room next to the security
		 * pass.
		 *
		 * We need to make sure that this hack is only
		 * applied once!
		 */
		if(!Q_stricmp(level.mapname, "city3") && !monster_count_city3)
		{
			level.total_monsters = level.total_monsters - 2;
			monster_count_city3 = true;
		}

		/* remove things (except the world) from
		   different skill levels or deathmatch */
		if (ent != g_edicts)
		{
			if (deathmatch->value)
			{
				if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH)
				{
					G_FreeEdict(ent);
					inhibit++;
					continue;
				}
			}
			else
			{
				if (((skill->value == 0) &&
					 (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
					((skill->value == 1) &&
					 (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
					(((skill->value == 2) ||
					  (skill->value == 3)) &&
					 (ent->spawnflags & SPAWNFLAG_NOT_HARD))
					)
				{
					G_FreeEdict(ent);
					inhibit++;
					continue;
				}
			}

			ent->spawnflags &=
				~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM |
				  SPAWNFLAG_NOT_HARD |
				  SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH);
		}

		ED_CallSpawn(ent);
	}

	gi.dprintf("%i entities inhibited.\n", inhibit);

	G_FindTeams();

	PlayerTrail_Init();
}
Пример #24
0
void ParseEntityString (qboolean respawn)
{
	edict_t		*ent;
	int			inhibit;
	const char	*com_token;
	const char	*entities;
	int			i;

	entities = level.entity_string;

	ent = NULL;
	inhibit = 0;
	i = 0;

	//mark all the spawned_entities as inuse so G_Spawn doesn't try to pick them during
	//trigger spawning etc
	for (i = 0; i < num_spawned_entities; i++)
		spawned_entities[i]->inuse = true;

	i = 0;

// parse ents
	while (1)
	{
		// parse the opening brace	
		com_token = COM_Parse (&entities);
		if (!entities)
			break;
		if (com_token[0] != '{')
			gi.error ("ED_LoadFromFile: found %s when expecting {",com_token);

		if (respawn)
		{
			ent = spawned_entities[i];
			if (ent != world)
			{
				//double check we aren't overwriting stuff that we shouldn't be
				if (ent->enttype == ENT_DOOR_TRIGGER || ent->enttype == ENT_PLAT_TRIGGER)
					TDM_Error ("ParseEntityString: Trying to reuse an already spawned ent!");
				G_FreeEdict (ent);
				G_InitEdict (ent);
			}
			i++;
		}
		else
		{
			if (!ent)
				ent = g_edicts;
			else
				ent = G_Spawn ();
		}
		entities = ED_ParseEdict (entities, ent);

		// yet another map hack
		if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27"))
			ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;

		// remove things (except the world) from different skill levels or deathmatch
		if (ent != g_edicts)
		{
			if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH )
			{
				G_FreeEdict (ent);	
				inhibit++;

				//have to keep num_spawned in sync for respawn
				if (!respawn)
					spawned_entities[num_spawned_entities++] = ent;
				continue;
			}

			ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH);
		}
		else if (respawn)
			continue;

		ED_CallSpawn (ent);

		if (!respawn)
		{
			if (num_spawned_entities == MAX_EDICTS * 4)
				TDM_Error ("Exceeded MAX_EDICTS * 4 entities during entity string parse");
			spawned_entities[num_spawned_entities++] = ent;
		}
		else
		{
			//an elevator or something respawned on top of a player? don't do it for match start, since
			//players will be respawning anyway.
			if (tdm_match_status < MM_PLAYING && (ent->solid == SOLID_BBOX || ent->solid == SOLID_BSP))
			{
				edict_t	*touch[MAX_EDICTS];
				int		count;
				int		j;

				//r1: fix 00000196, can't killbox during map spawn due to risk of killing half-spawned
				//map entities. do a pseudo-killbox that only whacks players instead.

				count = gi.BoxEdicts (ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_SOLID);
				for (j = 0; j < count; j++)
				{
					if (touch[j] == ent)
						continue;

					//no point killing anything that won't clip (eg corpses)
					if (touch[j]->solid == SOLID_NOT || touch[j]->enttype == ENT_BODYQUE)
						continue;

					if (!touch[j]->client)
						continue;

					if (touch[j]->inuse)
						T_Damage (touch[j], ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
				}
			}
		}
	}

	//gi.dprintf ("%i entities inhibited\n", inhibit);

#ifdef DEBUG
	i = 1;
	ent = EDICT_NUM(i);
	while (i < globals.num_edicts) {
		if (ent->inuse != 0 || ent->inuse != 1)
			Com_DPrintf("Invalid entity %d\n", i);
		i++, ent++;
	}
#endif

	G_FindTeams ();
}
Пример #25
0
void use_target_spawner (edict_t *self, edict_t *other, edict_t *activator)
{
	edict_t	*ent;
	int r, maxr = -1, minr = -1;
	int oldskill = skill->value;
	int newskill;
	char command[32];

	ent = G_Spawn();
	if (self->spawnflags & 32) {
		if (self->target)
			ent->target = self->target;
		else {
			gi.dprintf("%s with spawnflag 32 and no target at %s\n", self->classname, vtos(self->s.origin));
			G_FreeEdict(ent);
			return;
		}
	} else if (self->target)
		ent->classname = self->target;

	if ((self->spawnflags & 32) || (!self->target)) {
		if (self->spawnflags & 1) {
			minr = 0;
			maxr = 4;
		}
		if (self->spawnflags & 2) {
			if (minr == -1)
				minr = 5;
			else
				minr = 0;
			maxr = 7;
		}
		if (self->spawnflags & 4) {
			if (minr == -1)
				minr = 8;
			else
				minr = 0;
			maxr = 10;
		}
		if (self->spawnflags & 8) {
			if (minr == -1)
				minr = 11;
			else
				minr = 0;
			maxr = 13;
		}

		if (minr == -1) {
			gi.dprintf("%s with NULL target and no spawnflags at %s\n", self->classname, vtos(self->s.origin));
			G_FreeEdict(ent);
			return;
		}

		r = (int) (random() * (maxr - minr) + minr);
		switch(r) {
		case 0: ent->classname = "monster_soldier_light"; break;
		case 1: ent->classname = "monster_soldier"; break;
		case 2: ent->classname = "monster_soldier_ss"; break;
		case 3: ent->classname = "monster_infantry"; break;
		case 4: ent->classname = "monster_parasite"; break;
		case 5: ent->classname = "monster_chick"; break;
		case 6: ent->classname = "monster_mutant"; break;
		case 7: ent->classname = "monster_gunner"; break;
		case 8: ent->classname = "monster_tank"; break;
		case 9: ent->classname = "monster_tank_commander"; break;
		case 10: ent->classname = "monster_gladiator"; break;
		case 11: ent->classname = "monster_supertank"; break;
		case 12: ent->classname = "monster_boss2"; break;
		case 13:
			if (random() < 0.3)
				ent->classname = "monster_jorg";
			else
				ent->classname = "monster_supertank";
			break;
		default:
			return;
			//break;
		}
	}

	if (!ent->classname) {
		gi.dprintf("%s spawning no classname at %s\n", self->classname, vtos(self->s.origin));
		G_FreeEdict(ent);
		return;
	}
	// Due to buggy fact2, we can't allow target_spawner to spawn misc_insane
	if (ent->classid == CI_M_INSANE) {
		G_FreeEdict(ent);
		return;
	}

	if (ent->health == -1) {
		newskill = (oldskill * ent->dmg_radius) + ent->dmg;
	} else {
		newskill = ent->health + random() * (ent->max_health - ent->health);
	}
	sprintf(command, "%d", newskill);
	gi.cvar_forceset("skill", command);

	VectorCopy (self->s.origin, ent->s.origin);
	VectorCopy (self->s.angles, ent->s.angles);
	ED_CallSpawn (ent);

	sprintf(command, "%d", oldskill);
	gi.cvar_forceset("skill", command);


	gi.unlinkentity (ent);
	if (!KillBox2 (ent))
		return;
	gi.linkentity (ent);
	if (self->speed)
		VectorCopy (self->movedir, ent->velocity);
}
Пример #26
0
/**
 * @brief Creates a server's entity / program execution context
 * by parsing textual entity definitions out of an ent file.
 * @sa CM_EntityString
 * @sa SV_SpawnServer
 */
void G_SpawnEntities (const char *mapname, bool day, const char *entities)
{
	int entnum;

	G_FreeTags(TAG_LEVEL);

	OBJZERO(level);
	level.pathingMap = (pathing_t *)G_TagMalloc(sizeof(*level.pathingMap), TAG_LEVEL);

	G_EdictsReset();

	/* initialize reactionFire data */
	G_ReactionFireTargetsInit();

	Q_strncpyz(level.mapname, mapname, sizeof(level.mapname));
	level.day = day;

	G_ResetClientData();

	level.activeTeam = TEAM_NO_ACTIVE;
	level.actualRound = 1;
	level.hurtAliens = sv_hurtaliens->integer;
	ai_waypointList = NULL;

	/* parse ents */
	entnum = 0;
	while (1) {
		edict_t *ent;
		/* parse the opening brace */
		const char *token = Com_Parse(&entities);
		if (!entities)
			break;
		if (token[0] != '{')
			gi.Error("ED_LoadFromFile: found %s when expecting {", token);

		ent = G_Spawn();

		entities = ED_ParseEdict(entities, ent);

		ent->mapNum = entnum++;

		/* Set the position of the entity */
		VecToPos(ent->origin, ent->pos);

		/* Call this entity's specific initializer (sets ent->type) */
		ED_CallSpawn(ent);

		/* if this entity is an bbox (e.g. actor), then center its origin based on its position */
		if (ent->solid == SOLID_BBOX)
			G_EdictCalcOrigin(ent);
	}

	/* spawn ai players, if needed */
	if (level.num_spawnpoints[TEAM_CIVILIAN]) {
		if (AI_CreatePlayer(TEAM_CIVILIAN) == NULL)
			gi.DPrintf("Could not create civilian\n");
	}

	if ((sv_maxclients->integer == 1 || ai_numactors->integer) && level.num_spawnpoints[TEAM_ALIEN]) {
		if (AI_CreatePlayer(TEAM_ALIEN) == NULL)
			gi.DPrintf("Could not create alien\n");
	}

	Com_Printf("Used inventory slots after ai spawn: %i\n", game.i.GetUsedSlots(&game.i));

	G_FindEdictGroups();
}
Пример #27
0
/*
 * Creates a server's entity / program execution context by
 * parsing textual entity definitions out of an ent file.
 */
void
SpawnEntities(char *mapname, char *entities, char *spawnpoint)
{
    edict_t *ent;
    int inhibit;
    char *com_token;
    int i;
    float skill_level;

    skill_level = floor(skill->value);

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

    if (skill_level > 3)
    {
        skill_level = 3;
    }

    if (skill->value != skill_level)
    {
        gi.cvar_forceset("skill", va("%f", skill_level));
    }

    SaveClientData();

    gi.FreeTags(TAG_LEVEL);

    memset(&level, 0, sizeof(level));
    memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0]));

    strncpy(level.mapname, mapname, sizeof(level.mapname) - 1);
    strncpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint) - 1);

    /* set client fields on player ents */
    for (i = 0; i < game.maxclients; i++)
    {
        g_edicts[i + 1].client = game.clients + i;
    }

    ent = NULL;
    inhibit = 0;

    /* parse ents */
    while (1)
    {
        /* parse the opening brace */
        com_token = COM_Parse(&entities);

        if (!entities)
        {
            break;
        }

        if (com_token[0] != '{')
        {
            gi.error("ED_LoadFromFile: found %s when expecting {", com_token);
        }

        if (!ent)
        {
            ent = g_edicts;
        }
        else
        {
            ent = G_Spawn();
        }

        entities = ED_ParseEdict(entities, ent);

        /* yet another map hack */
        if (!Q_stricmp(level.mapname, "command") &&
                !Q_stricmp(ent->classname,
                           "trigger_once") && !Q_stricmp(ent->model, "*27"))
        {
            ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;
        }

        /* remove things (except the world) from
           different skill levels or deathmatch */
        if (ent != g_edicts)
        {
            if (deathmatch->value)
            {
                if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH)
                {
                    G_FreeEdict(ent);
                    inhibit++;
                    continue;
                }
            }
            else
            {
                if (((skill->value == 0) &&
                        (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
                        ((skill->value == 1) &&
                         (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
                        (((skill->value == 2) ||
                          (skill->value == 3)) &&
                         (ent->spawnflags & SPAWNFLAG_NOT_HARD))
                   )
                {
                    G_FreeEdict(ent);
                    inhibit++;
                    continue;
                }
            }

            ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM |
                                 SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH);
        }

        ED_CallSpawn(ent);
    }

    gi.dprintf("%i entities inhibited.\n", inhibit);

    G_FindTeams();

    PlayerTrail_Init();

    CTFSpawn();
}
Пример #28
0
void fixbot_fire_laser (edict_t *self)
{
 
	vec3_t forward, right, up;
	vec3_t tempang, start;
	vec3_t	dir, angles, end;
	edict_t *ent;

	// critter dun got blown up while bein' fixed
	if (self->enemy->health <= self->enemy->gib_health)
	{
		self->monsterinfo.currentmove = &fixbot_move_stand;
		self->monsterinfo.aiflags &= ~AI_MEDIC;
		return;
	}

	gi.sound(self, CHAN_AUTO, gi.soundindex("misc/lasfly.wav"), 1, ATTN_STATIC, 0);

	VectorCopy (self->s.origin, start);
	VectorCopy (self->enemy->s.origin, end);
	VectorSubtract (end, start, dir);
	vectoangles (dir, angles);
	
	ent = G_Spawn ();
	VectorCopy (self->s.origin, ent->s.origin);
	VectorCopy (angles, tempang);
	AngleVectors (tempang, forward, right, up);
	VectorCopy (tempang, ent->s.angles);
	VectorCopy (ent->s.origin, start);
	
	VectorMA (start, 16, forward, start);
	
	VectorCopy (start, ent->s.origin);
	ent->enemy = self->enemy;
	ent->owner = self;
	ent->dmg = -1;
	monster_dabeam (ent);

	if (self->enemy->health > (self->enemy->mass/10))
	{
		// sorry guys but had to fix the problem this way
		// if it doesn't do this then two creatures can share the same space
		// and its real bad.
		if (check_telefrag (self)) 
		{
			self->enemy->spawnflags = 0;
			self->enemy->monsterinfo.aiflags = 0;
			self->enemy->target = NULL;
			self->enemy->targetname = NULL;
			self->enemy->combattarget = NULL;
			self->enemy->deathtarget = NULL;
			self->enemy->owner = self;
			ED_CallSpawn (self->enemy);
			self->enemy->owner = NULL;
			self->s.origin[2] += 1;
		
			self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING;

			self->monsterinfo.currentmove = &fixbot_move_stand;
			self->monsterinfo.aiflags &= ~AI_MEDIC;

		}
	}
	else
		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
}