Exemplo n.º 1
0
/*
============
SpawnItem

Sets the clipping size and plants the object on the floor.

Items can't be immediately dropped to floor, because they might
be on an entity that hasn't spawned yet.
============
*/
void SpawnItem (edict_t *ent, gitem_t *item)
{
	if (!ent || !item) // FS: Prevent SP crash
	{
		return;
	}

	PrecacheItem (item);

	if (ent->spawnflags)
	{
		if (strcmp(ent->classname, "key_power_cube") != 0)
		{
			ent->spawnflags = 0;
			gi.dprintf(DEVELOPER_MSG_GAME, "%s at %s has invalid spawnflags set\n", ent->classname, vtos(ent->s.origin));
		}
	}

	// some items will be prevented in deathmatch
	if (deathmatch->value)
	{
		if ( (int)dmflags->value & DF_NO_ARMOR )
		{
			if (item->pickup == Pickup_Armor || item->pickup == Pickup_PowerArmor)
			{
				G_FreeEdict (ent);
				return;
			}
		}
		if ( (int)dmflags->value & DF_NO_ITEMS )
		{
			if (item->pickup == Pickup_Powerup)
			{
				G_FreeEdict (ent);
				return;
			}
		}
		if ( (int)dmflags->value & DF_NO_HEALTH )
		{
			if (item->pickup == Pickup_Health || item->pickup == Pickup_Adrenaline)
			{
				G_FreeEdict (ent);
				return;
			}
		}
		if ( (int)dmflags->value & DF_INFINITE_AMMO )
		{
			if (item->flags == IT_AMMO /*|| (strcmp(ent->classname, "weapon_flamethrower") == 0) */)
			{
				G_FreeEdict (ent);
				return;
			}
		}
	}

	if (coop->value && (strcmp(ent->classname, "key_power_cube") == 0))
	{
		ent->spawnflags |= (1 << (8 + level.power_cubes));
		level.power_cubes++;
	}

	// don't let them drop items that stay in a coop game
	if ((coop->value) && (item->flags & IT_STAY_COOP))
	{
		item->drop = NULL;
	}

	ent->item = item;
	ent->nextthink = level.time + 2 * FRAMETIME;    // items start after other solids
	ent->think = droptofloor;
	ent->s.effects = item->world_model_flags;
//faf	ent->s.renderfx = RF_GLOW;
	if (ent->model)
		gi.modelindex (ent->model);
}
Exemplo n.º 2
0
static bool Destroy_Camera (Edict* self)
{
	G_SpawnParticle(self->origin, self->spawnflags, self->particle);
	G_FreeEdict(self);
	return true;
}
Exemplo n.º 3
0
/*QUAKED monster_gekk (1 .5 0) (-24 -24 -24) (24 24 24) Ambush Trigger_Spawn Sight Chant GoodGuy NoGib
*/
void SP_monster_gekk (edict_t *self)
{
	if (deathmatch->value)
	{
		G_FreeEdict (self);
		return;
	}

	sound_swing = gi.soundindex ("gek/gk_atck1.wav");
	sound_hit = gi.soundindex ("gek/gk_atck2.wav");
	sound_hit2 = gi.soundindex ("gek/gk_atck3.wav");
	sound_death = gi.soundindex ("gek/gk_deth1.wav");
	sound_pain1 = gi.soundindex ("gek/gk_pain1.wav");
	sound_sight = gi.soundindex ("gek/gk_sght1.wav");
	sound_search = gi.soundindex ("gek/gk_idle1.wav");
	sound_step1 = gi.soundindex ("gek/gk_step1.wav");
	sound_step2 = gi.soundindex ("gek/gk_step2.wav");
	sound_step3 = gi.soundindex ("gek/gk_step3.wav");
	sound_thud = gi.soundindex ("mutant/thud1.wav");
	
	sound_chantlow = gi.soundindex ("gek/gek_low.wav");
	sound_chantmid = gi.soundindex ("gek/gek_mid.wav");
	sound_chanthigh = gi.soundindex ("gek/gek_high.wav");
	
	self->movetype = MOVETYPE_STEP;
	self->solid = SOLID_BBOX;

	// Lazarus: special purpose skins
	if ( self->style )
	{
		PatchMonsterModel("models/monsters/gekk/tris.md2");
		self->s.skinnum = self->style * 3;
	}

	self->s.modelindex = gi.modelindex ("models/monsters/gekk/tris.md2");
	VectorSet (self->mins, -24, -24, -24);
	VectorSet (self->maxs, 24, 24, 24);

	gi.modelindex ("models/objects/gekkgib/pelvis/tris.md2");
	gi.modelindex ("models/objects/gekkgib/arm/tris.md2");
	gi.modelindex ("models/objects/gekkgib/torso/tris.md2");
	gi.modelindex ("models/objects/gekkgib/claw/tris.md2");
	gi.modelindex ("models/objects/gekkgib/leg/tris.md2");
	gi.modelindex ("models/objects/gekkgib/head/tris.md2");
	
	if(!self->health)
	{
		if (skill->value == 0)
			self->health = 120;
		else
			self->health = 150;
	}
	if(!self->gib_health)
		self->gib_health = -100;
	if(!self->mass)
		self->mass = 300;

	self->pain = gekk_pain;
	self->die = gekk_die;

	self->monsterinfo.stand = gekk_stand;

	self->monsterinfo.walk = gekk_walk;
	self->monsterinfo.run = gekk_run_start;
	self->monsterinfo.dodge = gekk_dodge;
	self->monsterinfo.attack = gekk_jump;
	self->monsterinfo.melee = gekk_melee;
	self->monsterinfo.sight = gekk_sight;
	
	self->monsterinfo.search = gekk_search;
	self->monsterinfo.idle = gekk_idle;
	self->monsterinfo.checkattack = gekk_checkattack;

	if (!self->monsterinfo.flies)
		self->monsterinfo.flies = 0.70;

	// Lazarus
	if(self->powerarmor)
	{
		if (self->powerarmortype == 1)
			self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
		else
			self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
		self->monsterinfo.power_armor_power = self->powerarmor;
	}
	self->common_name = "Gekk";

	if (!self->blood_type)
		self->blood_type = 1; //Knightmare- set this for blood color

	gi.linkentity (self);
	
	self->monsterinfo.currentmove = &gekk_move_stand;

	self->monsterinfo.scale = MODEL_SCALE;
	walkmonster_start (self);

	if (self->spawnflags & 8)
		self->monsterinfo.currentmove = &gekk_move_chant;
}
Exemplo n.º 4
0
/*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4)
Used as a positional target for spotlights, etc.
*/
void SP_info_null (edict_t *self)
{
	G_FreeEdict (self);
}
Exemplo n.º 5
0
/*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4)
 Used as a positional target for spotlights, etc.
 */
