/*
=============
SpawnCorpse

A player is respawning, so make an entity that looks
just like the existing corpse to leave behind.
=============
*/
void SpawnCorpse( gentity_t *ent )
{
  gentity_t   *body;
  int         contents;
  vec3_t      origin, dest;
  trace_t     tr;
  float       vDiff;

  VectorCopy( ent->r.currentOrigin, origin );

  trap_UnlinkEntity( ent );

  // if client is in a nodrop area, don't leave the body
  contents = trap_PointContents( origin, -1 );
  if( contents & CONTENTS_NODROP )
    return;

  body = G_Spawn( );

  VectorCopy( ent->s.apos.trBase, body->s.angles );
  body->s.eFlags = EF_DEAD;
  body->s.eType = ET_CORPSE;
  body->s.number = body - g_entities;
  body->timestamp = level.time;
  body->s.event = 0;
  body->r.contents = CONTENTS_CORPSE;
  body->s.clientNum = ent->client->ps.stats[ STAT_CLASS ];
  body->nonSegModel = ent->client->ps.persistant[ PERS_STATE ] & PS_NONSEGMODEL;

  if( ent->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
    body->classname = "humanCorpse";
  else
    body->classname = "alienCorpse";

  body->s.misc = MAX_CLIENTS;

  body->think = BodySink;
  body->nextthink = level.time + 20000;

  body->s.legsAnim = ent->s.legsAnim;

  if( !body->nonSegModel )
  {
    switch( body->s.legsAnim & ~ANIM_TOGGLEBIT )
    {
      case BOTH_DEATH1:
      case BOTH_DEAD1:
        body->s.torsoAnim = body->s.legsAnim = BOTH_DEAD1;
        break;
      case BOTH_DEATH2:
      case BOTH_DEAD2:
        body->s.torsoAnim = body->s.legsAnim = BOTH_DEAD2;
        break;
      case BOTH_DEATH3:
      case BOTH_DEAD3:
      default:
        body->s.torsoAnim = body->s.legsAnim = BOTH_DEAD3;
        break;
    }
  }
  else
  {
    switch( body->s.legsAnim & ~ANIM_TOGGLEBIT )
    {
      case NSPA_DEATH1:
      case NSPA_DEAD1:
        body->s.legsAnim = NSPA_DEAD1;
        break;
      case NSPA_DEATH2:
      case NSPA_DEAD2:
        body->s.legsAnim = NSPA_DEAD2;
        break;
      case NSPA_DEATH3:
      case NSPA_DEAD3:
      default:
        body->s.legsAnim = NSPA_DEAD3;
        break;
    }
  }

  body->takedamage = qfalse;

  body->health = ent->health = ent->client->ps.stats[ STAT_HEALTH ];
  ent->health = 0;

  //change body dimensions
  BG_ClassBoundingBox( ent->client->ps.stats[ STAT_CLASS ], NULL, NULL, NULL, body->r.mins, body->r.maxs );
  vDiff = body->r.mins[ 2 ] - ent->r.mins[ 2 ];

  //drop down to match the *model* origins of ent and body
  VectorSet( dest, origin[ 0 ], origin[ 1 ], origin[ 2 ] - vDiff );
  trap_Trace( &tr, origin, body->r.mins, body->r.maxs, dest, body->s.number, body->clipmask );
  VectorCopy( tr.endpos, origin );

  G_SetOrigin( body, origin );
  VectorCopy( origin, body->s.origin );
  body->s.pos.trType = TR_GRAVITY;
  body->s.pos.trTime = level.time;
  VectorCopy( ent->client->ps.velocity, body->s.pos.trDelta );

  VectorCopy ( body->s.pos.trBase, body->r.currentOrigin );
  trap_LinkEntity( body );
}
Example #2
0
/*
==============================
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;
			}
		}
	}

//	gi.dprintf("TARGET: activating %s\n", ent->target);

//
// 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_stricmp(t->classname, "func_areaportal") &&
				(!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(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;
			}
		}
	}
}
Example #3
0
//----------------------------------------------------------
void eweb_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod,int dFlags,int hitLoc )
{
	vec3_t org;

	// turn off any firing animations it may have been doing
	self->s.frame = self->startFrame = self->endFrame = 0;
	self->svFlags &= ~(SVF_ANIMATING|SVF_PLAYER_USABLE);
	
			
	self->health = 0;
//	self->s.weapon = WP_EMPLACED_GUN; // we need to be able to switch back to the old weapon

	self->takedamage = qfalse;
	self->lastEnemy = attacker;

	if ( self->activator && self->activator->client )
	{
		if ( self->activator->NPC )
		{
			vec3_t right;

			// radius damage seems to throw them, but add an extra bit to throw them away from the weapon
			AngleVectors( self->currentAngles, NULL, right, NULL );
			VectorMA( self->activator->client->ps.velocity, 140, right, self->activator->client->ps.velocity );
			self->activator->client->ps.velocity[2] = -100;

			// kill them
			self->activator->health = 0;
			self->activator->client->ps.stats[STAT_HEALTH] = 0;
		}

		// kill the players emplaced ammo, cheesy way to keep the gun from firing
		self->activator->client->ps.ammo[weaponData[WP_EMPLACED_GUN].ammoIndex] = 0;
	}

	self->e_PainFunc = painF_NULL;

	if ( self->target )
	{
		G_UseTargets( self, attacker );
	}

	G_RadiusDamage( self->currentOrigin, self, self->splashDamage, self->splashRadius, self, MOD_UNKNOWN );

	VectorCopy( self->currentOrigin,  org );
	org[2] += 20;

	G_PlayEffect( "emplaced/explode", org );

	// Turn the top of the eweb off.
#define TURN_OFF			0x00000100//G2SURFACEFLAG_NODESCENDANTS
	gi.G2API_SetSurfaceOnOff( &self->ghoul2[self->playerModel], "eweb_damage", TURN_OFF );

	// create some persistent smoke by using a dynamically created fx runner
	gentity_t *ent = G_Spawn();

	if ( ent )
	{
		ent->delay = 200;
		ent->random = 100;

		ent->fxID = G_EffectIndex( "emplaced/dead_smoke" );

		ent->e_ThinkFunc = thinkF_fx_runner_think; 
		ent->nextthink = level.time + 50;

		// move up above the gun origin
		VectorCopy( self->currentOrigin, org );
		org[2] += 35;
		G_SetOrigin( ent, org );
		VectorCopy( org, ent->s.origin );

		VectorSet( ent->s.angles, -90, 0, 0 ); // up
		G_SetAngles( ent, ent->s.angles );

		gi.linkentity( ent );
	}

	G_ActivateBehavior( self, BSET_DEATH );
}
Example #4
0
void G_FindCraneParts()
{
	vec3_t  dist;
	edict_t *cable;
	edict_t *control;
	edict_t *beam;
	edict_t *hoist;
	edict_t *hook;
	edict_t *light;
	edict_t *p1, *p2;

	edict_t	*e;
	int		direction;
	int		i;

	for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++)
	{
		if (!e->inuse)
			continue;
		if (!e->classname)
			continue;
		if (Q_strcasecmp(e->classname,"crane_control"))
			continue;

		control = e;
		beam = G_Find(NULL,FOFS(targetname),control->target);
		if(!beam)
		{
			gi.dprintf("Crane_control with no target\n");
			G_FreeEdict(control);
			return;
		}
		// get path_corner locations to determine movement direction
		p1 = G_Find(NULL,FOFS(targetname),beam->pathtarget);
		if(!p1->target)
		{
			gi.dprintf("Only 1 path_corner in pathtarget sequence for crane_beam\n"
				"(2 are required)\n");
			G_FreeEdict(control);
			G_FreeEdict(beam);
			G_FreeEdict(p1);
			return;
		}
		p2 = G_Find(NULL,FOFS(targetname),p1->target);
		VectorSubtract(p1->s.origin,p2->s.origin,dist);
		if(fabs(dist[0]) > fabs(dist[1]))
		{
			VectorSet(beam->movedir, 1.0,0.0,0.0);
			direction = 0;
			if(p1->s.origin[0] < p2->s.origin[0])
			{
				VectorCopy(p1->s.origin,beam->pos1);
				VectorCopy(p2->s.origin,beam->pos2);
			}
			else
			{
				VectorCopy(p2->s.origin,beam->pos1);
				VectorCopy(p1->s.origin,beam->pos2);
			}
		}
		else
		{
			VectorSet(beam->movedir, 0.0,1.0,0.0);
			direction = 1;
			if(p1->s.origin[1] < p2->s.origin[1])
			{
				VectorCopy(p1->s.origin,beam->pos1);
				VectorCopy(p2->s.origin,beam->pos2);
			}
			else
			{
				VectorCopy(p2->s.origin,beam->pos1);
				VectorCopy(p1->s.origin,beam->pos2);
			}
		}
		hoist = G_Find(NULL,FOFS(targetname),beam->target);
		if(!hoist)
		{
			gi.dprintf("Crane_beam with no target\n");
			G_FreeEdict(control);
			G_FreeEdict(beam);
			return;
		}
		// get path_corner locations to determine movement direction
		p1 = G_Find(NULL,FOFS(targetname),hoist->pathtarget);
		if(!p1->target)
		{
			gi.dprintf("Only 1 path_corner in pathtarget sequence for crane_hoist\n"
				"(2 are required)\n");
			G_FreeEdict(control);
			G_FreeEdict(beam);
			G_FreeEdict(hoist);
			G_FreeEdict(p1);
			return;
		}
		p2 = G_Find(NULL,FOFS(targetname),p1->target);
		VectorSubtract(p1->s.origin,p2->s.origin,dist);
		if(fabs(dist[0]) > fabs(dist[1]))
		{
			VectorSet(hoist->movedir, 1.0,0.0,0.0);
			if(p1->s.origin[0] < p2->s.origin[0])
			{
				VectorCopy(p1->s.origin,hoist->pos1);
				VectorCopy(p2->s.origin,hoist->pos2);
			}
			else
			{
				VectorCopy(p2->s.origin,hoist->pos1);
				VectorCopy(p1->s.origin,hoist->pos2);
			}
		}
		else
		{
			VectorSet(hoist->movedir, 0.0,1.0,0.0);
			if(p1->s.origin[1] < p2->s.origin[1])
			{
				VectorCopy(p1->s.origin,hoist->pos1);
				VectorCopy(p2->s.origin,hoist->pos2);
			}
			else
			{
				VectorCopy(p2->s.origin,hoist->pos1);
				VectorCopy(p1->s.origin,hoist->pos2);
			}
		}

		// correct spawnflags for beam and hoist speakers
		if(beam->speaker)
		{
			if(direction)
				beam->speaker->spawnflags = 2;
			else
				beam->speaker->spawnflags = 1;
		}
		if(hoist->speaker)
		{
			if(direction)
				hoist->speaker->spawnflags = 1;
			else
				hoist->speaker->spawnflags = 2;
		}

		hook = G_Find(NULL,FOFS(targetname),hoist->target);
		if(!hook)
		{
			gi.dprintf("Crane hoist with no target\n");
			G_FreeEdict(control);
			G_FreeEdict(beam);
			G_FreeEdict(hoist);
			return;
		}
		// Turn on hook ambient sound if control is on
		// We use a trick here... since hook by definition cannot
		// be moving unless control is on, then with control off
		// we set hook speaker spawnflag to require hook to be
		// moving to play
		if(hook->speaker)
			hook->speaker->spawnflags = 1 - (control->spawnflags & 1);
			
		// Get offset from hook origin to hoist origin, so we can
		// correct timing problems
		VectorSubtract(hook->s.origin,hoist->s.origin,hook->offset);

		// get path_corner locations to determine movement direction
		p1 = G_Find(NULL,FOFS(targetname),hook->pathtarget);
		if(!p1->target)
		{
			gi.dprintf("Only 1 path_corner in pathtarget sequence for crane_hook\n"
				"(2 are required)\n");
			G_FreeEdict(control);
			G_FreeEdict(beam);
			G_FreeEdict(hoist);
			G_FreeEdict(hook);
			G_FreeEdict(p1);
			return;
		}
		p2 = G_Find(NULL,FOFS(targetname),p1->target);
		VectorSet(hook->movedir,0.0,0.0,1.0);
		if(p1->s.origin[2] < p2->s.origin[2])
		{
			VectorCopy(p1->s.origin,hook->pos1);
			VectorCopy(p2->s.origin,hook->pos2);
		}
		else
		{
			VectorCopy(p2->s.origin,hook->pos1);
			VectorCopy(p1->s.origin,hook->pos2);
		}

		control->crane_control = control;
		control->crane_beam    = beam;
		control->crane_hoist   = hoist;
		control->crane_hook    = hook;
		if(!beam->crane_control) beam->crane_control = control;
		if(control->team)
		{
			beam->crane_control = control;
			if(beam->flags & FL_TEAMSLAVE)
				beam->crane_onboard_control = beam->teammaster;
			else
				beam->crane_onboard_control = beam->teamchain;
		}
		else
			beam->crane_onboard_control = NULL;
		beam->crane_hoist    = hoist;
		beam->crane_hook     = hook;
		hoist->crane_control = beam->crane_control;
		hoist->crane_beam    = beam;
		hoist->crane_hook    = hook;
		hook->crane_control  = beam->crane_control;
		hook->crane_beam     = beam;
		hook->crane_hoist    = hoist;
		if(control->spawnflags & 4)
		{
			beam->dmg  = 0;
			hoist->dmg = 0;
			hook->dmg  = 0;
		}

		if(hook->crane_cable == NULL)
		{
			int   frame;
			float length;

			cable = G_Spawn();
			cable->classname = "crane_cable";
			VectorAdd(hook->absmin,hook->absmax,cable->s.origin);
			VectorScale(cable->s.origin,0.5,cable->s.origin);
			VectorAdd(cable->s.origin,hook->move_origin,cable->s.origin);
			VectorSubtract(cable->s.origin,hook->s.origin,cable->offset);
			cable->s.origin[2] = hoist->absmax[2] - 2;
			cable->model = "models/cable/tris.md2";
			gi.setmodel(cable,cable->model);
			cable->s.skinnum = 0;
			length = hoist->absmax[2]-1 - hook->absmax[2];
			frame = (int)(length/CABLE_SEGMENT);
			if((frame+1)*CABLE_SEGMENT < length) frame++;
			frame = max(0,min(frame,19));
			cable->s.frame = frame;
			cable->solid = SOLID_NOT;
			cable->movetype = MOVETYPE_STOP;
			VectorSet(cable->mins,-2,-2,length);
			VectorSet(cable->maxs, 2, 2,0);
			gi.linkentity(cable);
			beam->crane_cable    = cable;
			hoist->crane_cable   = cable;
			hook->crane_cable    = cable;
			cable->crane_control = control;
			cable->crane_beam    = beam;
			cable->crane_hoist   = hoist;
			cable->crane_hook    = hook;
		}
		control->crane_cable = hook->crane_cable;

		if((hook->spawnflags & 1) && (hook->crane_light == NULL))
		{
			light = G_Spawn();
			light->s.origin[0] = (hook->absmin[0] + hook->absmax[0])/2;
			light->s.origin[1] = (hook->absmin[1] + hook->absmax[1])/2;
			light->s.origin[2] = hook->absmin[2] + 8;
			VectorSet(light->mins,-32,-32,-512);
			VectorSet(light->maxs, 32, 32,   0);
			light->solid      = SOLID_NOT;
			light->movetype   = MOVETYPE_NOCLIP;
			light->s.effects  = EF_SPHERETRANS;
			light->s.modelindex = gi.modelindex("sprites/point.sp2");
			light->s.effects = EF_HYPERBLASTER;
			light->svflags       = SVF_NOCLIENT;
			VectorSubtract(light->s.origin,hook->s.origin,light->offset);
			gi.linkentity(light);
			beam->crane_light    = light;
			hook->crane_light    = light;
			cable->crane_light   = light;
		}
		control->crane_light = hook->crane_light;

		// If control is NOT onboard, move beam speaker (if any) to end of
		// beam closest to control
		if(!beam->crane_onboard_control && beam->speaker) {
			if(beam->movedir[0] > 0) {
				if(control->absmin[1]+control->absmax[1] < beam->absmin[1]+beam->absmax[1])
					beam->speaker->s.origin[1] = beam->absmin[1];
				else
					beam->speaker->s.origin[1] = beam->absmax[1];
			} else {
				if(control->absmin[0]+control->absmax[0] < beam->absmin[0]+beam->absmax[0])
					beam->speaker->s.origin[0] = beam->absmin[0];
				else
					beam->speaker->s.origin[0] = beam->absmax[0];
			}
			beam->speaker->s.origin[2] = control->s.origin[2] + 32;
			VectorSubtract(beam->speaker->s.origin,beam->s.origin,beam->speaker->offset);
		}
	}
}
Example #5
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, qboolean 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();

	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();
}
Example #6
0
File: g_spawn.c Project: qbism/qbq2
/*
==============
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_strcasecmp(level.mapname, "command") && !Q_strcasecmp(ent->classname, "trigger_once") && !Q_strcasecmp(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 ();
}
Example #7
0
void SP_crane_beam (edict_t *self)
{
	vec3_t  origin;
	edict_t *speaker;

	gi.setmodel (self, self->model);
	VectorAdd(self->absmin,self->absmax,origin);
	VectorScale(origin,0.5,origin);

	if (!self->targetname)
	{
		gi.dprintf ("crane_beam with no targetname at %s\n", vtos(origin));
		G_FreeEdict (self);
		return;
	}
	if (!self->target)
	{
		gi.dprintf ("crane_beam with no target at %s\n", vtos(origin));
		G_FreeEdict (self);
		return;
	}
	if (!self->pathtarget)
	{
		gi.dprintf ("crane_beam with no pathtarget at %s\n", vtos(origin));
		G_FreeEdict (self);
		return;
	}
	self->classname = "crane_beam";
	self->solid     = SOLID_BSP;
	self->movetype  = MOVETYPE_PUSH;

	if(!self->speed) self->speed = 160;
	self->moveinfo.speed = self->speed;
	if(st.noise)
		self->noise_index = gi.soundindex(st.noise);
	else
		self->noise_index = 0;

#ifdef LOOP_SOUND_ATTENUATION
	if (self->attenuation <= 0)
		self->attenuation = ATTN_IDLE;
#endif

	gi.linkentity (self);

	if(self->noise_index && !VectorLength(self->s.origin) )
	{
		speaker = G_Spawn();
		speaker->classname   = "moving_speaker";
		speaker->s.sound     = 0;
		speaker->volume      = 1;
		speaker->attenuation = self->attenuation; // was 1
		speaker->think       = Moving_Speaker_Think;
		speaker->nextthink   = level.time + 2*FRAMETIME;
		speaker->spawnflags  = 7;       // owner must be moving to play
		speaker->owner       = self;    // this will be changed later when we know
		                                // controls are spawned
		self->speaker        = speaker;
		VectorAdd(self->absmin,self->absmax,speaker->s.origin);
		VectorScale(speaker->s.origin,0.5,speaker->s.origin);
		VectorSubtract(speaker->s.origin,self->s.origin,speaker->offset);
	}
}
Example #8
0
// Add a player entity to another player's multiview list
void G_smvAddView(gentity_t *ent, int pID)
{
	int       i;
	mview_t   *mv = NULL;
	gentity_t *v;

	if (pID >= MAX_MVCLIENTS || G_smvLocateEntityInMVList(ent, pID, qfalse))
	{
		return;
	}

	for (i = 0; i < MULTIVIEW_MAXVIEWS; i++)
	{
		if (!ent->client->pers.mv[i].fActive)
		{
			mv = &ent->client->pers.mv[i];
			break;
		}
	}

	if (mv == NULL)
	{
		CP(va("print \"[lof]** [lon]Sorry, no more MV slots available (all[lof] %d [lon]in use)[lof]\n\"", MULTIVIEW_MAXVIEWS));
		return;
	}

	mv->camera = G_Spawn();
	if (mv->camera == NULL)
	{
		return;
	}

	if (ent->client->sess.sessionTeam == TEAM_SPECTATOR &&  /*ent->client->sess.sessionTeam != TEAM_SPECTATOR ||*/
	    ent->client->sess.spectatorState == SPECTATOR_FOLLOW)
	{
		SetTeam(ent, "s", qtrue, -1, -1, qfalse);
	}
	else if (ent->client->sess.sessionTeam != TEAM_SPECTATOR && !(ent->client->ps.pm_flags & PMF_LIMBO))
	{
		limbo(ent, qtrue);
	}

	ent->client->ps.clientNum        = ent - g_entities;
	ent->client->sess.spectatorState = SPECTATOR_FREE;

	ent->client->pers.mvCount++;
	mv->fActive = qtrue;
	mv->entID   = pID;

	v                 = mv->camera;
	v->classname      = "misc_portal_surface";
	v->r.svFlags      = SVF_PORTAL | SVF_SINGLECLIENT; // Only merge snapshots for the target client
	v->r.singleClient = ent->s.number;
	v->s.eType        = ET_PORTAL;

	VectorClear(v->r.mins);
	VectorClear(v->r.maxs);
	trap_LinkEntity(v);

	v->target_ent = &g_entities[pID];
	v->TargetFlag = pID;
	v->tagParent  = ent;

	G_smvUpdateClientCSList(ent);
}
Example #9
0
/*
==============================
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;
	edict_t		*master;
	qboolean	done = false;

//
// 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)))
		{
			// PMM - if this entity is part of a train, cleanly remove it
			if (t->flags & FL_TEAMSLAVE)
			{
//				if ((g_showlogic) && (g_showlogic->value))
//					gi.dprintf ("Removing %s from train!\n", t->classname);

				if (t->teammaster)
				{
					master = t->teammaster;
					while (!done)
					{
						if (master->teamchain == t)
						{
							master->teamchain = t->teamchain;
							done = true;
						}
						master = master->teamchain;
						if (!master)
						{
//							if ((g_showlogic) && (g_showlogic->value))
//								gi.dprintf ("Couldn't find myself in master's chain, ignoring!\n");
						}
					}
				}
				else
				{
//					if ((g_showlogic) && (g_showlogic->value))
//						gi.dprintf ("No master to free myself from, ignoring!\n");
				}
			}
			// PMM
			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_stricmp(t->classname, "func_areaportal") &&
				(!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(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;
			}
		}
	}
}
Example #10
0
/*
* W_Fire_Instagun_Strong
*/
void W_Fire_Instagun( edict_t *self, vec3_t start, vec3_t dir, float damage, int knockback,
					  int stun, int radius, int range, int mod, int timeDelta ) {
	vec3_t from, end;
	trace_t	tr;
	edict_t	*ignore, *event, *hit;
	int hit_movetype;
	int mask;
	bool missed = true;
	int dmgflags = 0;

	if( GS_Instagib() ) {
		damage = 9999;
	}

	VectorMA( start, range, dir, end );
	VectorCopy( start, from );
	ignore = self;
	mask = MASK_SHOT;
	if( GS_RaceGametype() ) {
		mask = MASK_SOLID;
	}
	tr.ent = -1;
	while( ignore ) {
		G_Trace4D( &tr, from, NULL, NULL, end, ignore, mask, timeDelta );
		VectorCopy( tr.endpos, from );
		ignore = NULL;
		if( tr.ent == -1 ) {
			break;
		}

		// allow trail to go through SOLID_BBOX entities (players, gibs, etc)
		hit = &game.edicts[tr.ent];
		hit_movetype = hit->movetype; // backup the original movetype as the entity may "die"

		if( !ISBRUSHMODEL( hit->s.modelindex ) ) {
			ignore = hit;
		}

		if( ( hit != self ) && ( hit->takedamage ) ) {
			G_Damage( hit, self, self, dir, dir, tr.endpos, damage, knockback, stun, dmgflags, mod );

			// spawn a impact event on each damaged ent
			event = G_SpawnEvent( EV_INSTA_EXPLOSION, DirToByte( tr.plane.normal ), tr.endpos );
			event->s.ownerNum = ENTNUM( self );
			event->s.firemode = FIRE_MODE_STRONG;
			if( hit->r.client ) {
				missed = false;
			}
		}

		// some entity was touched
		if( hit == world
			|| hit_movetype == MOVETYPE_NONE
			|| hit_movetype == MOVETYPE_PUSH ) {
			if( g_instajump->integer && self && self->r.client ) {
				// create a temporary inflictor entity
				edict_t *inflictor;

				inflictor = G_Spawn();
				inflictor->s.solid = SOLID_NOT;
				inflictor->timeDelta = 0;
				VectorCopy( tr.endpos, inflictor->s.origin );
				inflictor->s.ownerNum = ENTNUM( self );
				inflictor->projectileInfo.maxDamage = 0;
				inflictor->projectileInfo.minDamage = 0;
				inflictor->projectileInfo.maxKnockback = knockback;
				inflictor->projectileInfo.minKnockback = 1;
				inflictor->projectileInfo.stun = 0;
				inflictor->projectileInfo.radius = radius;

				G_RadiusDamage( inflictor, self, &tr.plane, NULL, mod );

				G_FreeEdict( inflictor );
			}
			break;
		}
	}

	if( missed && self->r.client ) {
		G_AwardPlayerMissedElectrobolt( self, mod );
	}

	// send the weapon fire effect
	event = G_SpawnEvent( EV_INSTATRAIL, ENTNUM( self ), start );
	VectorScale( dir, 1024, event->s.origin2 );
}
Example #11
0
/*
==================
AICast_CheckLoadGame

  at the start of a level, the game is either saved, or loaded

  we must wait for all AI to spawn themselves, and a real client to connect
==================
*/
void AICast_CheckLoadGame( void ) {
    char loading[4];
    gentity_t *ent = NULL; // TTimo: VC6 'may be used without having been init'
    qboolean ready;
    cast_state_t *pcs;

    // have we already done the save or load?
    if ( !saveGamePending ) {
        return;
    }

    // tell the cgame NOT to render the scene while we are waiting for things to settle
    trap_Cvar_Set( "cg_norender", "1" );

    trap_Cvar_VariableStringBuffer( "savegame_loading", loading, sizeof( loading ) );

//	reloading = qtrue;
    trap_Cvar_Set( "g_reloading", "1" );

    if ( strlen( loading ) > 0 && atoi( loading ) != 0 ) {
        // screen should be black if we are at this stage
        trap_SetConfigstring( CS_SCREENFADE, va( "1 %i 1", level.time - 10 ) );

//		if (!reloading && atoi(loading) == 2) {
        if ( !( g_reloading.integer ) && atoi( loading ) == 2 ) {
            // (SA) hmm, this seems redundant when it sets it above...
//			reloading = qtrue;	// this gets reset at the Map_Restart() since the server unloads the game dll
            trap_Cvar_Set( "g_reloading", "1" );
        }

        ready = qtrue;
        if ( numSpawningCast != numcast ) {
            ready = qfalse;
        } else if ( !( ent = AICast_FindEntityForName( "player" ) ) ) {
            ready = qfalse;
        } else if ( !ent->client || ent->client->pers.connected != CON_CONNECTED ) {
            ready = qfalse;
        }

        if ( ready ) {
            trap_Cvar_Set( "savegame_loading", "0" ); // in-case it aborts
            saveGamePending = qfalse;
            G_LoadGame( NULL );     // always load the "current" savegame

            // RF, spawn a thinker that will enable rendering after the client has had time to process the entities and setup the display
            //trap_Cvar_Set( "cg_norender", "0" );
            ent = G_Spawn();
            ent->nextthink = level.time + 200;
            ent->think = AICast_EnableRenderingThink;

            // wait for the clients to return from faded screen
            //trap_SetConfigstring( CS_SCREENFADE, va("0 %i 1500", level.time + 500) );
            trap_SetConfigstring( CS_SCREENFADE, va( "0 %i 750", level.time + 500 ) );
            level.reloadPauseTime = level.time + 1100;

            // make sure sound fades up
            trap_SendServerCommand( -1, va( "snd_fade 1 %d", 2000 ) );  //----(SA)	added

            AICast_CastScriptThink();
        }
    } else {

        ready = qtrue;
        if ( numSpawningCast != numcast ) {
            ready = qfalse;
        } else if ( !( ent = AICast_FindEntityForName( "player" ) ) ) {
            ready = qfalse;
        } else if ( !ent->client || ent->client->pers.connected != CON_CONNECTED ) {
            ready = qfalse;
        }

        // not loading a game, we must be in a new level, so look for some persistant data to read in, then save the game
        if ( ready ) {
            G_LoadPersistant();     // make sure we save the game after we have brought across the items

            trap_Cvar_Set( "g_totalPlayTime", "0" );  // reset play time
            trap_Cvar_Set( "g_attempts", "0" );
            pcs = AICast_GetCastState( ent->s.number );
            pcs->totalPlayTime = 0;
            pcs->lastLoadTime = 0;
            pcs->attempts = 0;

            // RF, disabled, since the pregame menu turns this off after the button is pressed, this isn't
            // required here
            // RF, spawn a thinker that will enable rendering after the client has had time to process the entities and setup the display
            //trap_Cvar_Set( "cg_norender", "0" );
            //ent = G_Spawn();
            //ent->nextthink = level.time + 200;
            //ent->think = AICast_EnableRenderingThink;

            saveGamePending = qfalse;

            // wait for the clients to return from faded screen
//			trap_SetConfigstring( CS_SCREENFADE, va("0 %i 1500", level.time + 500) );
//			trap_SetConfigstring( CS_SCREENFADE, va("0 %i 750", level.time + 500) );
            // (SA) send a command that will be interpreted for both the screenfade and any other effects (music cues, pregame menu, etc)

// briefing menu will handle transition, just set a cvar for it to check for drawing the 'continue' button
            trap_SendServerCommand( -1, "rockandroll\n" );

            level.reloadPauseTime = level.time + 1100;

            AICast_CastScriptThink();
        }
    }
}
Example #12
0
gentity_t *SpawnObelisk( vec3_t origin, int team, int spawnflags) {
	trace_t		tr;
	vec3_t		dest;
	gentity_t	*ent;

	ent = G_Spawn();

	VectorCopy( origin, ent->s.origin );
	VectorCopy( origin, ent->s.pos.trBase );
	VectorCopy( origin, ent->r.currentOrigin );

	VectorSet( ent->r.mins, -15, -15, 0 );
	VectorSet( ent->r.maxs, 15, 15, 87 );

	ent->s.eType = ET_GENERAL;
	ent->flags = FL_NO_KNOCKBACK;

	if( g_gametype.integer == GT_OBELISK ) {
		ent->r.contents = CONTENTS_SOLID;
		ent->takedamage = qtrue;
		ent->health = g_obeliskHealth.integer;
		ent->die = ObeliskDie;
		ent->pain = ObeliskPain;
		ent->think = ObeliskRegen;
		ent->nextthink = level.time + g_obeliskRegenPeriod.integer * 1000;
	}
	if( g_gametype.integer == GT_HARVESTER ) {
		ent->r.contents = CONTENTS_TRIGGER;
		ent->touch = ObeliskTouch;
	}

	if ( spawnflags & 1 ) {
		// suspended
		G_SetOrigin( ent, ent->s.origin );
	} else {
		// mappers like to put them exactly on the floor, but being coplanar
		// will sometimes show up as starting in solid, so lif it up one pixel
		ent->s.origin[2] += 1;

		// drop to floor
		VectorSet( dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096 );
		trap_Trace( &tr, ent->s.origin, ent->r.mins, ent->r.maxs, dest, ent->s.number, MASK_SOLID );
		if ( tr.startsolid ) {
			ent->s.origin[2] -= 1;
			G_Printf( "SpawnObelisk: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin) );

			ent->s.groundEntityNum = ENTITYNUM_NONE;
			G_SetOrigin( ent, ent->s.origin );
		}
		else {
			// allow to ride movers
			ent->s.groundEntityNum = tr.entityNum;
			G_SetOrigin( ent, tr.endpos );
		}
	}

	ent->spawnflags = team;

	trap_LinkEntity( ent );

	return ent;
}
Example #13
0
/*
* ClientUserinfoChanged
* called whenever the player updates a userinfo variable.
* 
* The game can override any of the settings in place
* (forcing skins or names, etc) before copying it off.
*/
void ClientUserinfoChanged( edict_t *ent, char *userinfo )
{
	char *s;
	char oldname[MAX_INFO_VALUE];
	gclient_t *cl;

	int rgbcolor, i;

	assert( ent && ent->r.client );
	assert( userinfo && Info_Validate( userinfo ) );

	// check for malformed or illegal info strings
	if( !Info_Validate( userinfo ) )
	{
		trap_DropClient( ent, DROP_TYPE_GENERAL, "Error: Invalid userinfo" );
		return;
	}

	cl = ent->r.client;

	// ip
	s = Info_ValueForKey( userinfo, "ip" );
	if( !s )
	{
		trap_DropClient( ent, DROP_TYPE_GENERAL, "Error: Server didn't provide client IP" );
		return;
	}

	Q_strncpyz( cl->ip, s, sizeof( cl->ip ) );

	// socket
	s = Info_ValueForKey( userinfo, "socket" );
	if( !s )
	{
		trap_DropClient( ent, DROP_TYPE_GENERAL, "Error: Server didn't provide client socket" );
		return;
	}

	Q_strncpyz( cl->socket, s, sizeof( cl->socket ) );

	// color
	s = Info_ValueForKey( userinfo, "color" );
	if( s )
		rgbcolor = COM_ReadColorRGBString( s );
	else
		rgbcolor = -1;

	if( rgbcolor != -1 )
	{
		rgbcolor = COM_ValidatePlayerColor( rgbcolor );
		Vector4Set( cl->color, COLOR_R( rgbcolor ), COLOR_G( rgbcolor ), COLOR_B( rgbcolor ), 255 );
	}
	else
	{
		Vector4Set( cl->color, 255, 255, 255, 255 );
	}

	// set name, it's validated and possibly changed first
	Q_strncpyz( oldname, cl->netname, sizeof( oldname ) );
	G_SetName( ent, Info_ValueForKey( userinfo, "name" ) );
	if( oldname[0] && Q_stricmp( oldname, cl->netname ) && !cl->isTV && !CheckFlood( ent, false ) )
		G_PrintMsg( NULL, "%s%s is now known as %s%s\n", oldname, S_COLOR_WHITE, cl->netname, S_COLOR_WHITE );
	if( !Info_SetValueForKey( userinfo, "name", cl->netname ) )
	{
		trap_DropClient( ent, DROP_TYPE_GENERAL, "Error: Couldn't set userinfo (name)" );
		return;
	}

	// clan tag
	G_SetClan( ent, Info_ValueForKey( userinfo, "clan" ) );

	// handedness
	s = Info_ValueForKey( userinfo, "hand" );
	if( !s )
		cl->hand = 2;
	else
		cl->hand = bound( atoi( s ), 0, 2 );

	// handicap
	s = Info_ValueForKey( userinfo, "handicap" );
	if( s )
	{
		i = atoi( s );

		if( i > 90 || i < 0 )
		{
			G_PrintMsg( ent, "Handicap must be defined in the [0-90] range.\n" );
			cl->handicap = 0;
		}
		else
		{
			cl->handicap = i;
		}
	}

	s = Info_ValueForKey( userinfo, "cg_movementStyle" );
	if( s )
	{
		i = bound( atoi( s ), 0, GS_MAXBUNNIES - 1 );
		if( trap_GetClientState( PLAYERNUM(ent) ) < CS_SPAWNED )
		{
			if( i != cl->movestyle )
				cl->movestyle = cl->movestyle_latched = i;
		}
		else if( cl->movestyle_latched != cl->movestyle )
		{
			G_PrintMsg( ent, "A movement style change is already in progress. Please wait.\n" );
		}
		else if( i != cl->movestyle_latched )
		{
			cl->movestyle_latched = i;
			if( cl->movestyle_latched != cl->movestyle )
			{
				edict_t *switcher;

				switcher = G_Spawn();
				switcher->think = think_MoveTypeSwitcher;
				switcher->nextThink = level.time + 10000;
				switcher->s.ownerNum = ENTNUM( ent );
				G_PrintMsg( ent, "Movement style will change in 10 seconds.\n" );
			}
		}
	}

	// update the movement features depending on the movestyle
	if( !G_ISGHOSTING( ent ) && g_allow_bunny->integer )
	{
		if( cl->movestyle == GS_CLASSICBUNNY )
			cl->ps.pmove.stats[PM_STAT_FEATURES] &= ~PMFEAT_FWDBUNNY;
		else
			cl->ps.pmove.stats[PM_STAT_FEATURES] |= PMFEAT_FWDBUNNY;
	}

	s = Info_ValueForKey( userinfo, "cg_noAutohop" );
	if( s && s[0] )
	{
		if( atoi( s ) != 0 )
			cl->ps.pmove.stats[PM_STAT_FEATURES] &= ~PMFEAT_CONTINOUSJUMP;
		else
			cl->ps.pmove.stats[PM_STAT_FEATURES] |= PMFEAT_CONTINOUSJUMP;
	}

#ifdef UCMDTIMENUDGE
	s = Info_ValueForKey( userinfo, "cl_ucmdTimeNudge" );
	if( !s )
	{
		cl->ucmdTimeNudge = 0;
	}
	else
	{
		cl->ucmdTimeNudge = atoi( s );
		clamp( cl->ucmdTimeNudge, -MAX_UCMD_TIMENUDGE, MAX_UCMD_TIMENUDGE );
	}
#endif

	// mm session
	// TODO: remove the key after storing it to gclient_t !
	s = Info_ValueForKey( userinfo, "cl_mm_session" );
	cl->mm_session = ( s == NULL ) ? 0 : atoi( s );

	s = Info_ValueForKey( userinfo, "mmflags" );
	cl->mmflags = ( s == NULL ) ? 0 : strtoul( s, NULL, 10 );

	// tv
	if( cl->isTV )
	{
		s = Info_ValueForKey( userinfo, "tv_port" );
		cl->tv.port = s ? atoi( s ) : 0;

		s = Info_ValueForKey( userinfo, "tv_port6" );
		cl->tv.port6 = s ? atoi( s ) : 0;

		s = Info_ValueForKey( userinfo, "max_cl" );
		cl->tv.maxclients = s ? atoi( s ) : 0;

		s = Info_ValueForKey( userinfo, "num_cl" );
		cl->tv.numclients = s ? atoi( s ) : 0;

		s = Info_ValueForKey( userinfo, "chan" );
		cl->tv.channel = s ? atoi( s ) : 0;
	}

	if( !G_ISGHOSTING( ent ) && trap_GetClientState( PLAYERNUM( ent ) ) >= CS_SPAWNED )
		G_Client_AssignTeamSkin( ent, userinfo );

	// save off the userinfo in case we want to check something later
	Q_strncpyz( cl->userinfo, userinfo, sizeof( cl->userinfo ) );

	G_UpdatePlayerInfoString( PLAYERNUM( ent ) );
	G_UpdateMMPlayerInfoString( PLAYERNUM( ent ) );

	G_Gametype_ScoreEvent( cl, "userinfochanged", oldname );
}
//----------------------------------------------------------------
static void turretG2_fire ( gentity_t *ent, vec3_t start, vec3_t dir )
//----------------------------------------------------------------
{
    vec3_t		org, ang;
    gentity_t	*bolt;

    if ( (trap_PointContents( start, ent->s.number )&MASK_SHOT) )
    {
        return;
    }

    VectorMA( start, -START_DIS, dir, org ); // dumb....

    if ( ent->random )
    {
        vectoangles( dir, ang );
        ang[PITCH] += flrand( -ent->random, ent->random );
        ang[YAW] += flrand( -ent->random, ent->random );
        AngleVectors( ang, dir, NULL, NULL );
    }

    vectoangles(dir, ang);

    if ( (ent->spawnflags&SPF_TURRETG2_TURBO) )
    {
        //muzzle flash
        G_PlayEffectID( ent->genericValue13, org, ang );
        WP_FireTurboLaserMissile( ent, start, dir );
        if ( ent->alt_fire )
        {
            TurboLaser_SetBoneAnim( ent, 2, 3 );
        }
        else
        {
            TurboLaser_SetBoneAnim( ent, 0, 1 );
        }
    }
    else
    {
        G_PlayEffectID( G_EffectIndex("blaster/muzzle_flash"), org, ang );
        bolt = G_Spawn();

        bolt->classname = "turret_proj";
        bolt->nextthink = level.time + 10000;
        bolt->think = G_FreeEntity;
        bolt->s.eType = ET_MISSILE;
        bolt->s.weapon = WP_BLASTER;
        bolt->r.ownerNum = ent->s.number;
        bolt->damage = ent->damage;
        bolt->alliedTeam = ent->alliedTeam;
        bolt->teamnodmg = ent->teamnodmg;
        bolt->dflags = (DAMAGE_NO_KNOCKBACK|DAMAGE_HEAVY_WEAP_CLASS);		// Don't push them around, or else we are constantly re-aiming
        bolt->splashDamage = ent->splashDamage;
        bolt->splashRadius = ent->splashDamage;
        bolt->methodOfDeath = MOD_TARGET_LASER;//MOD_ENERGY;
        bolt->splashMethodOfDeath = MOD_TARGET_LASER;//MOD_ENERGY;
        bolt->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER;
        //bolt->trigger_formation = qfalse;		// don't draw tail on first frame

        VectorSet( bolt->r.maxs, 1.5, 1.5, 1.5 );
        VectorScale( bolt->r.maxs, -1, bolt->r.mins );
        bolt->s.pos.trType = TR_LINEAR;
        bolt->s.pos.trTime = level.time;
        VectorCopy( start, bolt->s.pos.trBase );
        VectorScale( dir, ent->mass, bolt->s.pos.trDelta );
        SnapVector( bolt->s.pos.trDelta );		// save net bandwidth
        VectorCopy( start, bolt->r.currentOrigin);
    }
}
void GunRackAddItem( gitem_t *gun, vec3_t org, vec3_t angs, float ffwd, float fright, float fup )
{
	vec3_t		fwd, right;
	gentity_t	*it_ent = G_Spawn();
	qboolean	rotate = qtrue;

	AngleVectors( angs, fwd, right, NULL );

	if ( it_ent && gun )
	{
		// FIXME: scaling the ammo will probably need to be tweaked to a reasonable amount...adjust as needed
		// Set base ammo per type
		if ( gun->giType == IT_WEAPON )
		{
			it_ent->spawnflags |= 16;// VERTICAL

			switch( gun->giTag )
			{
			case WP_BLASTER:
				it_ent->count = 15;
				break;
			case WP_REPEATER:
				it_ent->count = 100;
				break;
			case WP_ROCKET_LAUNCHER:
				it_ent->count = 4;
				break;
			}
		}
		else
		{
			rotate = qfalse;

			// must deliberately make it small, or else the objects will spawn inside of each other.
			VectorSet( it_ent->maxs, 6.75f, 6.75f, 6.75f );
			VectorScale( it_ent->maxs, -1, it_ent->mins );
		}

		it_ent->spawnflags |= 1;// ITMSF_SUSPEND
		it_ent->classname = gun->classname;
		G_SpawnItem( it_ent, gun );

		// FinishSpawningItem handles everything, so clear the thinkFunc that was set in G_SpawnItem
		FinishSpawningItem( it_ent );

		if ( gun->giType == IT_AMMO )
		{
			if ( gun->giTag == AMMO_BLASTER ) // I guess this just has to use different logic??
			{
				if ( g_spskill->integer >= 2 )
				{
					it_ent->count += 10; // give more on higher difficulty because there will be more/harder enemies?
				}
			}
			else
			{
				// scale ammo based on skill
				switch ( g_spskill->integer )
				{
				case 0: // do default
					break;
				case 1:
					it_ent->count *= 0.75f;
					break;
				case 2:
					it_ent->count *= 0.5f;
					break;
				}
			}
		}

		it_ent->nextthink = 0;

		VectorCopy( org, it_ent->s.origin );
		VectorMA( it_ent->s.origin, fright, right, it_ent->s.origin );
		VectorMA( it_ent->s.origin, ffwd, fwd, it_ent->s.origin );
		it_ent->s.origin[2] += fup;

		VectorCopy( angs, it_ent->s.angles );

		// by doing this, we can force the amount of ammo we desire onto the weapon for when it gets picked-up
		it_ent->flags |= ( FL_DROPPED_ITEM | FL_FORCE_PULLABLE_ONLY );
		it_ent->physicsBounce = 0.1f;

		for ( int t = 0; t < 3; t++ )
		{
			if ( rotate )
			{
				if ( t == YAW )
				{
					it_ent->s.angles[t] = AngleNormalize180( it_ent->s.angles[t] + 180 + crandom() * 14 );
				}
				else
				{
					it_ent->s.angles[t] = AngleNormalize180( it_ent->s.angles[t] + crandom() * 4 );
				}
			}
			else
			{
				if ( t == YAW )
				{
					it_ent->s.angles[t] = AngleNormalize180( it_ent->s.angles[t] + 90 + crandom() * 4 );
				}
			}
		}

		G_SetAngles( it_ent, it_ent->s.angles );
		G_SetOrigin( it_ent, it_ent->s.origin );
		gi.linkentity( it_ent );
	}
}
Example #16
0
void SP_model_train (edict_t *self)
{
	SP_model_spawn (self);

	self->class_id = ENTITY_MODEL_TRAIN;

	// Reset s.sound, which SP_model_spawn may have turned on
	self->moveinfo.sound_middle = self->s.sound;
	self->s.sound = 0;

	if(!self->inuse) return;

	// Reset some things from SP_model_spawn
	self->delay = 0;
	self->think = NULL;
	self->nextthink = 0;
	if (self->health)
	{
		self->die = train_die;
		self->takedamage = DAMAGE_YES;
	}

	if(self->framenumbers > self->startframe+1)
	{
		edict_t	*animator;
		animator = G_Spawn();
		animator->owner = self;
		animator->think = model_train_animator;
		animator->nextthink = level.time + FRAMETIME;
	}
	self->s.frame = self->startframe;
	self->movetype = MOVETYPE_PUSH;

	// Really gross stuff here... translate model_spawn spawnflags
	// to func_train spawnflags. PLAYER_MODEL and NO_MODEL have
	// already been checked in SP_model_spawn and are never re-used,
	// so it's OK to overwrite those.
	if(self->spawnflags & MTRAIN_ROTATE)
	{
		self->spawnflags &= ~MTRAIN_ROTATE;
		self->spawnflags |= TRAIN_ROTATE;
	}
	if(self->spawnflags & MTRAIN_ROTATE_CONSTANT)
	{
		self->spawnflags &= ~MTRAIN_ROTATE_CONSTANT;
		self->spawnflags |= TRAIN_ROTATE_CONSTANT;
	}
	if( (self->spawnflags & (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT)) == (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT))
	{
		self->spawnflags &= ~(TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT);
		self->spawnflags |= TRAIN_SPLINE;
	}
	if(self->style == 3)
		self->spawnflags |= TRAIN_ANIMATE;		// 32
	if(self->style == 4)
		self->spawnflags |= TRAIN_ANIMATE_FAST;	// 64

	// TRAIN_SMOOTH forces trains to go directly to Move_Done from
	// Move_Final rather than slowing down (if necessary) for one
	// frame.
	if (self->spawnflags & TRAIN_SMOOTH)
		self->smooth_movement = true;
	else
		self->smooth_movement = false;

	self->blocked = train_blocked;
	if (self->spawnflags & TRAIN_BLOCK_STOPS)
		self->dmg = 0;
	else
	{
		if (!self->dmg)
			self->dmg = 100;
	}

	if (!self->speed)
		self->speed = 100;

	self->moveinfo.speed = self->speed;
	self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed;

	self->use = train_use;

	gi.linkentity (self);

	if (self->target)
	{
		// start trains on the second frame, to make sure their targets have had
		// a chance to spawn
		self->nextthink = level.time + FRAMETIME;
		self->think = func_train_find;
	}
	else
	{
		gi.dprintf ("model_train without a target at %s\n", vtos(self->absmin));
	}

}
Example #17
0
void
fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage,
		int speed, int effect, qboolean hyper)
{
	edict_t *bolt;
	trace_t tr;

	if (!self)
	{
		return;
	}

	VectorNormalize(dir);

	bolt = G_Spawn();
	bolt->svflags = SVF_DEADMONSTER;

	/* yes, I know it looks weird that projectiles are deadmonsters
	   what this means is that when prediction is used against the object
	   (blaster/hyperblaster shots), the player won't be solid clipped against
	   the object.  Right now trying to run into a firing hyperblaster
	   is very jerky since you are predicted 'against' the shots. */
	VectorCopy(start, bolt->s.origin);
	VectorCopy(start, bolt->s.old_origin);
	vectoangles(dir, bolt->s.angles);
	VectorScale(dir, speed, bolt->velocity);
	bolt->movetype = MOVETYPE_FLYMISSILE;
	bolt->clipmask = MASK_SHOT;
	bolt->solid = SOLID_BBOX;
	bolt->s.effects |= effect;
	bolt->s.renderfx |= RF_NOSHADOW;
	VectorClear(bolt->mins);
	VectorClear(bolt->maxs);
	bolt->s.modelindex = gi.modelindex("models/objects/laser/tris.md2");
	bolt->s.sound = gi.soundindex("misc/lasfly.wav");
	bolt->owner = self;
	bolt->touch = blaster_touch;
	bolt->nextthink = level.time + 2;
	bolt->think = G_FreeEdict;
	bolt->dmg = damage;
	bolt->classname = "bolt";

	if (hyper)
	{
		bolt->spawnflags = 1;
	}

	gi.linkentity(bolt);

	if (self->client)
	{
		check_dodge(self, bolt->s.origin, dir, speed);
	}

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

	if (tr.fraction < 1.0)
	{
		VectorMA(bolt->s.origin, -10, dir, bolt->s.origin);
		bolt->touch(bolt, tr.ent, NULL, NULL);
	}
}
Example #18
0
/*
================
G_MissileImpact
================
*/
void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
	gentity_t		*other;
	qboolean		hitClient = qfalse;