void G_info_null(g_edict_t *self) {
	G_FreeEdict(self);
}
Exemplo n.º 6
0
/*
==================
Cmd_Give_f

Give items to a client
==================
*/
void Cmd_Give_f (edict_t *ent)
{
	char		*name;
	gitem_t		*it;
	int			index;
	int			i;
	qboolean	give_all;
	edict_t		*it_ent;

	if (deathmatch->value && !sv_cheats->value)
	{
		gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
		return;
	}

	name = gi.args();

	if (Q_stricmp(name, "all") == 0)
		give_all = true;
	else
		give_all = false;

	if (give_all || Q_stricmp(gi.argv(1), "health") == 0)
	{
		if (gi.argc() == 3)
			ent->health = atoi(gi.argv(2));
		else
			ent->health = ent->max_health;
		if (!give_all)
			return;
	}

	if (give_all || Q_stricmp(name, "weapons") == 0)
	{
		for (i=0 ; i<game.num_items ; i++)
		{
			it = itemlist + i;
			if (!it->pickup)
				continue;
			if (!(it->flags & IT_WEAPON))
				continue;
			ent->client->pers.inventory[i] += 1;
		}
		if (!give_all)
			return;
	}

	if (give_all || Q_stricmp(name, "ammo") == 0)
	{
		for (i=0 ; i<game.num_items ; i++)
		{
			it = itemlist + i;
			if (!it->pickup)
				continue;
			if (!(it->flags & IT_AMMO))
				continue;
			Add_Ammo (ent, it, 1000);
		}
		if (!give_all)
			return;
	}

	if (give_all || Q_stricmp(name, "armor") == 0)
	{
		gitem_armor_t	*info;

		it = FindItem("Jacket Armor");
		ent->client->pers.inventory[ITEM_INDEX(it)] = 0;

		it = FindItem("Combat Armor");
		ent->client->pers.inventory[ITEM_INDEX(it)] = 0;

		it = FindItem("Body Armor");
		info = (gitem_armor_t *)it->info;
		ent->client->pers.inventory[ITEM_INDEX(it)] = info->max_count;

		if (!give_all)
			return;
	}

	if (give_all || Q_stricmp(name, "Power Shield") == 0)
	{
		it = FindItem("Power Shield");
		it_ent = G_Spawn();
		it_ent->classname = it->classname;
		SpawnItem (it_ent, it);
		Touch_Item (it_ent, ent, NULL, NULL);
		if (it_ent->inuse)
			G_FreeEdict(it_ent);

		if (!give_all)
			return;
	}

	if (give_all)
	{
		for (i=0 ; i<game.num_items ; i++)
		{
			it = itemlist + i;
			if (!it->pickup)
				continue;
			if (it->flags & (IT_ARMOR|IT_WEAPON|IT_AMMO))
				continue;
			ent->client->pers.inventory[i] = 1;
		}
		return;
	}

	it = FindItem (name);
	if (!it)
	{
		name = gi.argv(1);
		it = FindItem (name);
		if (!it)
		{
			gi.cprintf (ent, PRINT_HIGH, "unknown item\n");
			return;
		}
	}

	if (!it->pickup)
	{
		gi.cprintf (ent, PRINT_HIGH, "non-pickup item\n");
		return;
	}

	index = ITEM_INDEX(it);

	if (it->flags & IT_AMMO)
	{
		if (gi.argc() == 3)
			ent->client->pers.inventory[index] = atoi(gi.argv(2));
		else
			ent->client->pers.inventory[index] += it->quantity;
	}
	else
	{
		it_ent = G_Spawn();
		it_ent->classname = it->classname;
		SpawnItem (it_ent, it);
		Touch_Item (it_ent, ent, NULL, NULL);
		if (it_ent->inuse)
			G_FreeEdict(it_ent);
	}
}
Exemplo n.º 7
0
/*QUAKED monster_makron (1 .5 0) (-30 -30 0) (30 30 90) Ambush Trigger_Spawn Sight
*/
void SP_monster_makron (edict_t *self)
{
	if (deathmatch->value)
	{
		G_FreeEdict (self);
		return;
	}

	MakronPrecache ();

	self->movetype = MOVETYPE_STEP;
	self->solid = SOLID_BBOX;
	self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2");
	VectorSet (self->mins, -30, -30, 0);
	VectorSet (self->maxs, 30, 30, 90);

	// Lazarus: mapper-configurable health
	if(!self->health)
		self->health = 3000;

	// Lazarus: get around Killed's prevention of health dropping below -999
//	if(!self->gib_health)
//		self->gib_health = -2000;
	self->gib_health = -900;
	if(!self->mass)
		self->mass = 500;

	self->pain = makron_pain;
	self->die = makron_die;
	self->monsterinfo.stand = makron_stand;
	self->monsterinfo.walk = makron_walk;
	self->monsterinfo.run = makron_run;
	self->monsterinfo.dodge = NULL;
	self->monsterinfo.attack = makron_attack;
	self->monsterinfo.melee = NULL;
	self->monsterinfo.sight = makron_sight;
	self->monsterinfo.checkattack = Makron_CheckAttack;

	// Knightmare- added sparks and blood type
	if (!self->blood_type)
		self->blood_type = 2; //sparks
	else
		self->fogclip |= 2; //custom bloodtype flag

	// Lazarus
	if(self->powerarmor) {
		self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
		self->monsterinfo.power_armor_power = self->powerarmor;
	}

	gi.linkentity (self);
	
	self->monsterinfo.currentmove = &makron_move_sight;
	if(self->health < 0)
	{
		mmove_t	*deathmoves[] = {&makron_move_death2,
			                     &makron_move_death3,
								 NULL};
		M_SetDeath(self,(mmove_t **)&deathmoves);
	}
	self->monsterinfo.scale = MODEL_SCALE;
	walkmonster_start(self);
}
Exemplo n.º 8
0
Arquivo: g_utils.c Projeto: qbism/qbq2
/*
==============================
G_UseTargets

the global "activator" should be set to the entity that initiated the firing.

If self.delay is set, a DelayedUse entity will be created that will actually
do the SUB_UseTargets after that many seconds have passed.

Centerprints any self.message to the activator.

Search for (string)targetname in all entities that
match (string)self.target and call their .use function

==============================
*/
void G_UseTargets (edict_t *ent, edict_t *activator)
{
    edict_t		*t;

//
// check for a delay
//
    if (ent->delay)
    {
        // create a temp object to fire at a later time
        t = G_Spawn();
        t->classname = "DelayedUse";
        t->nextthink = level.time + ent->delay;
        t->think = Think_Delay;
        t->activator = activator;
        if (!activator)
            gi.dprintf ("Think_Delay with no activator\n");
        t->message = ent->message;
        t->target = ent->target;
        t->killtarget = ent->killtarget;
        return;
    }


//
// print the message
//
    if ((ent->message) && !(activator->svflags & SVF_MONSTER))
    {
        gi.centerprintf (activator, "%s", ent->message);
        if (ent->noise_index)
            gi.sound (activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0);
        else
            gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
    }

//
// kill killtargets
//
    if (ent->killtarget)
    {
        t = NULL;
        while ((t = G_Find (t, FOFS(targetname), ent->killtarget)))
        {
            G_FreeEdict (t);
            if (!ent->inuse)
            {
                gi.dprintf("entity was removed while using killtargets\n");
                return;
            }
        }
    }

//
// fire targets
//
    if (ent->target)
    {
        t = NULL;
        while ((t = G_Find (t, FOFS(targetname), ent->target)))
        {
            // doors fire area portals in a specific way
            if (!Q_strcasecmp(t->classname, "func_areaportal") &&
                    (!Q_strcasecmp(ent->classname, "func_door") || !Q_strcasecmp(ent->classname, "func_door_rotating")))
                continue;

            if (t == ent)
            {
                gi.dprintf ("WARNING: Entity used itself.\n");
            }
            else
            {
                if (t->use)
                    t->use (t, ent, activator);
            }
            if (!ent->inuse)
            {
                gi.dprintf("entity was removed while using targets\n");
                return;
            }
        }
    }
}
Exemplo n.º 9
0
qboolean monster_start (edict_t *self)
{
	if (deathmatch->value)
	{
		G_FreeEdict (self);
		return false;
	}

	// Lazarus: Already gibbed monsters passed across levels via trigger_transition:
	if ( (self->max_health > 0) && (self->health <= self->gib_health) && !(self->spawnflags & SF_MONSTER_NOGIB) )
	{
		void	SP_gibhead(edict_t *);

		SP_gibhead(self);
		return true;
	}

	// Lazarus: Good guys
	if (self->spawnflags & SF_MONSTER_GOODGUY) {
		self->monsterinfo.aiflags |= AI_GOOD_GUY;
		if(!self->dmgteam) {
			self->dmgteam = gi.TagMalloc(8*sizeof(char), TAG_LEVEL);
		//	strncpy(self->dmgteam,"player");
			Q_strncpyz(self->dmgteam,"player", 8);
		}
	}

	// Lazarus: Max range for sight/attack
	if(st.distance)
		self->monsterinfo.max_range = max(500,st.distance);
	else
		self->monsterinfo.max_range = 1280;	// Q2 default is 1000. We're mean.

	// Lazarus: We keep SIGHT to mean what old AMBUSH does, and AMBUSH additionally
	//          now means don't play idle sounds
/*	if ((self->spawnflags & MONSTER_SIGHT) && !(self->monsterinfo.aiflags & AI_GOOD_GUY))
	{
		self->spawnflags &= ~MONSTER_SIGHT;
		self->spawnflags |= MONSTER_AMBUSH;
	} */
	if ((self->spawnflags & SF_MONSTER_AMBUSH) && !(self->monsterinfo.aiflags & AI_GOOD_GUY))
		self->spawnflags |= SF_MONSTER_SIGHT;

	// Lazarus: Don't add trigger spawned monsters until they are actually spawned
	if (!(self->monsterinfo.aiflags & AI_GOOD_GUY) && !(self->spawnflags & SF_MONSTER_TRIGGER_SPAWN))
		level.total_monsters++;

	self->nextthink = level.time + FRAMETIME;
	self->svflags |= SVF_MONSTER;
	self->s.renderfx |= RF_FRAMELERP;
	self->air_finished = level.time + 12;
	self->use = monster_use;
	// Lazarus - don't reset max_health unnecessarily
	if(!self->max_health)
		self->max_health = self->health;
	if (self->health < (self->max_health / 2))
		self->s.skinnum |= 1;
	else
		self->s.skinnum &= ~1;
	self->clipmask = MASK_MONSTERSOLID;

	if (self->s.skinnum < 1) // Knightmare added
		self->s.skinnum = 0;
	self->deadflag = DEAD_NO;
	self->svflags &= ~SVF_DEADMONSTER;

	if(self->monsterinfo.flies > 1.0)
	{
		self->s.effects |= EF_FLIES;
		self->s.sound = gi.soundindex ("infantry/inflies1.wav");
	}

	// Lazarus
	if(self->health <=0)
	{
		self->svflags |= SVF_DEADMONSTER;
		self->movetype = MOVETYPE_TOSS;
		self->takedamage = DAMAGE_YES;
		self->monsterinfo.pausetime = 100000000;
		self->monsterinfo.aiflags &= ~AI_RESPAWN_FINDPLAYER;
		if(self->max_health > 0)
		{
			// This must be a dead monster who changed levels
			// via trigger_transition
			self->nextthink = 0;
			self->deadflag = DEAD_DEAD;
		}
		if(self->s.effects & EF_FLIES && self->monsterinfo.flies <= 1.0)
		{
			self->think = M_FliesOff;
			self->nextthink = level.time + 1 + random()*60;
		}
		return true;
	}
	else
	{
		// make sure red shell is turned off in case medic got confused:
		self->monsterinfo.aiflags &= ~AI_RESURRECTING;
		self->svflags &= ~SVF_DEADMONSTER;
		self->takedamage = DAMAGE_AIM;
	}

	if (!self->monsterinfo.checkattack)
		self->monsterinfo.checkattack = M_CheckAttack;
	VectorCopy (self->s.origin, self->s.old_origin);

	if (st.item)
	{
		self->item = FindItemByClassname (st.item);
		if (!self->item)
			gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item);
	}

	// randomize what frame they start on
	// Lazarus: preserve frame if set for monsters changing levels
	if (!self->s.frame)
	{
		if (self->monsterinfo.currentmove)
			self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1));
	}

	return true;
}
Exemplo n.º 10
0
/*
 * QUAKED monster_flyer (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
 */
void
SP_monster_flyer(edict_t *self)
{
	if (!self)
	{
		return;
	}

	if (deathmatch->value)
	{
		G_FreeEdict(self);
		return;
	}

	/* fix a map bug in jail5.bsp */
	if (!Q_stricmp(level.mapname, "jail5") && (self->s.origin[2] == -104))
	{
		self->targetname = self->target;
		self->target = NULL;
	}

	sound_sight = gi.soundindex("flyer/flysght1.wav");
	sound_idle = gi.soundindex("flyer/flysrch1.wav");
	sound_pain1 = gi.soundindex("flyer/flypain1.wav");
	sound_pain2 = gi.soundindex("flyer/flypain2.wav");
	sound_slash = gi.soundindex("flyer/flyatck2.wav");
	sound_sproing = gi.soundindex("flyer/flyatck1.wav");
	sound_die = gi.soundindex("flyer/flydeth1.wav");

	gi.soundindex("flyer/flyatck3.wav");

	self->s.modelindex = gi.modelindex("models/monsters/flyer/tris.md2");
	VectorSet(self->mins, -16, -16, -24);
	VectorSet(self->maxs, 16, 16, 16);
	self->movetype = MOVETYPE_STEP;
	self->solid = SOLID_BBOX;

	self->s.sound = gi.soundindex("flyer/flyidle1.wav");

	self->health = 50;
	self->mass = 50;

	self->pain = flyer_pain;
	self->die = flyer_die;

	self->monsterinfo.stand = flyer_stand;
	self->monsterinfo.walk = flyer_walk;
	self->monsterinfo.run = flyer_run;
	self->monsterinfo.attack = flyer_attack;
	self->monsterinfo.melee = flyer_melee;
	self->monsterinfo.sight = flyer_sight;
	self->monsterinfo.idle = flyer_idle;
	self->monsterinfo.blocked = (void *)flyer_blocked;

	gi.linkentity(self);

	self->monsterinfo.currentmove = &flyer_move_stand;
	self->monsterinfo.scale = MODEL_SCALE;

	flymonster_start(self);
}
Exemplo n.º 11
0
//================
//G_ClearSnap
// We just run G_SnapFrame, the server just sent the snap to the clients,
// it's now time to clean up snap specific data to start the next snap from clean.
//================
void G_ClearSnap( void )
{
	edict_t	*ent;

	game.realtime = trap_Milliseconds(); // level.time etc. might not be real time

	// clear gametype's clock override
	gs.gameState.longstats[GAMELONG_CLOCKOVERRIDE] = 0;

	// clear all events in the snap
	for( ent = &game.edicts[0]; ENTNUM( ent ) < game.numentities; ent++ )
	{
		if( ISEVENTENTITY( &ent->s ) )  // events do not persist after a snapshot
		{
			G_FreeEdict( ent );
			continue;
		}

		// events only last for a single message
		ent->s.events[0] = ent->s.events[1] = 0;
		ent->s.eventParms[0] = ent->s.eventParms[1] = 0;
		ent->numEvents = 0;
		ent->eventPriority[0] = ent->eventPriority[1] = qfalse;
		ent->s.teleported = qfalse; // remove teleported bit.

		// remove effect bits that are (most likely) added from gametypes
		ent->s.effects = ( ent->s.effects & (EF_TAKEDAMAGE|EF_CARRIER|EF_FLAG_TRAIL|EF_ROTATE_AND_BOB|EF_STRONG_WEAPON) );
	}

	// recover some info, let players respawn and finally clear the snap structures
	for( ent = &game.edicts[0]; ENTNUM( ent ) < game.numentities; ent++ )
	{
		if( !GS_MatchPaused() )
		{
			// copy origin to old origin ( this old_origin is for snaps )
			if( !( ent->r.svflags & SVF_TRANSMITORIGIN2 ) )
				VectorCopy( ent->s.origin, ent->s.old_origin );
			
			G_CheckClientRespawnClick( ent );
		}

		if( GS_MatchPaused() )
			ent->s.sound = entity_sound_backup[ENTNUM( ent )];

		// clear the snap temp info
		memset( &ent->snap, 0, sizeof( ent->snap ) );
		if( ent->r.client && trap_GetClientState( PLAYERNUM( ent ) ) >= CS_SPAWNED )
		{
			memset( &ent->r.client->resp.snap, 0, sizeof( ent->r.client->resp.snap ) );

			// set race stats to invisible
			ent->r.client->ps.stats[STAT_TIME_SELF] = STAT_NOTSET;
			ent->r.client->ps.stats[STAT_TIME_BEST] = STAT_NOTSET;
			ent->r.client->ps.stats[STAT_TIME_RECORD] = STAT_NOTSET;
			ent->r.client->ps.stats[STAT_TIME_ALPHA] = STAT_NOTSET;
			ent->r.client->ps.stats[STAT_TIME_BETA] = STAT_NOTSET;
		}
	}

	g_snapStarted = qfalse;
}
Exemplo n.º 12
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;
/*freeze*/
	static int	fStarted = 0;