#ifdef MISSIONPACK
	vec3_t			forward, impactpoint, bouncedir;
	int				eFlags;
#endif
	other = &g_entities[trace->entityNum];

	// check for bounce
	if ( !other->takedamage &&
		( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) ) {
		G_BounceMissile( ent, trace );
		G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
		return;
	}

#ifdef MISSIONPACK
	if ( other->takedamage ) {
		if ( ent->s.weapon != WP_PROX_LAUNCHER ) {
			if ( other->client && other->client->invulnerabilityTime > level.time ) {
				//
				VectorCopy( ent->s.pos.trDelta, forward );
				VectorNormalize( forward );
				if (G_InvulnerabilityEffect( other, forward, ent->s.pos.trBase, impactpoint, bouncedir )) {
					VectorCopy( bouncedir, trace->plane.normal );
					eFlags = ent->s.eFlags & EF_BOUNCE_HALF;
					ent->s.eFlags &= ~EF_BOUNCE_HALF;
					G_BounceMissile( ent, trace );
					ent->s.eFlags |= eFlags;
				}
				ent->target_ent = other;
				return;
			}
		}
	}
#endif
	// impact damage
	if (other->takedamage) {
		// FIXME: wrong damage direction?
		if ( ent->damage ) {
			vec3_t	velocity;

			if( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) {
				g_entities[ent->r.ownerNum].client->accuracy_hits++;
				hitClient = qtrue;
			}
			BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
			if ( VectorLength( velocity ) == 0 ) {
				velocity[2] = 1;	// stepped on a grenade
			}
			G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
				ent->s.origin, ent->damage, 
				0, ent->methodOfDeath);
		}
	}