/*freeze*/

	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);

/*freeze*/
	if (fStarted)
		sl_GameEnd(&gi, level);
/*freeze*/
	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 ();
/*freeze*/
	sl_GameStart(&gi, level);
	{
		static cvar_t*	_log_style_cvar = NULL;

		if (NULL == _log_style_cvar)
			_log_style_cvar = gi.cvar("sl_log_style", "0", 0);

		if (_log_style_cvar && _log_style_cvar->value >= SL_LOG_STYLE_1_2a)
			fStarted = 1;
	}
/*freeze*/
}
Exemplo n.º 13
0
/*
===============
Touch_Item
===============
*/
void Touch_Item (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
	qboolean	taken;
	float		vol;

	if (!other->client)
	{
		if (!ent->playedsound && ent->groundentity)
		{
			//gi.dprintf(DEVELOPER_MSG_GAME, "Plonk!  %s\n",other->classname);
			if (ent->item)
			{
				//velocity goes from around -250 for normal drop to ~1000 from top of dday2 church stairs
				//knife ~1 lb  50cal ~50 lbs
				vol = ((1000+(-1 * ent->velocity[2]))/2000) * ( (ent->item->weight+100)/150 );
				if (vol > .9)
					vol = .9;


//				gi.dprintf(DEVELOPER_MSG_GAME, "%f %f   %f\n", ent->velocity[2], ent->item->weight, vol);
//				gi.dprintf(DEVELOPER_MSG_GAME, "%f %f   %f\n", ((1000+(-1 * ent->velocity[2]))/2000), (ent->item->weight+100)/150, vol);
				
				if (ent->item->flags & IT_AMMO || ent->item->position == LOC_GRENADES || ent->item->position == LOC_KNIFE)
					gi.sound (ent, CHAN_WEAPON, gi.soundindex("weapons/ammodrop.wav"), vol, ATTN_NORM, 0);
					//gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("weapons/ammodrop.wav"), vol, ATTN_NORM, 0);			
				else if (ent->item->flags & IT_WEAPON)
					gi.sound (ent, CHAN_WEAPON, gi.soundindex("weapons/gundrop.wav"), vol, ATTN_NORM, 0);
					//gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("weapons/gundrop.wav"), vol, ATTN_NORM, 0);			
			}
			ent->playedsound = true;
		}
		return;
	}
	if (other->health < 1)
		return;		// dead people can't pickup
	if (!ent->item->pickup)
		return;		// not a grabbable item?
	if (other->client->resp.autopickup == false && ent->item->classnameb != HGRENADE)
		return;


	if (other->client && other->client->resp.mos == MEDIC)
	{
		if (!( 
				(ent->item->tag && ent->item->tag == AMMO_TYPE_PISTOL) ||
				(ent->item->position && ent->item->position == LOC_PISTOL) ||
				(ent->item->pickup_name && !Q_stricmp(ent->item->pickup_name,"Knife")) ||
				(ent->item->pickup_name && !Q_stricmp(ent->item->pickup_name,"Helmet")) 
			))
			return;
	}

	//pbowens: you can only have 1 helmet
	if (ent->item->pickup_name && !Q_stricmp(ent->item->pickup_name, "Helmet") )
	{
		if (other->client->pers.inventory[ITEM_INDEX(ent->item)])
		{
//			safe_cprintf(other, PRINT_HIGH, "You already have a helmet!\n");
			return;
		}
	}

	// you cannot pickup more than 1 team weapon
	if (ent->item->guninfo && other->client->pers.inventory[ITEM_INDEX(ent->item)])
		return;

//faf	if (ent->item->position != LOC_GRENADES && ent->count > 1 &&
//faf		other->client->pers.inventory[ITEM_INDEX(ent->item)] ) // dont pick up if ammo already
//faf		return;

	taken = ent->item->pickup(ent, other);

	if (taken)
	{
		// flash the screen
		//other->client->bonus_alpha = 0.25;	

		// show icon and name on status bar
		other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(ent->item->icon);
		other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS+ITEM_INDEX(ent->item);

		other->client->pickup_msg_time = level.time + 3.0;

		// change selected item
		//if (ent->item->use)
		//	other->client->pers.selected_item = other->client->ps.stats[STAT_SELECTED_ITEM] = ITEM_INDEX(ent->item);

		gi.sound(other, CHAN_ITEM, gi.soundindex(ent->item->pickup_sound), 1, ATTN_NORM, 0);
	}

	if (!(ent->spawnflags & ITEM_TARGETS_USED))
	{
		G_UseTargets (ent, other);
		ent->spawnflags |= ITEM_TARGETS_USED;
	}

	if (!taken)
		return;

	if (!((coop->value) &&  (ent->item->flags & IT_STAY_COOP)) || (ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))
	{
		if (ent->flags & FL_RESPAWN)
			ent->flags &= ~FL_RESPAWN;
		else
			G_FreeEdict (ent);
	}

}
Exemplo n.º 14
0
void Weapon_Sandbag_Fire (edict_t *ent)