#ifdef MISSIONPACK
	if( ent->s.weapon == WP_PROX_LAUNCHER ) {
		if( ent->s.pos.trType != TR_GRAVITY ) {
			return;
		}

		// if it's a player, stick it on to them (flag them and remove this entity)
		if( other->s.eType == ET_PLAYER && other->health > 0 ) {
			ProximityMine_Player( ent, other );
			return;
		}

		SnapVectorTowards( trace->endpos, ent->s.pos.trBase );
		G_SetOrigin( ent, trace->endpos );
		ent->s.pos.trType = TR_STATIONARY;
		VectorClear( ent->s.pos.trDelta );

		G_AddEvent( ent, EV_PROXIMITY_MINE_STICK, trace->surfaceFlags );

		ent->think = ProximityMine_Activate;
		ent->nextthink = level.time + 2000;

		vectoangles( trace->plane.normal, ent->s.angles );
		ent->s.angles[0] += 90;

		// link the prox mine to the other entity
		ent->enemy = other;
		ent->die = ProximityMine_Die;
		VectorCopy(trace->plane.normal, ent->movedir);
		VectorSet(ent->r.mins, -4, -4, -4);
		VectorSet(ent->r.maxs, 4, 4, 4);
		trap_LinkEntity(ent);

		return;
	}