{
	edict_t	*sandbag;

    
	ent->client->ps.gunframe++;

	if (ent->client->resp.team_on->index == 0)
	{
		if (allied_sandbags >= sandbaglimit->value)
		{
			safe_centerprintf(ent, "Your team is at the sandbag limit!\n");
			return;
		}
	}
	else if (ent->client->resp.team_on->index == 1)
	{
		if (axis_sandbags >= sandbaglimit->value)
		{
			safe_centerprintf(ent, "Your team is at the sandbag limit!\n");
			return;
		}
	}

	if (VectorCompare (ent->client->sandbag_pos , vec3_origin))
	{
		safe_centerprintf(ent, "There's no space for sandbags there!\n");
		return;
	}

	ent->client->pers.inventory[ITEM_INDEX(FindItem("Sandbags"))]--;





	sandbag = G_Spawn();

	VectorCopy (ent->client->sandbag_preview->mins, sandbag->mins);
	VectorCopy (ent->client->sandbag_preview->maxs, sandbag->maxs);
	VectorCopy (ent->client->sandbag_preview->s.angles, sandbag->s.angles);

	sandbag->classnameb = SANDBAGS;

	sandbag->movetype = MOVETYPE_TOSS;
	sandbag->solid = SOLID_BBOX;
	sandbag->s.modelindex = gi.modelindex ("models/objects/sandbag/tris.md2");
	sandbag->think = sandbag_think;
	sandbag->nextthink = level.time +.1;
//	ent->s.frame = rand() % 16;
//	ent->s.frame = 1;

	sandbag->mass = 300;

	sandbag->touch = sandbag_touch;

	sandbag->health = 2000;
	sandbag->takedamage      = DAMAGE_YES;
	sandbag->die = sandbag_die;
		sandbag->s.skinnum = 0;


		sandbag->s.frame = 0;
//		VectorSet (sandbag->mins, -19, -9, -10);
//		VectorSet (sandbag->maxs, 19, 9, 8);

	VectorCopy (ent->client->sandbag_pos, sandbag->s.origin);
	
	sandbag->clipmask = MASK_SHOT;


	sandbag->spawnflags = 1;
	if (ent->client->resp.team_on)
		sandbag->obj_owner = ent->client->resp.team_on->index;

	if (ent->client->resp.team_on->index == 0)
		allied_sandbags++;
	else if (ent->client->resp.team_on->index == 1)
		axis_sandbags++;

	sandbag->obj_time = level.time;


	gi.linkentity (sandbag);






	if (ent->client->pers.inventory[ITEM_INDEX(FindItem("Sandbags"))] ==0)
	{
		ent->client->weaponstate=WEAPON_LOWER;
		ent->client->ps.gunframe = 20;
		Use_Weapon (ent, FindItem("fists"));
		return;
	}

	G_FreeEdict (ent->client->sandbag_preview);
	ent->client->sandbag_preview = NULL;
}
Exemplo n.º 15
0
void cash_kill( edict_t *self )
{
	num_cash_items--;
	G_FreeEdict( self );
}
Exemplo n.º 16
0
static void func_explosive_explode( edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, const vec3_t point )
{
	vec3_t origin, bakorigin;
	vec3_t chunkorigin;
	vec3_t size;
	int count;
	int mass;

	// do not explode unless visible
	if( self->r.svflags & SVF_NOCLIENT )
		return;

	self->takedamage = DAMAGE_NO;

	// bmodel origins are (0 0 0), we need to adjust that here
	VectorCopy( self->s.origin, bakorigin );
	VectorScale( self->r.size, 0.5, size );
	VectorAdd( self->r.absmin, size, origin );
	VectorCopy( origin, self->s.origin );

	if( self->projectileInfo.maxDamage )
		G_RadiusDamage( self, attacker, NULL, NULL, MOD_EXPLOSIVE );

	VectorSubtract( self->s.origin, inflictor->s.origin, self->velocity );
	VectorNormalize( self->velocity );
	VectorScale( self->velocity, 150, self->velocity );

	// start chunks towards the center
	VectorScale( size, 0.5, size );
	mass = self->projectileInfo.radius * 0.75;
	if( !mass )
		mass = 75;

	// big chunks
	if( self->count > 0 )
	{
		if( mass >= 100 )
		{
			count = mass / 100;
			if( count > 8 )
				count = 8;
			while( count-- )
			{
				chunkorigin[0] = origin[0] + crandom() * size[0];
				chunkorigin[1] = origin[1] + crandom() * size[1];
				chunkorigin[2] = origin[2] + crandom() * size[2];
				ThrowDebris( self, self->count, 1, chunkorigin );
			}
		}
	}

	// small chunks
	if( self->viewheight > 0 )
	{
		count = mass / 25;
		if( count > 16 )
			count = 16;
		if( count < 1 ) count = 1;
		while( count-- )
		{
			chunkorigin[0] = origin[0] + crandom() * size[0];
			chunkorigin[1] = origin[1] + crandom() * size[1];
			chunkorigin[2] = origin[2] + crandom() * size[2];
			ThrowDebris( self, self->viewheight, 2, chunkorigin );
		}
	}

	G_UseTargets( self, attacker );

	if( self->projectileInfo.maxDamage )
	{
		edict_t *explosion;

		explosion = G_Spawn();
		VectorCopy( self->s.origin, explosion->s.origin );
		explosion->projectileInfo = self->projectileInfo;
		BecomeExplosion1( explosion );
	}

	if( self->use == NULL )
	{
		G_FreeEdict( self );
		return;
	}

	self->health = self->max_health;
	self->r.solid = SOLID_NOT;
	self->r.svflags |= SVF_NOCLIENT;
	VectorCopy( bakorigin, self->s.origin );
	VectorClear( self->velocity );
	GClip_LinkEntity( self );
}
Exemplo n.º 17
0
void SpawnTotem(edict_t *ent, int abilityID)
{
	int			talentLevel, cost=TOTEM_COST;
	edict_t		*totem;
	int			totemType;
	vec3_t		start;//GHz 4.32

	// cost is doubled if you are a flyer or cacodemon below skill level 5
	if ((ent->mtype == MORPH_FLYER && ent->myskills.abilities[FLYER].current_level < 5) 
		|| (ent->mtype == MORPH_CACODEMON && ent->myskills.abilities[CACODEMON].current_level < 5))
		cost *= 2;

	if(!V_CanUseAbilities(ent, abilityID, cost, true))
		return;
	
	if (ctf->value && abilityID == FIRE_TOTEM 
		&& (CTF_DistanceFromBase(ent, NULL, CTF_GetEnemyTeam(ent->teamnum)) < CTF_BASE_DEFEND_RANGE))
	{
		safe_cprintf(ent, PRINT_HIGH, "Can't build in enemy base!\n");
		return;
	}

	//Determine the totem type.
	switch(abilityID)
	{
	case FIRE_TOTEM:		totemType = TOTEM_FIRE;		break;
	case WATER_TOTEM:		totemType = TOTEM_WATER;	break;
	case AIR_TOTEM:			totemType = TOTEM_AIR;		break;
	case EARTH_TOTEM:		totemType = TOTEM_EARTH;	break;
	case DARK_TOTEM:		totemType = TOTEM_DARKNESS;	break;
	case NATURE_TOTEM:		totemType = TOTEM_NATURE;	break;
	default: return;
	}

	//Can't create too many totems.
	if(ent->totem1)
	{
		//Can't have more than one totem without the talent.
		/*if(getTalentLevel(ent, TALENT_TOTEM) < 1)
		{
			safe_cprintf(ent, PRINT_HIGH, "You already have a totem active.\n");
			return;
		}
		//Can't have more than two totems.
		else*/ if(ent->totem2)
		{
			safe_cprintf(ent, PRINT_HIGH, "You already have two totems active.\n");
			return;
		}
		//Can't have two totems of opposite alignment.
		else
		{
			int opposite = 0;
			switch(ent->totem1->mtype)
			{
			case TOTEM_FIRE:		opposite = TOTEM_WATER;		break;
			case TOTEM_WATER:		opposite = TOTEM_FIRE;		break;
			case TOTEM_AIR:			opposite = TOTEM_EARTH;		break;
			case TOTEM_EARTH:		opposite = TOTEM_AIR;		break;
			case TOTEM_DARKNESS:	opposite = TOTEM_NATURE;	break;
			case TOTEM_NATURE:		opposite = TOTEM_DARKNESS;	break;
			}
			if(totemType == opposite)
			{
				safe_cprintf(ent, PRINT_HIGH, "You can't create two totems of opposite elemental alignment.\n");
				return;
			}
			else if(totemType == ent->totem1->mtype)
			{
				safe_cprintf(ent, PRINT_HIGH, "You can't create totems of the same type.\n");
				return;
			}
		}
	}

	//Drop a totem.
	totem = DropTotem(ent);
	totem->mtype = totemType;
	totem->monsterinfo.level = ent->myskills.abilities[abilityID].current_level;
	totem->classname = "totem";
	/*totem->owner =*/ totem->activator = ent;
	totem->think = totem_general_think;
	totem->touch = totem_touch;
	totem->nextthink = level.time + FRAMETIME*2;
	totem->delay = level.time + 0.5;
	totem->die = totem_die;

	//TODO: update this with the new model.
	totem->s.modelindex = gi.modelindex("models/items/mega_h/tris.md2");
	//totem->s.angles[ROLL] = 270;
	VectorSet (totem->mins, -8, -8, -12);
	VectorSet (totem->maxs, 8, 8, 16);
	VectorCopy(ent->s.origin, totem->s.origin);
	
	totem->health = TOTEM_HEALTH_BASE + TOTEM_HEALTH_MULT * totem->monsterinfo.level;

	//Talent: Totemic Focus - increases totem health
	if((talentLevel = getTalentLevel(ent, TALENT_TOTEM)) > 0)
		totem->health *= 1 + 0.1666 * talentLevel;

	if (totemType == TOTEM_FIRE)
	{
		// fire totem is much tougher
		totem->health *= 2;
		// fire totem has a longer delay
		totem->delay = level.time + 2.0;
	}

	totem->max_health = totem->health*2;

	//Not sure if this stuff is needed (Archer)
	totem->svflags |= SVF_MONSTER;
	totem->takedamage = DAMAGE_AIM;
	totem->clipmask = MASK_MONSTERSOLID;

	//Back to stuff we need
	totem->mass = 200;
	totem->movetype = MOVETYPE_TOSS;//MOVETYPE_WALK;
	totem->deadflag = DEAD_NO;
	totem->svflags &= ~SVF_DEADMONSTER;	
	totem->solid = SOLID_BBOX;

	//Graphical effects
	//TODO: update this to make it look better.
	totem->s.effects |= EF_PLASMA | EF_COLOR_SHELL | EF_SPHERETRANS;
	switch(totemType)
	{
	case TOTEM_FIRE:
		totem->s.effects |= 262144;		//red radius light
		totem->s.renderfx |= RF_SHELL_RED;
		break;
	case TOTEM_WATER:
		totem->s.effects |= 524288;		//blue radius light
		totem->s.renderfx |= RF_SHELL_CYAN;
		break;
	case TOTEM_AIR:
		totem->s.effects |= 64;			//bright light radius
		totem->s.renderfx |= RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_GREEN;		
		break;
	case TOTEM_EARTH:
		totem->s.renderfx |= RF_SHELL_YELLOW;
		break;
	case TOTEM_DARKNESS:
		totem->s.effects |= 2147483648;		//strange darkness effect
		//totem->s.renderfx |= RF_SHELL_RED | RF_SHELL_BLUE;
		break;
	case TOTEM_NATURE:
		totem->s.effects |= 128;	//green radius light
		totem->s.renderfx |= RF_SHELL_GREEN;
		break;
	}
//GHz 4.32
	if (!G_GetSpawnLocation(ent, 64, totem->mins, totem->maxs, start))
	{
		G_FreeEdict(totem);
		return;
	}

	VectorCopy(start, totem->s.origin);
	gi.linkentity(totem);
//GHz
	if(!ent->totem1)	ent->totem1 = totem;
	else				ent->totem2 = totem;

	ent->client->pers.inventory[ITEM_INDEX(Fdi_POWERCUBE)] -= cost;

	// calling entity made a sound, used to alert monsters
	ent->lastsound = level.framenum;
	ent->client->ability_delay = level.time + 1.3;
}
Exemplo n.º 18
0
//QUAKED light_mine (0 1 0) (-2 -2 -12) (2 2 12)
void SP_light_mine( edict_t *ent )
{
	G_FreeEdict( ent );
}
Exemplo n.º 19
0
/*QUAKED monster_brain (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
*/
void SP_monster_brain (edict_t *self)
{
	if (deathmatch->value)
	{
		G_FreeEdict (self);
		return;
	}

	sound_chest_open = gi.soundindex ("brain/brnatck1.wav");
	sound_tentacles_extend = gi.soundindex ("brain/brnatck2.wav");
	sound_tentacles_retract = gi.soundindex ("brain/brnatck3.wav");
	sound_death = gi.soundindex ("brain/brndeth1.wav");
	sound_idle1 = gi.soundindex ("brain/brnidle1.wav");
	sound_idle2 = gi.soundindex ("brain/brnidle2.wav");
	sound_idle3 = gi.soundindex ("brain/brnlens1.wav");
	sound_pain1 = gi.soundindex ("brain/brnpain1.wav");
	sound_pain2 = gi.soundindex ("brain/brnpain2.wav");
	sound_sight = gi.soundindex ("brain/brnsght1.wav");
	sound_search = gi.soundindex ("brain/brnsrch1.wav");
	sound_melee1 = gi.soundindex ("brain/melee1.wav");
	sound_melee2 = gi.soundindex ("brain/melee2.wav");
	sound_melee3 = gi.soundindex ("brain/melee3.wav");

	self->movetype = MOVETYPE_STEP;
	self->solid = SOLID_BBOX;
	self->s.modelindex = gi.modelindex ("models/monsters/brain/tris.md2");
	VectorSet (self->mins, -16, -16, -24);
	VectorSet (self->maxs, 16, 16, 32);

	self->health = 300;
	self->gib_health = -150;
	self->mass = 400;

	self->pain = brain_pain;
	self->die = brain_die;

	self->monsterinfo.stand = brain_stand;
	self->monsterinfo.walk = brain_walk;
	self->monsterinfo.run = brain_run;
// PMM
	self->monsterinfo.dodge = M_MonsterDodge;
	self->monsterinfo.duck = brain_duck;
	self->monsterinfo.unduck = monster_duck_up;
//	self->monsterinfo.dodge = brain_dodge;
// pmm
//	self->monsterinfo.attack = brain_attack;
	self->monsterinfo.melee = brain_melee;
	self->monsterinfo.sight = brain_sight;
	self->monsterinfo.search = brain_search;
	self->monsterinfo.idle = brain_idle;

	self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
	self->monsterinfo.power_armor_power = 100;

	gi.linkentity (self);

	self->monsterinfo.currentmove = &brain_move_stand;	
	self->monsterinfo.scale = MODEL_SCALE;

	walkmonster_start (self);
}
Exemplo n.º 20
0
//QUAKED misc_model (1 .5 .25) (-16 -16 -16) (16 16 16)
//Generic placeholder for inserting .md3 models in game. Requires compilation of map geometry to be added to level.
//-------- KEYS --------
//angle: direction in which model will be oriented.
//model : path/name of model to use (eg: models/mapobjects/teleporter/teleporter.md3).
void SP_misc_model( edict_t *ent )
{
	G_FreeEdict( ent );
}
Exemplo n.º 21
0
/*
=================
debris
=================
*/
void debris_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
	G_FreeEdict (self);
}
Exemplo n.º 22
0
/*
 * @brief Creates a server's entity / program execution context by
 * parsing textual entity definitions out of an ent file.
 */