#endif

	if (!strcmp(ent->classname, "hook")) {
		gentity_t *nent;
		vec3_t v;

		nent = G_Spawn();
		if ( other->takedamage && other->client ) {

			G_AddEvent( nent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
			nent->s.otherEntityNum = other->s.number;

			ent->enemy = other;

			v[0] = other->r.currentOrigin[0] + (other->r.mins[0] + other->r.maxs[0]) * 0.5;
			v[1] = other->r.currentOrigin[1] + (other->r.mins[1] + other->r.maxs[1]) * 0.5;
			v[2] = other->r.currentOrigin[2] + (other->r.mins[2] + other->r.maxs[2]) * 0.5;

			SnapVectorTowards( v, ent->s.pos.trBase );	// save net bandwidth
		} else {
			VectorCopy(trace->endpos, v);
			G_AddEvent( nent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
			ent->enemy = NULL;
		}

		SnapVectorTowards( v, ent->s.pos.trBase );	// save net bandwidth

		nent->freeAfterEvent = qtrue;
		// change over to a normal entity right at the point of impact
		nent->s.eType = ET_GENERAL;
		ent->s.eType = ET_GRAPPLE;

		G_SetOrigin( ent, v );
		G_SetOrigin( nent, v );

		ent->think = Weapon_HookThink;
		ent->nextthink = level.time + FRAMETIME;

		ent->parent->client->ps.pm_flags |= PMF_GRAPPLE_PULL;
		VectorCopy( ent->r.currentOrigin, ent->parent->client->ps.grapplePoint);

		trap_LinkEntity( ent );
		trap_LinkEntity( nent );

		return;
	}

	// is it cheaper in bandwidth to just remove this ent and create a new
	// one, rather than changing the missile into the explosion?

	if ( other->takedamage && other->client ) {
		G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
		ent->s.otherEntityNum = other->s.number;
	} else if( trace->surfaceFlags & SURF_METALSTEPS ) {
		G_AddEvent( ent, EV_MISSILE_MISS_METAL, DirToByte( trace->plane.normal ) );
	} else {
		G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
	}

	ent->freeAfterEvent = qtrue;

	// change over to a normal entity right at the point of impact
	ent->s.eType = ET_GENERAL;

	SnapVectorTowards( trace->endpos, ent->s.pos.trBase );	// save net bandwidth

	G_SetOrigin( ent, trace->endpos );

	// splash damage (doesn't apply to person directly hit)
	if ( ent->splashDamage ) {
		if( G_RadiusDamage( trace->endpos, ent->parent, ent->splashDamage, ent->splashRadius, 
			other, ent->splashMethodOfDeath ) ) {
			if( !hitClient ) {
				g_entities[ent->r.ownerNum].client->accuracy_hits++;
			}
		}
	}

	trap_LinkEntity( ent );
}
Example #19
0
/*
================
LaunchItem

Spawns an item and tosses it forward
================
*/
gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity, int ownerNum ) {
	gentity_t	*dropped;
	trace_t		tr;
	vec3_t		vec, temp;
	int			i;

	dropped = G_Spawn();

	dropped->s.eType = ET_ITEM;
	dropped->s.modelindex = item - bg_itemlist;	// store item number in modelindex
	dropped->s.otherEntityNum2 = 1;	// DHM - Nerve :: this is taking modelindex2's place for a dropped item

	dropped->classname = item->classname;
	dropped->item = item;
	VectorSet( dropped->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, 0 );			//----(SA)	so items sit on the ground
	VectorSet( dropped->r.maxs, ITEM_RADIUS, ITEM_RADIUS, 2*ITEM_RADIUS );	//----(SA)	so items sit on the ground
	dropped->r.contents = CONTENTS_TRIGGER|CONTENTS_ITEM;

	dropped->clipmask = CONTENTS_SOLID | CONTENTS_MISSILECLIP;		// NERVE - SMF - fix for items falling through grates

	dropped->touch = Touch_Item_Auto;

	trap_Trace( &tr, origin, dropped->r.mins, dropped->r.maxs, origin, ownerNum, MASK_SOLID );
	if ( tr.startsolid ) {
		VectorSubtract( g_entities[ownerNum].s.origin, origin, temp );
		VectorNormalize( temp );

		for ( i=16; i<=48; i+=16 ) {
			VectorScale( temp, i, vec );
			VectorAdd( origin, vec, origin );

			trap_Trace( &tr, origin, dropped->r.mins, dropped->r.maxs, origin, ownerNum, MASK_SOLID );
			if ( !tr.startsolid )
				break;
		}
	}

	G_SetOrigin( dropped, origin );
	dropped->s.pos.trType = TR_GRAVITY;
	dropped->s.pos.trTime = level.time;
	VectorCopy( velocity, dropped->s.pos.trDelta );

	// ydnar: set yaw to parent angles 
	temp[ PITCH ] = 0;
	temp[ YAW ] = g_entities[ ownerNum ].s.apos.trBase[ YAW ];
	temp[ ROLL ] = 0;
	G_SetAngle( dropped, temp );

	dropped->s.eFlags |= EF_BOUNCE_HALF;

	if (item->giType == IT_TEAM) { // Special case for CTF flags
		gentity_t* flag = &g_entities[ g_entities[ownerNum].client->flagParent ];

		dropped->s.otherEntityNum =	g_entities[ownerNum].client->flagParent;	// store the entitynum of our original flag spawner
		dropped->s.density = 1;
		dropped->think = Team_DroppedFlagThink;
		dropped->nextthink = level.time + 30000;

		if( level.gameManager ) {
			G_Script_ScriptEvent( level.gameManager, "trigger", flag->item->giTag == PW_REDFLAG ? "allied_object_dropped" : "axis_object_dropped" );
		}
		G_Script_ScriptEvent( flag, "trigger", "dropped" );
	} else { // auto-remove after 30 seconds
		dropped->think = G_FreeEntity;

		dropped->nextthink = level.time + 30000;
	}

	dropped->flags = FL_DROPPED_ITEM;

	trap_LinkEntity (dropped);

	return dropped;
}
Example #20
0
void
ThrowGib(edict_t *self, char *gibname, int damage, int type)
{
	edict_t *gib;
	vec3_t vd;
	vec3_t origin;
	vec3_t size;
	float vscale;

	if (level.framenum > lastgibframe)
	{
		gibsthisframe = 0;
		lastgibframe = level.framenum;
	}

	gibsthisframe++;

	if (gibsthisframe > 20)
	{
		return;
	}

	gib = G_Spawn();

	VectorScale(self->size, 0.5, size);
	VectorAdd(self->absmin, size, origin);
	gib->s.origin[0] = origin[0] + crandom() * size[0];
	gib->s.origin[1] = origin[1] + crandom() * size[1];
	gib->s.origin[2] = origin[2] + crandom() * size[2];

	gi.setmodel(gib, gibname);
	gib->solid = SOLID_BBOX;
	gib->s.effects |= EF_GIB;
	gib->flags |= FL_NO_KNOCKBACK;
	gib->takedamage = DAMAGE_YES;
	gib->die = gib_die;

	if (type == GIB_ORGANIC)
	{
		gib->movetype = MOVETYPE_TOSS;
		gib->touch = gib_touch;
		vscale = 0.5;
	}
	else
	{
		gib->movetype = MOVETYPE_BOUNCE;
		vscale = 1.0;
	}

	VelocityForDamage(damage, vd);
	VectorMA(self->velocity, vscale, vd, gib->velocity);
	ClipGibVelocity(gib);
	gib->avelocity[0] = random() * 600;
	gib->avelocity[1] = random() * 600;
	gib->avelocity[2] = random() * 600;

	gib->think = G_FreeEdict;
	gib->nextthink = level.time + 10 + random() * 10;

	gi.linkentity(gib);
}
Example #21
0
void crane_reset_use (edict_t *self, edict_t *other, edict_t *activator)
{
	float   d1, d2;
	int     dir;
	edict_t *delay;
	edict_t *crane;
	edict_t *control, *beam, *cable, *cargo, *hoist, *hook;
	vec3_t  bonk, v1, v2;
	

	crane = G_Find (NULL, FOFS(targetname), self->target);
	if(!crane)
	{
		gi.dprintf("Cannot find target of crane_reset at %s\n",vtos(self->s.origin));
		return;
	}
	control = crane->crane_control;
	control->activator = activator;

	if(!(control->spawnflags & 1))
	{
		if(control->message)
			safe_centerprintf(activator,"%s\n",control->message);
		else
			safe_centerprintf(activator,"No power\n");
		return;
	}
	
	beam    = control->crane_beam;
	hoist   = control->crane_hoist;
	hook    = control->crane_hook;
	cable   = control->crane_cable;
	cargo   = hook->crane_cargo;
	VectorSubtract(beam->pos1,self->s.origin,v1);
	VectorSubtract(beam->pos2,self->s.origin,v2);
	d1 = VectorLength(v1);
	d2 = VectorLength(v2);

	if(d2 < d1)
		control->crane_increment = 1;
	else
		control->crane_increment = -1;

	if(beam->movedir[0] > 0)
	{
		// travels in X
		dir = 0;
		if(control->crane_increment > 0)
		{
			if(Crane_Hook_Bonk(hook,0,1,bonk))
			{
				bonk[0] += beam->absmax[0] - hook->absmax[0];
				beam->crane_bonk = min(bonk[0],beam->pos2[0]);
			}
			else
				beam->crane_bonk = beam->pos2[0];
			beam->crane_bonk += beam->absmin[0] - beam->absmax[0];
		}
		else
		{
			if(Crane_Hook_Bonk(hook,0,-1,bonk))
			{
				bonk[0] += beam->absmin[0] - hook->absmin[0];
				beam->crane_bonk = max(bonk[0],beam->pos1[0]);
			}
			else
				beam->crane_bonk = beam->pos1[0];
		}
	}
	else
	{
		// travels in Y
		dir = 1;
		if(control->crane_increment > 0)
		{
			if(Crane_Hook_Bonk(hook,1,1,bonk))
			{
				bonk[1] += beam->absmax[1] - hook->absmax[1];
				beam->crane_bonk = min(bonk[1],beam->pos2[1]);
			}
			else
				beam->crane_bonk = beam->pos2[1];
			beam->crane_bonk += beam->absmin[1] - beam->absmax[1];
		}
		else
		{
			if(Crane_Hook_Bonk(hook,1,-1,bonk))
			{
				bonk[1] += beam->absmin[1] - hook->absmin[1];
				beam->crane_bonk = max(bonk[1],beam->pos1[1]);
			}
			else
				beam->crane_bonk = beam->pos1[1];
		}
	}

	if(beam->speaker && beam->crane_onboard_control)
	{
		beam->speaker->owner = beam->crane_onboard_control;
		VectorAdd(beam->crane_onboard_control->absmin,
			      beam->crane_onboard_control->absmax,
				  beam->speaker->s.origin);
		VectorScale(beam->speaker->s.origin,0.5,beam->speaker->s.origin);
		VectorSubtract(beam->speaker->s.origin,
			           beam->crane_onboard_control->s.origin,beam->speaker->offset);
		beam->speaker->owner->noise_index = beam->noise_index;
	}

	beam->crane_dir = dir;
	beam->moveinfo.remaining_distance = control->crane_increment *
		(beam->crane_bonk - beam->absmin[dir]);
	if(beam->moveinfo.remaining_distance <= 0) return;

	Crane_AdjustSpeed(beam);

	VectorSet(beam->moveinfo.dir,
		beam->movedir[0]*control->crane_increment,
		beam->movedir[1]*control->crane_increment,
		0);
	beam->crane_control = control;

	hoist->crane_dir  = dir;
	hoist->crane_bonk = beam->crane_bonk + hoist->absmin[dir] - beam->absmin[dir];
	hoist->crane_control = control;
	memcpy(&hoist->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));

	hook->crane_dir   = dir;
	hook->crane_bonk  = beam->crane_bonk + hook->absmin[dir] - beam->absmin[dir];
	hook->crane_control = control;
	memcpy(&hook->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));

	cable->crane_dir  = dir;
	cable->crane_bonk = beam->crane_bonk + cable->absmin[dir] - beam->absmin[dir];
	cable->crane_control = control;
	memcpy(&cable->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));
		
	if(beam->crane_onboard_control)
	{
		beam->crane_onboard_control->crane_dir  = dir;
		beam->crane_onboard_control->crane_bonk = beam->crane_bonk +
			beam->crane_onboard_control->absmin[dir] -
			beam->absmin[dir];
		beam->crane_onboard_control->crane_control = control;
		memcpy(&beam->crane_onboard_control->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));
	}

	if(cargo)
	{
		cargo->crane_dir  = dir;
		cargo->crane_bonk = beam->crane_bonk + cargo->absmin[dir] - beam->absmin[dir];
		cargo->crane_control = control;
		memcpy(&cargo->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));
	}
	delay = G_Spawn();
	delay->owner     = control;
	delay->think     = crane_reset_go;
	delay->nextthink = level.time + FRAMETIME;
	gi.linkentity(delay);

	self->count--;
	if(!self->count) {
		self->think = G_FreeEdict;
		self->nextthink = level.time + 1;
	}
}
Example #22
0
/*
================
LaunchItem

Spawns an item and tosses it forward
================
*/
gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity ) {
	gentity_t	*dropped;

	dropped = G_Spawn();

	dropped->s.eType = ET_ITEM;
	dropped->s.modelindex = item - bg_itemlist;	// store item number in modelindex
	dropped->s.modelindex2 = 1; // This is non-zero is it's a dropped item

	dropped->classname = item->classname;
	dropped->item = item;
	VectorSet (dropped->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, -ITEM_RADIUS);
	VectorSet (dropped->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS);
	dropped->r.contents = CONTENTS_TRIGGER;

	dropped->touch = Touch_Item;

	G_SetOrigin( dropped, origin );
	dropped->s.pos.trType = TR_GRAVITY;
	dropped->s.pos.trTime = level.time;
	VectorCopy( velocity, dropped->s.pos.trDelta );

	dropped->s.eFlags |= EF_BOUNCE_HALF;
#ifdef MISSIONPACK
	if ((g_gametype.integer == GT_CTF || g_gametype.integer == GT_1FCTF)			&& item->giType == IT_TEAM) { // Special case for CTF flags
#else
	if (g_gametype.integer == GT_CTF && item->giType == IT_TEAM) { // Special case for CTF flags
#endif
		dropped->think = Team_DroppedFlagThink;
		dropped->nextthink = level.time + 30000;
		Team_CheckDroppedItem( dropped );
	} else { // auto-remove after 30 seconds
		dropped->think = G_FreeEntity;
		dropped->nextthink = level.time + 30000;
	}

	dropped->flags = FL_DROPPED_ITEM;

	trap_LinkEntity (dropped);

	return dropped;
}

/*
================
Drop_Item

Spawns an item and tosses it forward
================
*/
gentity_t *Drop_Item( gentity_t *ent, gitem_t *item, float angle ) {
	vec3_t	velocity;
	vec3_t	angles;

	VectorCopy( ent->s.apos.trBase, angles );
	angles[YAW] += angle;
	angles[PITCH] = 0;	// always forward

	AngleVectors( angles, velocity, NULL, NULL );
	VectorScale( velocity, 150, velocity );
	velocity[2] += 200 + crandom() * 50;
	
	return LaunchItem( item, ent->s.pos.trBase, velocity );
}
Example #23
0
void SP_trigger_objective_info( gentity_t *ent ) {
	char *scorestring;

	if ( !ent->track ) {
		G_Error( "'trigger_objective_info' does not have a 'track' \n" );
	}

	if ( level.numOidTriggers >= MAX_OID_TRIGGERS ) {
		G_Error( "Exceeded maximum number of 'trigger_objective_info' entities\n" );
	}

	// JPW NERVE -- if this trigger has a "score" field set, then blowing up an objective
	//  inside of this field will add "score" to the right player team.  storing this
	//  in ent->accuracy since that's unused.
	G_SpawnString( "score", "0", &scorestring );
	ent->accuracy = atof( scorestring );
	// jpw

	// Arnout: HACK HACK - someone at nerve forgot to add the score field to sub - have to
	// hardcode it cause we don't want people to download the map again
	{
		char mapName[MAX_QPATH];
		trap_Cvar_VariableStringBuffer( "mapname", mapName, sizeof( mapName ) );
		if ( !Q_stricmp( mapName, "mp_sub" ) && !Q_stricmp( ent->track, "the Axis Submarine" ) ) {
			ent->accuracy = 15;
		}
	}

	trap_SetConfigstring( CS_OID_TRIGGERS + level.numOidTriggers, ent->track );
	ent->s.teamNum = level.numOidTriggers;

	level.numOidTriggers++;
	InitTrigger( ent );

	// unlike other triggers, we need to send this one to the client
	ent->r.svFlags &= ~SVF_NOCLIENT;
	ent->s.eType = ET_OID_TRIGGER;

	trap_LinkEntity( ent );

	// NERVE - SMF - spawn an explosive indicator
	if ( ( ent->spawnflags & AXIS_OBJECTIVE ) || ( ent->spawnflags & ALLIED_OBJECTIVE ) ) {
		gentity_t *e;
		e = G_Spawn();

		e->r.svFlags = SVF_BROADCAST;
		e->classname = "explosive_indicator";
		e->s.eType = ET_EXPLOSIVE_INDICATOR;
		e->s.pos.trType = TR_STATIONARY;

		if ( ent->spawnflags & AXIS_OBJECTIVE ) {
			e->s.teamNum = 1;
		} else if ( ent->spawnflags & ALLIED_OBJECTIVE ) {
			e->s.teamNum = 2;
		}

		e->r.ownerNum = ent->s.number;
		e->think = explosive_indicator_think;
		e->nextthink = level.time + FRAMETIME;

		VectorCopy( ent->r.mins, e->s.pos.trBase );
		VectorAdd( ent->r.maxs, e->s.pos.trBase, e->s.pos.trBase );
		VectorScale( e->s.pos.trBase, 0.5, e->s.pos.trBase );

		SnapVector( e->s.pos.trBase );

		trap_LinkEntity( e );
	}
	// -NERVE - SMF
}
Example #24
0
/*
===================
G_SpawnGEntityFromSpawnVars

Spawn an entity and fill in all of the level fields from
level.spawnVars[], then call the class specfic spawn function
===================
*/
void G_SpawnGEntityFromSpawnVars( void ) {
	int			i;
	gentity_t	*ent;
	char		*s, *value, *gametypeName;
	static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester", "teamtournament"};

	// get the next free entity
	ent = G_Spawn();

	for ( i = 0 ; i < level.numSpawnVars ; i++ ) {
		G_ParseField( level.spawnVars[i][0], level.spawnVars[i][1], ent );
	}

	// check for "notsingle" flag
	if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
		G_SpawnInt( "notsingle", "0", &i );
		if ( i ) {
			G_FreeEntity( ent );
			return;
		}
	}
	// check for "notteam" flag (GT_FFA, GT_TOURNAMENT, GT_SINGLE_PLAYER)
	if ( g_gametype.integer >= GT_TEAM ) {
		G_SpawnInt( "notteam", "0", &i );
		if ( i ) {
			G_FreeEntity( ent );
			return;
		}
	} else {
		G_SpawnInt( "notfree", "0", &i );
		if ( i ) {
			G_FreeEntity( ent );
			return;
		}
	}

#ifdef MISSIONPACK
	G_SpawnInt( "notta", "0", &i );
	if ( i ) {
		G_FreeEntity( ent );
		return;
	}
#else
	G_SpawnInt( "notq3a", "0", &i );
	if ( i ) {
		G_FreeEntity( ent );
		return;
	}
#endif

	if( G_SpawnString( "gametype", NULL, &value ) ) {
		if( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) {
			gametypeName = gametypeNames[g_gametype.integer];

			s = strstr( value, gametypeName );
			if( !s ) {
				G_FreeEntity( ent );
				return;
			}
		}
	}

	// move editor origin to pos
	VectorCopy( ent->s.origin, ent->r.currentOrigin );

	// if we didn't get a classname, don't bother spawning anything
	if ( !G_CallSpawn( ent ) ) {
		G_FreeEntity( ent );
	}
}
Example #25
0
/*
================
LaunchItem

Spawns an item and tosses it forward
================
*/
gentity_t *LaunchItem( gitem_t *item, const vec3_t origin, const vec3_t velocity, char *target ) {
	gentity_t	*dropped;

	dropped = G_Spawn();

	dropped->s.eType = ET_ITEM;
	dropped->s.modelindex = item - bg_itemlist;	// store item number in modelindex
	dropped->s.modelindex2 = 1; // This is non-zero is it's a dropped item

	dropped->classname = G_NewString(item->classname);	//copy it so it can be freed safely
	dropped->item = item;

	// try using the "correct" mins/maxs first
	VectorSet( dropped->mins, item->mins[0], item->mins[1], item->mins[2] );
	VectorSet( dropped->maxs, item->maxs[0], item->maxs[1], item->maxs[2] );

	if ((!dropped->mins[0] && !dropped->mins[1] && !dropped->mins[2]) && 
		(!dropped->maxs[0] && !dropped->maxs[1] && !dropped->maxs[2]))
	{
		VectorSet( dropped->maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS );
		VectorScale( dropped->maxs, -1, dropped->mins );
	}

	dropped->contents = CONTENTS_TRIGGER|CONTENTS_ITEM;//CONTENTS_TRIGGER;//not CONTENTS_BODY for dropped items, don't need to ID them

	if ( target && target[0] )
	{
		dropped->target = G_NewString( target );
	}
	else
	{
		// if not targeting something, auto-remove after 30 seconds
		// only if it's NOT a security or goodie key
		if (dropped->item->giTag != INV_SECURITY_KEY )
		{
			dropped->e_ThinkFunc = thinkF_G_FreeEntity;
			dropped->nextthink = level.time + 30000;
		}

		if ( dropped->item->giType == IT_AMMO && dropped->item->giTag == AMMO_FORCE )
		{
			dropped->nextthink = -1;
			dropped->e_ThinkFunc = thinkF_NULL;
		}
	}

	dropped->e_TouchFunc = touchF_Touch_Item;

	if ( item->giType == IT_WEAPON )
	{
		// give weapon items zero pitch, a random yaw, and rolled onto their sides...but would be bad to do this for a bowcaster
		if ( item->giTag != WP_BOWCASTER
			&& item->giTag != WP_THERMAL
			&& item->giTag != WP_TRIP_MINE
			&& item->giTag != WP_DET_PACK )
		{
			VectorSet( dropped->s.angles, 0, crandom() * 180, 90.0f );
			G_SetAngles( dropped, dropped->s.angles );
		}
	}

	G_SetOrigin( dropped, origin );
	dropped->s.pos.trType = TR_GRAVITY;
	dropped->s.pos.trTime = level.time;
	VectorCopy( velocity, dropped->s.pos.trDelta );

	dropped->s.eFlags |= EF_BOUNCE_HALF;

	dropped->flags = FL_DROPPED_ITEM;

	gi.linkentity (dropped);

	return dropped;
}
Example #26
0
// links the trigger to it's objective, determining if it's a func_explosive
// of func_constructible and spawning the right indicator
void Think_SetupObjectiveInfo(gentity_t *ent)
{
	ent->target_ent = G_FindByTargetname(NULL, ent->target);

	if (!ent->target_ent)
	{
		G_Error("'trigger_objective_info' has a missing target '%s'\n", ent->target);
	}

	if (ent->target_ent->s.eType == ET_EXPLOSIVE)
	{
		// this is for compass usage
		if ((ent->spawnflags & AXIS_OBJECTIVE) || (ent->spawnflags & ALLIED_OBJECTIVE))
		{
			gentity_t *e = G_Spawn();

			e->r.svFlags = SVF_BROADCAST;
			e->classname = "explosive_indicator";
			if (ent->spawnflags & 8)
			{
				e->s.eType = ET_TANK_INDICATOR;
			}
			else
			{
				e->s.eType = ET_EXPLOSIVE_INDICATOR;
			}
			e->parent       = ent;
			e->s.pos.trType = TR_STATIONARY;

			if (ent->spawnflags & AXIS_OBJECTIVE)
			{
				e->s.teamNum = 1;
			}
			else if (ent->spawnflags & ALLIED_OBJECTIVE)
			{
				e->s.teamNum = 2;
			}

			G_SetOrigin(e, ent->r.currentOrigin);

			e->s.modelindex2 = ent->s.teamNum;
			e->r.ownerNum    = ent->s.number;
			e->think         = explosive_indicator_think;
			e->nextthink     = level.time + FRAMETIME;

			e->s.effect1Time = ent->target_ent->constructibleStats.weaponclass;

			if (ent->tagParent)
			{
				e->tagParent = ent->tagParent;
				Q_strncpyz(e->tagName, ent->tagName, MAX_QPATH);
			}
			else
			{
				VectorCopy(ent->r.absmin, e->s.pos.trBase);
				VectorAdd(ent->r.absmax, e->s.pos.trBase, e->s.pos.trBase);
				VectorScale(e->s.pos.trBase, 0.5, e->s.pos.trBase);
			}

			SnapVector(e->s.pos.trBase);

			trap_LinkEntity(e);

			ent->target_ent->parent = ent;
		}
	}
	else if (ent->target_ent->s.eType == ET_CONSTRUCTIBLE)
	{
		gentity_t *constructibles[2];
		int       team[2] = { 0 };

		ent->target_ent->parent = ent;

		constructibles[0] = ent->target_ent;
		constructibles[1] = G_FindByTargetname(constructibles[0], ent->target);     // see if we are targetting a 2nd one for two team constructibles

		team[0] = constructibles[0]->spawnflags & AXIS_CONSTRUCTIBLE ? TEAM_AXIS : TEAM_ALLIES;

		constructibles[0]->s.otherEntityNum2 = ent->s.teamNum;

		if (constructibles[1])
		{
			team[1] = constructibles[1]->spawnflags & AXIS_CONSTRUCTIBLE ? TEAM_AXIS : TEAM_ALLIES;

			if (constructibles[1]->s.eType != ET_CONSTRUCTIBLE)
			{
				G_Error("'trigger_objective_info' targets multiple entities with targetname '%s', the second one isn't a 'func_constructible' [%d]\n", ent->target, constructibles[1]->s.eType);
			}

			if (team[0] == team[1])
			{
				G_Error("'trigger_objective_info' targets two 'func_constructible' entities with targetname '%s' that are constructible by the same team\n", ent->target);
			}

			constructibles[1]->s.otherEntityNum2 = ent->s.teamNum;

			ent->chain         = constructibles[1];
			ent->chain->parent = ent;

			constructibles[0]->chain = constructibles[1];
			constructibles[1]->chain = constructibles[0];
		}
		else
		{
			constructibles[0]->chain = NULL;
		}

		// if already constructed (in case of START_BUILT)
		if (constructibles[0]->s.angles2[1] == 0)
		{
			// spawn a constructible icon - this is for compass usage
			gentity_t *e = G_Spawn();

			e->r.svFlags = SVF_BROADCAST;
			e->classname = "constructible_indicator";
			if (ent->spawnflags & 8)
			{
				e->s.eType = ET_TANK_INDICATOR_DEAD;
			}
			else
			{
				e->s.eType = ET_CONSTRUCTIBLE_INDICATOR;
			}
			e->s.pos.trType = TR_STATIONARY;

			if (constructibles[1])
			{
				// see if one of the two is still partially built (happens when a multistage destructible construction blows up for the first time)
				if (constructibles[0]->count2 && constructibles[0]->grenadeFired > 1)
				{
					e->s.teamNum = team[0];
				}
				else if (constructibles[1]->count2 && constructibles[1]->grenadeFired > 1)
				{
					e->s.teamNum = team[1];
				}
				else
				{
					e->s.teamNum = 3;   // both teams
				}
			}
			else
			{
				e->s.teamNum = team[0];
			}

			e->s.modelindex2 = ent->s.teamNum;
			e->r.ownerNum    = ent->s.number;
			ent->count2      = (e - g_entities);
			e->think         = constructible_indicator_think;
			e->nextthink     = level.time + FRAMETIME;

			e->parent = ent;

			if (ent->tagParent)
			{
				e->tagParent = ent->tagParent;
				Q_strncpyz(e->tagName, ent->tagName, MAX_QPATH);
			}
			else
			{
				VectorCopy(ent->r.absmin, e->s.pos.trBase);
				VectorAdd(ent->r.absmax, e->s.pos.trBase, e->s.pos.trBase);
				VectorScale(e->s.pos.trBase, 0.5, e->s.pos.trBase);
			}

			SnapVector(e->s.pos.trBase);

			trap_LinkEntity(e);     // moved down
		}
		ent->touch = Touch_ObjectiveInfo;

	}
	else if (ent->target_ent->s.eType == ET_COMMANDMAP_MARKER)
	{
		ent->target_ent->parent = ent;
	}

	trap_LinkEntity(ent);
}
Example #27
0
void G_SpawnGEntityFromSpawnVars( qboolean inSubBSP ) {
	int			i;
	gentity_t	*ent;
	char		*s, *value, *gametypeName;
	static char *gametypeNames[] = {"ffa", "holocron", "jedimaster", "duel", "powerduel", "single", "team", "siege", "ctf", "cty"};

	// get the next free entity
	ent = G_Spawn();

	for ( i = 0 ; i < level.numSpawnVars ; i++ ) {
		BG_ParseField( fields, level.spawnVars[i][0], level.spawnVars[i][1], (byte *)ent );
	}

	// check for "notsingle" flag
	if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
		G_SpawnInt( "notsingle", "0", &i );
		if ( i ) {
			G_FreeEntity( ent );
			return;
		}
	}
	// check for "notteam" flag (GT_FFA, GT_DUEL, GT_SINGLE_PLAYER)
	if ( g_gametype.integer >= GT_TEAM ) {
		G_SpawnInt( "notteam", "0", &i );
		if ( i ) {
			G_FreeEntity( ent );
			return;
		}
	} else {
		G_SpawnInt( "notfree", "0", &i );
		if ( i ) {
			G_FreeEntity( ent );
			return;
		}
	}

	G_SpawnInt( "notta", "0", &i );
	if ( i ) {
		G_FreeEntity( ent );
		return;
	}

	if( G_SpawnString( "gametype", NULL, &value ) ) {
		if( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) {
			gametypeName = gametypeNames[g_gametype.integer];

			s = strstr( value, gametypeName );
			if( !s ) {
				G_FreeEntity( ent );
				return;
			}
		}
	}

	// move editor origin to pos
	VectorCopy( ent->s.origin, ent->s.pos.trBase );
	VectorCopy( ent->s.origin, ent->r.currentOrigin );

	// if we didn't get a classname, don't bother spawning anything
	if ( !G_CallSpawn( ent ) ) {
		G_FreeEntity( ent );
	}

	//Tag on the ICARUS scripting information only to valid recipients
	if ( trap_ICARUS_ValidEnt( ent ) )
	{
		trap_ICARUS_InitEnt( ent );

		if ( ent->classname && ent->classname[0] )
		{
			if ( Q_strncmp( "NPC_", ent->classname, 4 ) != 0 )
			{//Not an NPC_spawner (rww - probably don't even care for MP, but whatever)
				G_ActivateBehavior( ent, BSET_SPAWN );
			}
		}
	}
}
Example #28
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);
    }
}
Example #29
0
//----------------------------------------------------------
void emplaced_gun_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	vec3_t fwd1, fwd2;

	if ( self->health <= 0 )
	{
		// can't use a dead gun.
		return;
	}

	if ( self->svFlags & SVF_INACTIVE )
	{
		return; // can't use inactive gun
	}

	if ( !activator->client )
	{
		return; // only a client can use it.
	}

	if ( self->activator )
	{
		// someone is already in the gun.
		return;
	}

	if ( other && other->client && G_IsRidingVehicle( other ) )
	{//can't use eweb when on a vehicle
		return;
	}

	if ( activator && activator->client && G_IsRidingVehicle( activator ) )
	{//can't use eweb when on a vehicle
		return;
	}

	// We'll just let the designers duke this one out....I mean, as to whether they even want to limit such a thing.
	if ( self->spawnflags & EMPLACED_FACING )
	{
		// Let's get some direction vectors for the users
		AngleVectors( activator->client->ps.viewangles, fwd1, NULL, NULL );

		// Get the guns direction vector
		AngleVectors( self->pos1, fwd2, NULL, NULL );

		float dot = DotProduct( fwd1, fwd2 );

		// Must be reasonably facing the way the gun points ( 90 degrees or so ), otherwise we don't allow to use it.
		if ( dot < 0.0f )
		{
			return;
		}
	}

	// don't allow using it again for half a second
	if ( self->delay + 500 < level.time )
	{
		int	oldWeapon = activator->s.weapon;

		if ( oldWeapon == WP_SABER )
		{
			self->alt_fire = activator->client->ps.SaberActive();
		}

		// swap the users weapon with the emplaced gun and add the ammo the gun has to the player
		activator->client->ps.weapon = self->s.weapon;
		Add_Ammo( activator, WP_EMPLACED_GUN, self->count );
		activator->client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_EMPLACED_GUN );

		// Allow us to point from one to the other
		activator->owner = self; // kind of dumb, but when we are locked to the weapon, we are owned by it.
		self->activator = activator;

		G_RemoveWeaponModels( activator );

extern void ChangeWeapon( gentity_t *ent, int newWeapon );
		if ( activator->NPC )
		{
			ChangeWeapon( activator, WP_EMPLACED_GUN );
		}
		else if ( activator->s.number == 0 )
		{
			// we don't want for it to draw the weapon select stuff
			cg.weaponSelect = WP_EMPLACED_GUN;
			CG_CenterPrint( "@SP_INGAME_EXIT_VIEW", SCREEN_HEIGHT * 0.95 );
		}
		// Since we move the activator inside of the gun, we reserve a solid spot where they were standing in order to be able to get back out without being in solid
		if ( self->nextTrain )
		{//you never know
			G_FreeEntity( self->nextTrain );
		}
		self->nextTrain = G_Spawn();
		//self->nextTrain->classname = "emp_placeholder";
		self->nextTrain->contents = CONTENTS_MONSTERCLIP|CONTENTS_PLAYERCLIP;//hmm... playerclip too now that we're doing it for NPCs?
		G_SetOrigin( self->nextTrain, activator->client->ps.origin );
		VectorCopy( activator->mins, self->nextTrain->mins );
		VectorCopy( activator->maxs, self->nextTrain->maxs );
		gi.linkentity( self->nextTrain );

		//need to inflate the activator's mins/maxs since the gunsit anim puts them outside of their bbox
		VectorSet( activator->mins, -24, -24, -24 );
		VectorSet( activator->maxs, 24, 24, 40 );

		// Move the activator into the center of the gun.  For NPC's the only way the can get out of the gun is to die.
		VectorCopy( self->s.origin, activator->client->ps.origin );
		activator->client->ps.origin[2] += 30; // move them up so they aren't standing in the floor
		gi.linkentity( activator );

		// the gun will track which weapon we used to have
		self->s.weapon = oldWeapon;

		// Lock the player
		activator->client->ps.eFlags |= EF_LOCKED_TO_WEAPON;
		activator->owner = self; // kind of dumb, but when we are locked to the weapon, we are owned by it.
		self->activator = activator;
		self->delay = level.time; // can't disconnect from the thing for half a second

		// Let the gun be considered an enemy
		//Ugh, so much AI code seems to assume enemies are clients, maybe this shouldn't be on, but it's too late in the game to change it now without knowing what side-effects this will have
		self->svFlags |= SVF_NONNPC_ENEMY;
		self->noDamageTeam = activator->client->playerTeam;

		// FIXME: don't do this, we'll try and actually put the player in this beast
		// move the player to the center of the gun