void G_SpawnEntities(const char *name, const char *entities) {
	g_edict_t *ent;
	int32_t inhibit;
	char *com_token;
	int32_t i;

	gi.FreeTag(Z_TAG_GAME_LEVEL);

	memset(&g_level, 0, sizeof(g_level));
	memset(g_game.edicts, 0, g_max_entities->value * sizeof(g_game.edicts[0]));

	g_strlcpy(g_level.name, name, sizeof(g_level.name));

	// set client fields on player ents
	for (i = 0; i < sv_max_clients->integer; i++) {
		g_game.edicts[i + 1].client = g_game.clients + i;
	}
	ge.num_edicts = sv_max_clients->integer + 1;

	ent = NULL;
	inhibit = 0;

	// parse ents
	while (true) {
		// parse the opening brace
		com_token = ParseToken(&entities);

		if (!entities)
			break;

		if (com_token[0] != '{')
			gi.Error("Found \"%s\" when expecting \"{\"", com_token);

		if (!ent)
			ent = g_game.edicts;
		else
			ent = G_Spawn();

		entities = G_ParseEntity(entities, ent);

		// some ents don't belong in deathmatch
		if (ent != g_game.edicts) {

			// legacy levels may require this
			if (ent->locals.spawn_flags & SF_NOT_DEATHMATCH) {
				G_FreeEdict(ent);
				inhibit++;
				continue;
			}

			// emits and models are client sided
			if (!g_strcmp0(ent->class_name, "misc_emit") || !g_strcmp0(ent->class_name, "misc_model")) {
				G_FreeEdict(ent);
				inhibit++;
				continue;
			}

			// lights aren't even used
			if (!g_strcmp0(ent->class_name, "light") || !g_strcmp0(ent->class_name, "light_spot")) {
				G_FreeEdict(ent);
				inhibit++;
				continue;
			}

			// strip away unsupported flags
			ent->locals.spawn_flags &= ~(SF_NOT_EASY | SF_NOT_MEDIUM | SF_NOT_HARD | SF_NOT_COOP
					| SF_NOT_DEATHMATCH);
		}

		// retain the map-specified origin for respawns
		VectorCopy(ent->s.origin, ent->locals.map_origin);

		G_SpawnEntity(ent);

		if (g_level.gameplay > 1 && ent->locals.item) { // now that we've spawned them, hide them
			ent->sv_flags |= SVF_NO_CLIENT;
			ent->solid = SOLID_NOT;
			ent->locals.next_think = 0;
		}
	}

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

	G_InitEntityTeams();

	G_InitMedia();

	G_ResetTeams();

	G_ResetVote();
}
Exemplo n.º 23
0
/*QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST
Any brush that you want to explode or break apart.  If you want an
ex0plosion, set dmg and it will do a radius explosion of that amount
at the center of the bursh.

If targeted it will not be shootable.

health defaults to 100.

mass defaults to 75.  This determines how much debris is emitted when
it explodes.  You get one large chunk per 100 of mass (up to 8) and
one small chunk per 25 of mass (up to 16).  So 800 gives the most.
*/
void func_explosive_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
	vec3_t	origin;
	vec3_t	chunkorigin;
	vec3_t	size;
	int		count;
	int		mass;

	// bmodel origins are (0 0 0), we need to adjust that here
	VectorScale (self->size, 0.5, size);
	VectorAdd (self->absmin, size, origin);
	VectorCopy (origin, self->s.origin);

	self->takedamage = DAMAGE_NO;

	if (self->dmg)
		T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE);

	VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity);
	VectorNormalize (self->velocity);
	VectorScale (self->velocity, 150, self->velocity);

	// start chunks towards the center
	VectorScale (size, 0.5, size);

	mass = self->mass;
	if (!mass)
		mass = 75;

	// big chunks
	if (mass >= 100)
	{
		count = mass / 100;
		if (count > 8)
			count = 8;
		while(count--)
		{
			chunkorigin[0] = origin[0] + crandom() * size[0];
			chunkorigin[1] = origin[1] + crandom() * size[1];
			chunkorigin[2] = origin[2] + crandom() * size[2];
			ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin);
		}
	}

	// small chunks
	count = mass / 25;
	if (count > 16)
		count = 16;
	while(count--)
	{
		chunkorigin[0] = origin[0] + crandom() * size[0];
		chunkorigin[1] = origin[1] + crandom() * size[1];
		chunkorigin[2] = origin[2] + crandom() * size[2];
		ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin);
	}

	G_UseTargets (self, attacker);

	if (self->dmg)
		BecomeExplosion1 (self);
	else
		G_FreeEdict (self);
}
Exemplo n.º 24
0
void SP_misc_viper (edict_t *ent)
{
	if (!ent->target)
	{
		gi.dprintf ("misc_viper without a target at %s\n", vtos(ent->absmin));
		G_FreeEdict (ent);
		return;
	}

	if (ent->spawnflags & 1)
	{
		ent->s.effects |= EF_ROCKET;
		ent->spawnflags &= ~1; // turn this off so that it doesn't mess up the trains
	}

	if (!ent->speed)
		ent->speed = 300;

	ent->movetype = MOVETYPE_PUSH;

	if (ent->spawnflags & 2)
	{
		ent->solid = SOLID_BBOX;
	}
	else
	{
		ent->solid = SOLID_NOT;
	}

	if(ent->model)
	{
		ent->s.modelindex = gi.modelindex (ent->model);
	}
	else
	{
		ent->s.modelindex = gi.modelindex ("models/ships/viper/tris.md2");
	}

	if(ent->model2)
	{
		ent->s.modelindex2 = gi.modelindex (ent->model2);
	}

	if(ent->model3)
	{
		ent->s.modelindex3 = gi.modelindex (ent->model3);
	}

	if(ent->model4)
	{
		ent->s.modelindex4 = gi.modelindex (ent->model4);
	}

	if (!(ent->spawnflags & 4))
	{
		VectorSet (ent->mins, -16, -16, 0);
		VectorSet (ent->maxs, 16, 16, 32);
	}

	ent->think = func_train_find;
	ent->nextthink = level.time + FRAMETIME;
	ent->use = misc_viper_use;
	ent->svflags |= SVF_NOCLIENT;
	ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed;

	gi.linkentity (ent);
}
Exemplo n.º 25
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 (!stricmp(level.mapname, "command") && !stricmp(ent->classname, "trigger_once") && !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);

	G_FindTeams ();

	PlayerTrail_Init ();