//		activator->contents = 0;
//		VectorCopy( self->currentOrigin, activator->client->ps.origin );

		SetClientViewAngle( activator, self->pos1 );

		//FIXME: should really wait a bit after spawn and get this just once?
		self->waypoint = NAV::GetNearestNode(self);
#ifdef _DEBUG
		if ( self->waypoint == -1 )
		{
			gi.Printf( S_COLOR_RED"ERROR: no waypoint for emplaced_gun %s at %s\n", self->targetname, vtos(self->currentOrigin) );
		}
#endif

		G_Sound( self, G_SoundIndex( "sound/weapons/emplaced/emplaced_mount.mp3" ));
#ifdef _IMMERSION
		G_Force( self, G_ForceIndex( "fffx/weapons/emplaced/emplaced_mount", FF_CHANNEL_TOUCH ) );
#endif // _IMMERSION

		if ( !(self->spawnflags&EMPLACED_PLAYERUSE) || activator->s.number == 0 )
		{//player-only usescript or any usescript
			// Run use script
			G_ActivateBehavior( self, BSET_USE );
		}
	}
}
Example #30
0
/*
===================
G_SpawnGEntityFromSpawnVars

Spawn an entity and fill in all of the level fields from
level.spawnVars[], then call the class specfic spawn function
===================
*/
void G_SpawnGEntityFromSpawnVars( void ) {
    int			i;
    gentity_t	*ent;
    char		*s, *value;

    // get the next free entity
    ent = G_Spawn();

    for ( i = 0 ; i < level.numSpawnVars ; i++ ) {
        G_ParseField( level.spawnVars[i][0], level.spawnVars[i][1], ent );
    }

    // check for "notsingle" flag
    if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
        G_SpawnInt( "notsingle", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    // check for "notteam" flag (GT_FFA, GT_TOURNAMENT, GT_SINGLE_PLAYER)
    if ( gt[g_gametype.integer].teams ) {
        G_SpawnInt( "notteam", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    } else {
        G_SpawnInt( "notfree", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }

#ifdef MISSIONPACK
    G_SpawnInt( "notta", "0", &i );
    if ( i ) {
        ADJUST_AREAPORTAL();
        G_FreeEntity( ent );
        return;
    }
#else
    G_SpawnInt( "notq3a", "0", &i );
    if ( i ) {
        ADJUST_AREAPORTAL();
        G_FreeEntity( ent );
        return;
    }
#endif
//fnq3
    G_SpawnInt( "notfnq3", "0", &i );
    if ( i ) {
        ADJUST_AREAPORTAL();
        G_FreeEntity( ent );
        return;
    }

    if ( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) {
        if ( G_SpawnString("gametype", NULL, &value) ) {
            s = strstr( value, gt[g_gametype.integer].refName );
            if ( !s ) {
                ADJUST_AREAPORTAL();
                G_FreeEntity( ent );
                return;
            }
        }

        if ( G_SpawnString("not_gametype", NULL, &value) ) {
            s = strstr( value, gt[g_gametype.integer].refName );
            if ( s ) {
                ADJUST_AREAPORTAL();
                G_FreeEntity( ent );
                return;
            }
        }
    }

    if ( gt[g_gametype.integer].arena ) {
        G_SpawnInt( "not_gt_arena", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].ctf ) {
        G_SpawnInt( "not_gt_ctf", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].dom ) {
        G_SpawnInt( "not_gt_dom", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].duel ) {
        G_SpawnInt( "not_gt_duel", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].elimination ) {
        G_SpawnInt( "not_gt_elim", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].freeze ) {
        G_SpawnInt( "not_gt_freeze", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].single ) {
        G_SpawnInt( "not_gt_single", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].tdm ) {
        G_SpawnInt( "not_gt_tdm", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
    if ( gt[g_gametype.integer].teams ) {
        G_SpawnInt( "not_gt_teams", "0", &i );
        if ( i ) {
            ADJUST_AREAPORTAL();
            G_FreeEntity( ent );
            return;
        }
    }
//-fnq3

    // move editor origin to pos
    VectorCopy( ent->s.origin, ent->s.pos.trBase );
    VectorCopy( ent->s.origin, ent->r.currentOrigin );

    // if we didn't get a classname, don't bother spawning anything
    if ( !G_CallSpawn(ent) ) {
        G_FreeEntity( ent );
    }
}