//ZOID
	CTFSpawn();
//ZOID
}
Exemplo n.º 26
0
/*QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8
Once this trigger is touched/used, any trigger_crosslevel_target with the same trigger number is automatically used when a level is started within the same unit.  It is OK to check multiple triggers.  Message, delay, target, and killtarget also work.
*/
void trigger_crosslevel_trigger_use (edict_t *self, edict_t *other, edict_t *activator)
{
	game.serverflags |= self->spawnflags;
	G_FreeEdict (self);
}
Exemplo n.º 27
0
void pendulum_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
    // Mostly copied from func_explosive_explode. We can't use that function because
    // the origin is a bit different.

    vec3_t origin;
    vec3_t forward, left, up;
    vec3_t chunkorigin;
    vec3_t size;
    int    count;
    int    mass;

    // Particles originate from business end of pendulum
    AngleVectors(self->s.angles, forward, left, up);
    VectorScale(forward, self->move_origin[0], forward);
    VectorScale(left, -self->move_origin[1], left);
    VectorScale(up, self->move_origin[2], up);
    VectorAdd(self->s.origin, forward, origin);
    VectorAdd(origin, left, origin);
    VectorAdd(origin, up, origin);

    self->mass      *= 2;
    self->takedamage = DAMAGE_NO;

    VectorSubtract(origin, self->enemy->s.origin, self->velocity);
    VectorNormalize(self->velocity);
    VectorScale(self->velocity, 150, self->velocity);

    // start chunks towards the center
    VectorScale(size, 0.5, size);

    mass = self->mass;
    if (!mass)
    {
        mass = 75;
    }

    // big chunks
    if (mass >= 100)
    {
        count = mass / 100;
        if (count > 8)
        {
            count = 8;
        }
        while (count--)
        {
            chunkorigin[0] = origin[0] + crandom() * size[0];
            chunkorigin[1] = origin[1] + crandom() * size[1];
            chunkorigin[2] = origin[2] + crandom() * size[2];
            ThrowDebris(self, "models/objects/debris1/tris.md2", 1, chunkorigin, 0, 0);
        }
    }

    // small chunks
    count = mass / 25;
    if (count > 16)
    {
        count = 16;
    }
    while (count--)
    {
        chunkorigin[0] = origin[0] + crandom() * size[0];
        chunkorigin[1] = origin[1] + crandom() * size[1];
        chunkorigin[2] = origin[2] + crandom() * size[2];
        ThrowDebris(self, "models/objects/debris2/tris.md2", 2, chunkorigin, 0, 0);
    }
    G_FreeEdict(self);
}
Exemplo n.º 28
0
/*QUAKED dm_props_banner (.5 0 1) (-4 -4 -4) (4 4 4)
Temp banner for teamplay

 style = team (1 / 2)
 scale = scale the size up/down (2 = double size)

model="models\props\temp\triangle\small.md2"
*/
void SP_dm_props_banner (edict_t *self)
{
//	vec3_t	end, bestnorm, bestend;
//	float bestdist;
//	int	x,y;
//	trace_t tr;

	if (!deathmatch_value || !teamplay->value)
	{	// remove
		G_FreeEdict (self);
		return;
	}
	
	if (!self->style)
	{
		gi.dprintf( "%s has invalid style (should be 1 or 2) at %s\n", self->classname, vtos(self->s.origin) );
		G_FreeEdict (self);
		return;
	}
/*
	// trace a line back, to get the wall, then go out
	{
		bestdist = 9999;

		for (x=-256; x<300; x+= 256)
		{
			VectorCopy( self->s.origin, end );
			end[0] = self->s.origin[0] + x;
			tr = gi.trace( self->s.origin, NULL, NULL, end, NULL, MASK_SOLID );
			if (tr.fraction < bestdist)
			{
				VectorCopy( tr.plane.normal, bestnorm );
				VectorCopy( tr.endpos, bestend );
				bestdist = tr.fraction;
			}
		}
		for (y=-256; y<300; y+= 256)
		{
			VectorCopy( self->s.origin, end );
			end[1] = self->s.origin[1] + y;
			tr = gi.trace( self->s.origin, NULL, NULL, end, NULL, MASK_SOLID );
			if (tr.fraction < bestdist)
			{
				VectorCopy( tr.plane.normal, bestnorm );
				VectorCopy( tr.endpos, bestend );
				bestdist = tr.fraction;
			}
		}

		vectoangles( bestnorm, self->s.angles );

		VectorMA( bestend, 40 * self->cast_info.scale, bestnorm, self->s.origin );
	}

*/
// Ridah, 1-jun-99, use flag models for now
#if 1
	{
		void think_flag (edict_t *self);

//		self->solid = SOLID_BBOX;
		self->movetype = MOVETYPE_NONE;

		if (self->style == 2)
		{
			self->model = "models/props/flag/flag1.md2";
		}
		else
		{
			self->model = "models/props/flag/flag3.md2";
		}

		self->s.modelindex = gi.modelindex (self->model);

		self->s.renderfx2 |= RF2_NOSHADOW;
		self->s.renderfx |= RF_MINLIGHT;

		if (!self->cast_info.scale)
			self->cast_info.scale = 1;

		self->s.scale = (self->cast_info.scale - 1);

//		VectorMA( bestend, 40 * self->cast_info.scale, bestnorm, self->s.origin );

		self->cast_info.scale *= 0.3;

		gi.linkentity (self);

		self->s.effects |= EF_ANIM_ALLFAST_NEW;
		self->s.renderfx2 |= RF2_MODULUS_FRAME;
		self->s.renderfx2 |= RDF_NOLERP;

// Disabled, doesn't animate much, and uses bandwidth
//		self->nextthink = level.time + FRAMETIME *2;
//		self->think = think_flag;
	}

#else // TRIANGULAR ROTATING ICONS

	self->solid = SOLID_NOT;
	self->movetype = MOVETYPE_NONE;

	self->s.skinnum = self->style - 1;

	self->s.renderfx2 |= RF2_NOSHADOW;	
	self->s.renderfx |= RF_MINLIGHT;

	if (!self->cast_info.scale)
		self->cast_info.scale = 1;

	self->s.scale = self->cast_info.scale - 1;

	self->s.modelindex = gi.modelindex ("models/props/temp/triangle/small.md2");

	gi.linkentity (self);

	{
		edict_t *arm;

		arm = G_Spawn();
		arm->solid = self->solid;
		arm->movetype = self->movetype;
		arm->s.renderfx2 |= RF2_NOSHADOW;
		arm->s.scale = self->s.scale;

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

		arm->s.modelindex = gi.modelindex ("models/props/temp/triangle/arm.md2");
		gi.linkentity (arm);
	}

	VectorCopy( self->s.angles, self->last_step_pos );
	VectorClear( self->move_angles );
#endif
}
Exemplo n.º 29
0
Arquivo: g_utils.c Projeto: qbism/tmg
void Think_Delay (edict_t *ent)
{
	G_UseTargets (ent, ent->activator);
	G_FreeEdict (ent);
}
Exemplo n.º 30
0
/*
================
droptofloor
================
*/
void droptofloor (edict_t *ent)
{
	trace_t		tr;
	vec3_t		dest;
	float		*v;

	v = tv(-15,-15,-15);
	VectorCopy (v, ent->mins);
	v = tv(15,15,15);
	VectorCopy (v, ent->maxs);

	if (ent->model)
		gi.setmodel (ent, ent->model);
	else
		gi.setmodel (ent, ent->item->world_model);
	ent->solid = SOLID_TRIGGER;
	ent->movetype = MOVETYPE_TOSS;  
	ent->touch = Touch_Item;

	v = tv(0,0,-128);
	VectorAdd (ent->s.origin, v, dest);

	tr = gi.trace (ent->s.origin, ent->mins, ent->maxs, dest, ent, MASK_SOLID);
	if (tr.startsolid)
	{
		gi.dprintf(DEVELOPER_MSG_GAME, "droptofloor: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin));
		G_FreeEdict (ent);
		return;
	}

	VectorCopy (tr.endpos, ent->s.origin);

	if (ent->team)
	{
		ent->flags &= ~FL_TEAMSLAVE;
		ent->chain = ent->teamchain;
		ent->teamchain = NULL;

		ent->svflags |= SVF_NOCLIENT;
		ent->solid = SOLID_NOT;
		if (ent == ent->teammaster)
		{
			ent->nextthink = level.time + FRAMETIME;
			ent->think = DoRespawn;
		}
	}

	if (ent->spawnflags & ITEM_NO_TOUCH)
	{
		ent->solid = SOLID_BBOX;
		ent->touch = NULL;
		ent->s.effects &= ~EF_ROTATE;
		ent->s.renderfx &= ~RF_GLOW;
	}

	if (ent->spawnflags & ITEM_TRIGGER_SPAWN)
	{
		ent->svflags |= SVF_NOCLIENT;
		ent->solid = SOLID_NOT;
		ent->use = Use_Item;
	}

	gi.linkentity (ent);
}