Example #1
0
/*
===============
CheckGrabAttack
===============
*/
void CheckGrabAttack( gentity_t *ent )
{
  trace_t   tr;
  vec3_t    end, dir;
  gentity_t *traceEnt;

  // set aiming directions
  AngleVectors( ent->client->ps.viewangles, forward, right, up );

  CalcMuzzlePoint( ent, forward, right, up, muzzle );

  VectorMA( muzzle, LEVEL1_GRAB_RANGE, forward, end );

  trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );
  if( tr.surfaceFlags & SURF_NOIMPACT )
    return;

  traceEnt = &g_entities[ tr.entityNum ];

  if( !traceEnt->takedamage )
    return;

  if( traceEnt->client )
  {
    if( traceEnt->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
      return;

    if( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 )
      return;

    if( !( traceEnt->client->ps.stats[ STAT_STATE ] & SS_GRABBED ) )
    {
      AngleVectors( traceEnt->client->ps.viewangles, dir, NULL, NULL );
      traceEnt->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );

      //event for client side grab effect
      G_AddPredictableEvent( ent, EV_LEV1_GRAB, 0 );
    }

    traceEnt->client->ps.stats[ STAT_STATE ] |= SS_GRABBED;

    if( ent->client->ps.weapon == WP_ALEVEL1 )
      traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_TIME;
    else if( ent->client->ps.weapon == WP_ALEVEL1_UPG )
      traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_U_TIME;
  }
  else if( traceEnt->s.eType == ET_BUILDABLE &&
      traceEnt->s.modelindex == BA_H_MGTURRET )
  {
    if( !traceEnt->lev1Grabbed )
      G_AddPredictableEvent( ent, EV_LEV1_GRAB, 0 );

    traceEnt->lev1Grabbed = qtrue;
    traceEnt->lev1GrabTime = level.time;
  }
}
Example #2
0
void trigger_push_touch( gentity_t *self, gentity_t *other, trace_t *trace ) {

	if ( ( self->spawnflags & 4 ) && other->r.svFlags & SVF_CASTAI ) {
		return;
	}

	if ( !other->client ) {
		return;
	}

	if ( other->client->ps.pm_type != PM_NORMAL ) {
		return;
	}
	if ( other->client->ps.powerups[PW_FLIGHT] ) {
		return;
	}

//----(SA) commented out as we have no hook
//	if (other->client && other->client->hook)
//		Weapon_HookFree(other->client->hook);

	if ( other->client->ps.velocity[2] < 100 ) {
		// don't play the event sound again if we are in a fat trigger
		G_AddPredictableEvent( other, EV_JUMP_PAD, 0 );
	}
	VectorCopy( self->s.origin2, other->client->ps.velocity );

	if ( self->spawnflags & 2 ) {
		G_FreeEntity( self );
	}
}
Example #3
0
void heal_touch(gentity_t * self, gentity_t * other, trace_t * trace)
{
	int             i, clientcount = 0;
	gentity_t      *touchClients[MAX_CLIENTS];
	int             healvalue;

	memset(touchClients, 0, sizeof(touchClients));

	if(!other->client)
	{
		return;
	}

	if(self->timestamp > level.time)
	{
		return;
	}
	self->timestamp = level.time + 1000;

	for(i = 0; i < level.numConnectedClients; i++)
	{
		int             j = level.sortedClients[i];

		if(level.clients[j].ps.stats[STAT_MAX_HEALTH] > g_entities[j].health &&
		   trap_EntityContactCapsule(g_entities[j].r.absmin, g_entities[j].r.absmax, self) && G_IsAllowedHeal(&g_entities[j]))
		{
			touchClients[clientcount] = &g_entities[j];
			clientcount++;
		}
	}

	if(clientcount == 0)
	{
		return;
	}

	for(i = 0; i < clientcount; i++)
	{
		healvalue = min(touchClients[i]->client->ps.stats[STAT_MAX_HEALTH] - touchClients[i]->health, self->damage);
		if(self->health != -9999)
		{
			healvalue = min(healvalue, self->health);
		}
		if(healvalue <= 0)
		{
			continue;
		}

		touchClients[i]->health += healvalue;
		// add the medicheal event (to get sound, etc.)
		G_AddPredictableEvent(other, EV_ITEM_PICKUP, BG_FindItemForClassName("item_health_cabinet") - bg_itemlist);

		if(self->health != -9999)
		{
			self->health -= healvalue;
		}
	}
}
Example #4
0
void ammo_touch( gentity_t *self, gentity_t *other, trace_t *trace ) {
	int i, clientcount = 0, count;
	gentity_t* touchClients[MAX_CLIENTS];

	memset(touchClients, 0, sizeof(touchClients));

	if( other->client == NULL ) {
		return;
	}

	// flags is for the last entity number that got ammo
	if ( self->timestamp > level.time ) {
		return;
	}
	self->timestamp = level.time + 1000;

	for( i = 0; i < level.numConnectedClients; i++ ) {
		int j = level.sortedClients[i];

		if( trap_EntityContactCapsule( g_entities[j].r.absmin, g_entities[j].r.absmax, self ) && G_IsAllowedAmmo( &g_entities[j] ) ) {
			touchClients[clientcount] = &g_entities[j];
			clientcount++;
		}
	}
	
	if(clientcount == 0) {
		return;
	}

	// Gordon: if low, just give out what's left
	if(self->health == -9999) {
		count = clientcount;
	} else {
		count = min(clientcount, self->health / (float)self->damage );
	}

	for( i = 0; i < count; i++) {
		int ammoAdded = qfalse;

		// self->damage contains the amount of ammo to add
		ammoAdded = AddMagicAmmo(touchClients[i], self->damage);

		if (ammoAdded) {
			// add the ammo pack event (to get sound, etc.)
			G_AddPredictableEvent( touchClients[i], EV_ITEM_PICKUP, BG_FindItem("Ammo Pack")-bg_itemlist );
			if (self->health != -9999) {
				// reduce the ammount of available ammo by the added clip number
				self->health -= self->damage;
//				G_Printf("%i clips left\n", self->health );
			}
		}
	}
}
Example #5
0
/*
===============
Touch_Item
===============
*/
void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
	int			respawn;
	qboolean	predict;

	if (!other->client)
		return;
	if (other->health < 1)
		return;		// dead people can't pickup

	// the same pickup rules are used for client side and server side
	if ( !BG_CanItemBeGrabbed( g_gametype.integer, &ent->s, &other->client->ps ) ) {
		return;
	}

	G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname );

	predict = other->client->pers.predictItemPickup;

	// call the item-specific pickup function
	switch( ent->item->giType ) {
	case IT_WEAPON:
		respawn = Pickup_Weapon(ent, other);
//		predict = qfalse;
		break;
	case IT_AMMO:
		respawn = Pickup_Ammo(ent, other);
//		predict = qfalse;
		break;
	case IT_ARMOR:
		respawn = Pickup_Armor(ent, other);
		break;
	case IT_HEALTH:
		respawn = Pickup_Health(ent, other);
		break;
	case IT_POWERUP:
		respawn = Pickup_Powerup(ent, other);
		predict = qfalse;
		break;
#ifdef MISSIONPACK
	case IT_PERSISTANT_POWERUP:
		respawn = Pickup_PersistantPowerup(ent, other);
		break;
#endif
	case IT_TEAM:
		respawn = Pickup_Team(ent, other);
		break;
	case IT_HOLDABLE:
		respawn = Pickup_Holdable(ent, other);
		break;
	default:
		return;
	}

	if ( !respawn ) {
		return;
	}

	// play the normal pickup sound
	if (predict) {
		G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
	} else {
		G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
	}

	// powerup pickups are global broadcasts
	if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) {
		// if we want the global sound to play
		if (!ent->speed) {
			gentity_t	*te;

			te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
			te->s.eventParm = ent->s.modelindex;
			te->r.svFlags |= SVF_BROADCAST;
		} else {
			gentity_t	*te;

			te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
			te->s.eventParm = ent->s.modelindex;
			// only send this temp entity to a single client
			te->r.svFlags |= SVF_SINGLECLIENT;
			te->r.singleClient = other->s.number;
		}
	}

	// fire item targets
	G_UseTargets (ent, other);

	// wait of -1 will not respawn
	if ( ent->wait == -1 ) {
		ent->r.svFlags |= SVF_NOCLIENT;
		ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		ent->unlinkAfterEvent = qtrue;
		return;
	}

	// non zero wait overrides respawn time
	if ( ent->wait ) {
		respawn = ent->wait;
	}

	// random can be used to vary the respawn time
	if ( ent->random ) {
		respawn += crandom() * ent->random;
		if ( respawn < 1 ) {
			respawn = 1;
		}
	}

	// dropped items will not respawn
	if ( ent->flags & FL_DROPPED_ITEM ) {
		ent->freeAfterEvent = qtrue;
	}

	// picked up items still stay around, they just don't
	// draw anything.  This allows respawnable items
	// to be placed on movers.
	ent->r.svFlags |= SVF_NOCLIENT;
	ent->s.eFlags |= EF_NODRAW;
	ent->r.contents = 0;

	// ZOID
	// A negative respawn times means to never respawn this item (but don't
	// delete it).  This is used by items that are respawned by third party
	// events such as ctf flags
	if ( respawn <= 0 ) {
		ent->nextthink = 0;
		ent->think = 0;
	} else {
		ent->nextthink = level.time + respawn * 1000;
		ent->think = RespawnItem;
	}
	trap_LinkEntity( ent );
}
Example #6
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles )
{
    int                 index;
    vec3_t              spawn_origin, spawn_angles;
    gclient_t           *client;
    int                 i;
    clientPersistant_t  saved;
    clientSession_t     savedSess;
    int                 persistant[ MAX_PERSISTANT ];
    gentity_t           *spawnPoint = NULL;
    int                 flags;
    int                 savedPing;
    int                 teamLocal;
    int                 eventSequence;
    char                userinfo[ MAX_INFO_STRING ];
    vec3_t              up = { 0.0f, 0.0f, 1.0f };
    int                 maxAmmo, maxClips;
    weapon_t            weapon;

    index = ent - g_entities;
    client = ent->client;

    teamLocal = client->pers.teamSelection;

    //if client is dead and following teammate, stop following before spawning
    if( client->sess.spectatorClient != -1 )
    {
        client->sess.spectatorClient = -1;
        client->sess.spectatorState = SPECTATOR_FREE;
    }

    // only start client if chosen a class and joined a team
    if( client->pers.classSelection == PCL_NONE && teamLocal == TEAM_NONE )
        client->sess.spectatorState = SPECTATOR_FREE;
    else if( client->pers.classSelection == PCL_NONE )
        client->sess.spectatorState = SPECTATOR_LOCKED;

    // if client is dead and following teammate, stop following before spawning
    if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
        G_StopFollowing( ent );

    if( origin != NULL )
        VectorCopy( origin, spawn_origin );

    if( angles != NULL )
        VectorCopy( angles, spawn_angles );

    // find a spawn point
    // do it before setting health back up, so farthest
    // ranging doesn't count this client
    if( client->sess.spectatorState != SPECTATOR_NOT )
    {
        if( teamLocal == TEAM_NONE )
            spawnPoint = G_SelectSpectatorSpawnPoint( spawn_origin, spawn_angles );
        else if( teamLocal == TEAM_ALIENS )
            spawnPoint = G_SelectAlienLockSpawnPoint( spawn_origin, spawn_angles );
        else if( teamLocal == TEAM_HUMANS )
            spawnPoint = G_SelectHumanLockSpawnPoint( spawn_origin, spawn_angles );
    }
    else
    {
        if( spawn == NULL )
        {
            G_Error( "ClientSpawn: spawn is NULL\n" );
            return;
        }

        spawnPoint = spawn;

        if( ent != spawn )
        {
            //start spawn animation on spawnPoint
            G_SetBuildableAnim( spawnPoint, BANIM_SPAWN1, qtrue );

            if( spawnPoint->buildableTeam == TEAM_ALIENS )
                spawnPoint->clientSpawnTime = ALIEN_SPAWN_REPEAT_TIME;
            else if( spawnPoint->buildableTeam == TEAM_HUMANS )
                spawnPoint->clientSpawnTime = HUMAN_SPAWN_REPEAT_TIME;
        }
    }

    // toggle the teleport bit so the client knows to not lerp
    flags = ( ent->client->ps.eFlags & EF_TELEPORT_BIT ) ^ EF_TELEPORT_BIT;
    G_UnlaggedClear( ent );

    // clear everything but the persistant data

    saved = client->pers;
    savedSess = client->sess;
    savedPing = client->ps.ping;

    for( i = 0; i < MAX_PERSISTANT; i++ )
        persistant[ i ] = client->ps.persistant[ i ];

    eventSequence = client->ps.eventSequence;
    memset( client, 0, sizeof( *client ) );

    client->pers = saved;
    client->sess = savedSess;
    client->ps.ping = savedPing;
    client->lastkilled_client = -1;

    for( i = 0; i < MAX_PERSISTANT; i++ )
        client->ps.persistant[ i ] = persistant[ i ];

    client->ps.eventSequence = eventSequence;

    // increment the spawncount so the client will detect the respawn
    client->ps.persistant[ PERS_SPAWN_COUNT ]++;
    client->ps.persistant[ PERS_SPECSTATE ] = client->sess.spectatorState;

    client->airOutTime = level.time + 12000;

    trap_GetUserinfo( index, userinfo, sizeof( userinfo ) );
    client->ps.eFlags = flags;

    //Com_Printf( "ent->client->pers->pclass = %i\n", ent->client->pers.classSelection );

    ent->s.groundEntityNum = ENTITYNUM_NONE;
    ent->client = &level.clients[ index ];
    ent->takedamage = qtrue;
    ent->inuse = qtrue;
    ent->classname = "player";
    ent->r.contents = CONTENTS_BODY;
    ent->clipmask = MASK_PLAYERSOLID;
    ent->die = player_die;
    ent->waterlevel = 0;
    ent->watertype = 0;
    ent->flags = 0;

    // calculate each client's acceleration
    ent->evaluateAcceleration = qtrue;

    client->ps.stats[ STAT_MISC ] = 0;

    client->ps.eFlags = flags;
    client->ps.clientNum = index;

    BG_ClassBoundingBox( ent->client->pers.classSelection, ent->r.mins, ent->r.maxs, NULL, NULL, NULL );

    if( client->sess.spectatorState == SPECTATOR_NOT )
        client->ps.stats[ STAT_MAX_HEALTH ] =
            BG_Class( ent->client->pers.classSelection )->health;
    else
        client->ps.stats[ STAT_MAX_HEALTH ] = 100;

    // clear entity values
    if( ent->client->pers.classSelection == PCL_HUMAN )
    {
        BG_AddUpgradeToInventory( UP_MEDKIT, client->ps.stats );
        weapon = client->pers.humanItemSelection;
    }
    else if( client->sess.spectatorState == SPECTATOR_NOT )
        weapon = BG_Class( ent->client->pers.classSelection )->startWeapon;
    else
        weapon = WP_NONE;

    maxAmmo = BG_Weapon( weapon )->maxAmmo;
    maxClips = BG_Weapon( weapon )->maxClips;
    client->ps.stats[ STAT_WEAPON ] = weapon;
    client->ps.ammo = maxAmmo;
    client->ps.clips = maxClips;

    // We just spawned, not changing weapons
    client->ps.persistant[ PERS_NEWWEAPON ] = 0;

    ent->client->ps.stats[ STAT_CLASS ] = ent->client->pers.classSelection;
    ent->client->ps.stats[ STAT_TEAM ] = ent->client->pers.teamSelection;

    ent->client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
    ent->client->ps.stats[ STAT_STATE ] = 0;
    VectorSet( ent->client->ps.grapplePoint, 0.0f, 0.0f, 1.0f );

    // health will count down towards max_health
    ent->health = client->ps.stats[ STAT_HEALTH ] = client->ps.stats[ STAT_MAX_HEALTH ]; //* 1.25;

    //if evolving scale health
    if( ent == spawn )
    {
        ent->health *= ent->client->pers.evolveHealthFraction;
        client->ps.stats[ STAT_HEALTH ] *= ent->client->pers.evolveHealthFraction;
    }

    //clear the credits array
    for( i = 0; i < MAX_CLIENTS; i++ )
        ent->credits[ i ] = 0;

    client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX;

    G_SetOrigin( ent, spawn_origin );
    VectorCopy( spawn_origin, client->ps.origin );

#define UP_VEL  150.0f
#define F_VEL   50.0f

    //give aliens some spawn velocity
    if( client->sess.spectatorState == SPECTATOR_NOT &&
            client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
    {
        if( ent == spawn )
        {
            //evolution particle system
            G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, DirToByte( up ) );
        }
        else
        {
            spawn_angles[ YAW ] += 180.0f;
            AngleNormalize360( spawn_angles[ YAW ] );

            if( spawnPoint->s.origin2[ 2 ] > 0.0f )
            {
                vec3_t  forward, dir;

                AngleVectors( spawn_angles, forward, NULL, NULL );
                VectorScale( forward, F_VEL, forward );
                VectorAdd( spawnPoint->s.origin2, forward, dir );
                VectorNormalize( dir );

                VectorScale( dir, UP_VEL, client->ps.velocity );
            }

            G_AddPredictableEvent( ent, EV_PLAYER_RESPAWN, 0 );
        }
    }
    else if( client->sess.spectatorState == SPECTATOR_NOT &&
             client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
    {
        spawn_angles[ YAW ] += 180.0f;
        AngleNormalize360( spawn_angles[ YAW ] );
    }

    // the respawned flag will be cleared after the attack and jump keys come up
    client->ps.pm_flags |= PMF_RESPAWNED;

    trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
    G_SetClientViewAngle( ent, spawn_angles );

    if( client->sess.spectatorState == SPECTATOR_NOT )
    {
        trap_LinkEntity( ent );

        // force the base weapon up
        if( client->pers.teamSelection == TEAM_HUMANS )
            G_ForceWeaponChange( ent, weapon );

        client->ps.weaponstate = WEAPON_READY;
    }

    // don't allow full run speed for a bit
    client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
    client->ps.pm_time = 100;

    client->respawnTime = level.time;
    ent->nextRegenTime = level.time;

    client->inactivityTime = level.time + g_inactivity.integer * 1000;
    client->latched_buttons = 0;

    // set default animations
    client->ps.torsoAnim = TORSO_STAND;
    client->ps.legsAnim = LEGS_IDLE;

    if( level.intermissiontime )
        MoveClientToIntermission( ent );
    else
    {
        // fire the targets of the spawn point
        if( !spawn )
            G_UseTargets( spawnPoint, ent );

        client->ps.weapon = client->ps.stats[ STAT_WEAPON ];
    }

    // run a client frame to drop exactly to the floor,
    // initialize animations and other things
    client->ps.commandTime = level.time - 100;
    ent->client->pers.cmd.serverTime = level.time;
    ClientThink( ent-g_entities );

    // positively link the client, even if the command times are weird
    if( client->sess.spectatorState == SPECTATOR_NOT )
    {
        BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
        VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
        trap_LinkEntity( ent );
    }

    // must do this here so the number of active clients is calculated
    CalculateRanks( );

    // run the presend to set anything else
    ClientEndFrame( ent );

    // clear entity state values
    BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );

    client->pers.infoChangeTime = level.time;
}
Example #7
0
/*
===============
Touch_Item
===============
*/
void Touch_Item( gentity_t *ent, gentity_t *other, trace_t *trace ) {
	int respawn;
	int makenoise = EV_ITEM_PICKUP;

	// only activated items can be picked up
	if ( !ent->active ) {
		return;
	} else {
		// need to set active to false if player is maxed out
		ent->active = qfalse;
	}

	if ( !other->client ) {
		return;
	}
	if ( other->health < 1 ) {
		return;     // dead people can't pickup

	}
	// the same pickup rules are used for client side and server side
	if ( !BG_CanItemBeGrabbed( &ent->s, &other->client->ps ) ) {
		return;
	}

	G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname );

	// call the item-specific pickup function
	switch ( ent->item->giType ) {
	case IT_WEAPON:
		respawn = Pickup_Weapon( ent, other );
		break;
	case IT_AMMO:
		respawn = Pickup_Ammo( ent, other );
		break;
	case IT_ARMOR:
		respawn = Pickup_Armor( ent, other );
		break;
	case IT_HEALTH:
		respawn = Pickup_Health( ent, other );
		break;
	case IT_POWERUP:
		respawn = Pickup_Powerup( ent, other );
		break;
	case IT_TEAM:
		respawn = Pickup_Team( ent, other );
		break;
	case IT_HOLDABLE:
		respawn = Pickup_Holdable( ent, other );
		break;
	case IT_KEY:
		respawn = Pickup_Key( ent, other );
		break;
	case IT_TREASURE:
		respawn = Pickup_Treasure( ent, other );
		break;
	case IT_CLIPBOARD:
		respawn = Pickup_Clipboard( ent, other );
		// send the event to the client to request that the UI draw a popup
		// (specified by the configstring in ent->s.density).
		//G_AddEvent( other, EV_POPUP, ent->s.density);
		//if(ent->key)
		//G_AddEvent( other, EV_GIVEPAGE, ent->key );
		break;
	default:
		return;
	}

	if ( !respawn ) {
		return;
	}

	// play sounds
	if ( ent->noise_index ) {
		// (SA) a sound was specified in the entity, so play that sound
		// (this G_AddEvent) and send the pickup as "EV_ITEM_PICKUP_QUIET"
		// so it doesn't make the default pickup sound when the pickup event is recieved
		makenoise = EV_ITEM_PICKUP_QUIET;
		G_AddEvent( other, EV_GENERAL_SOUND, ent->noise_index );
	}


	// send the pickup event
	if ( other->client->pers.predictItemPickup ) {
		G_AddPredictableEvent( other, makenoise, ent->s.modelindex );
	} else {
		G_AddEvent( other, makenoise, ent->s.modelindex );
	}

	// powerup pickups are global broadcasts
	if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM ) {
		// (SA) probably need to check for IT_KEY here too... (coop?)
		gentity_t   *te;

		te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
		te->s.eventParm = ent->s.modelindex;
		te->r.svFlags |= SVF_BROADCAST;

		// (SA) set if we want this to only go to the pickup client
//		te->r.svFlags |= SVF_SINGLECLIENT;
//		te->r.singleClient = other->s.number;

	}

	// fire item targets
	G_UseTargets( ent, other );

	// wait of -1 will not respawn
	if ( ent->wait == -1 ) {
		ent->flags |= FL_NODRAW;
		//ent->r.svFlags |= SVF_NOCLIENT;
		ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		ent->unlinkAfterEvent = qtrue;
		return;
	}

	// wait of -2 will respawn but not be available for pickup anymore
	// (partial use things that leave a spent modle (ex. plate for turkey)
	if ( respawn == RESPAWN_PARTIAL_DONE ) {
		ent->s.density = ( 1 << 9 );    // (10 bits of data transmission for density)
		ent->active = qtrue;        // re-activate
		trap_LinkEntity( ent );
		return;
	}

	if ( respawn == RESPAWN_PARTIAL ) {    // multi-stage health
		ent->s.density--;
		if ( ent->s.density ) {        // still not completely used up ( (SA) this will change to == 0 and stage 1 will be a destroyable item (plate/etc.) )
			ent->active = qtrue;        // re-activate
			trap_LinkEntity( ent );
			return;
		}
	}


	// non zero wait overrides respawn time
	if ( ent->wait ) {
		respawn = ent->wait;
	}

	// random can be used to vary the respawn time
	if ( ent->random ) {
		respawn += crandom() * ent->random;
		if ( respawn < 1 ) {
			respawn = 1;
		}
	}

	// dropped items will not respawn
	if ( ent->flags & FL_DROPPED_ITEM ) {
		ent->freeAfterEvent = qtrue;
	}

	// picked up items still stay around, they just don't
	// draw anything.  This allows respawnable items
	// to be placed on movers.
	ent->r.svFlags |= SVF_NOCLIENT;
	ent->flags |= FL_NODRAW;
	//ent->s.eFlags |= EF_NODRAW;
	ent->r.contents = 0;

	// ZOID
	// A negative respawn times means to never respawn this item (but don't
	// delete it).  This is used by items that are respawned by third party
	// events such as ctf flags
	if ( respawn <= 0 ) {
		ent->nextthink = 0;
		ent->think = 0;
	} else {
		ent->nextthink = level.time + respawn * 1000;
		ent->think = RespawnItem;
	}
	trap_LinkEntity( ent );
}
Example #8
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn and evolve
Initializes all non-persistent parts of playerState
============
*/
void ClientSpawn( gentity_t *ent, gentity_t *spawn, const vec3_t origin, const vec3_t angles )
{
	int                index;
	vec3_t             spawn_origin, spawn_angles;
	gclient_t          *client;
	int                i;
	clientPersistant_t saved;
	clientSession_t    savedSess;
	bool           savedNoclip, savedCliprcontents;
	int                persistant[ MAX_PERSISTANT ];
	gentity_t          *spawnPoint = nullptr;
	int                flags;
	int                savedPing;
	int                teamLocal;
	int                eventSequence;
	char               userinfo[ MAX_INFO_STRING ];
	vec3_t             up = { 0.0f, 0.0f, 1.0f };
	int                maxAmmo, maxClips;
	weapon_t           weapon;

	ClientSpawnCBSE(ent, ent == spawn);

	index = ent - g_entities;
	client = ent->client;

	teamLocal = client->pers.team;

	//if client is dead and following teammate, stop following before spawning
	if ( client->sess.spectatorClient != -1 )
	{
		client->sess.spectatorClient = -1;
		client->sess.spectatorState = SPECTATOR_FREE;
	}

	// only start client if chosen a class and joined a team
	if ( client->pers.classSelection == PCL_NONE && teamLocal == TEAM_NONE )
	{
		client->sess.spectatorState = SPECTATOR_FREE;
	}
	else if ( client->pers.classSelection == PCL_NONE )
	{
		client->sess.spectatorState = SPECTATOR_LOCKED;
	}

	// if client is dead and following teammate, stop following before spawning
	if ( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
	{
		G_StopFollowing( ent );
	}

	if ( origin != nullptr )
	{
		VectorCopy( origin, spawn_origin );
	}

	if ( angles != nullptr )
	{
		VectorCopy( angles, spawn_angles );
	}

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	if ( client->sess.spectatorState != SPECTATOR_NOT )
	{
		if ( teamLocal == TEAM_NONE )
		{
			spawnPoint = G_SelectSpectatorSpawnPoint( spawn_origin, spawn_angles );
		}
		else if ( teamLocal == TEAM_ALIENS )
		{
			spawnPoint = G_SelectAlienLockSpawnPoint( spawn_origin, spawn_angles );
		}
		else if ( teamLocal == TEAM_HUMANS )
		{
			spawnPoint = G_SelectHumanLockSpawnPoint( spawn_origin, spawn_angles );
		}
	}
	else
	{
		if ( spawn == nullptr )
		{
			Com_Error(errorParm_t::ERR_DROP,  "ClientSpawn: spawn is NULL" );
		}

		spawnPoint = spawn;

		if ( spawnPoint->s.eType == entityType_t::ET_BUILDABLE )
		{
			G_SetBuildableAnim( spawnPoint, BANIM_SPAWN1, true );

			if ( spawnPoint->buildableTeam == TEAM_ALIENS )
			{
				spawnPoint->clientSpawnTime = ALIEN_SPAWN_REPEAT_TIME;
			}
			else if ( spawnPoint->buildableTeam == TEAM_HUMANS )
			{
				spawnPoint->clientSpawnTime = HUMAN_SPAWN_REPEAT_TIME;
			}
		}
	}

	// toggle the teleport bit so the client knows to not lerp
	flags = ( ent->client->ps.eFlags & EF_TELEPORT_BIT ) ^ EF_TELEPORT_BIT;
	G_UnlaggedClear( ent );

	// clear everything but the persistent data

	saved = client->pers;
	savedSess = client->sess;
	savedPing = client->ps.ping;
	savedNoclip = client->noclip;
	savedCliprcontents = client->cliprcontents;

	for ( i = 0; i < MAX_PERSISTANT; i++ )
	{
		persistant[ i ] = client->ps.persistant[ i ];
	}

	eventSequence = client->ps.eventSequence;
	memset( client, 0, sizeof( *client ) );

	client->pers = saved;
	client->sess = savedSess;
	client->ps.ping = savedPing;
	client->noclip = savedNoclip;
	client->cliprcontents = savedCliprcontents;

	for ( i = 0; i < MAX_PERSISTANT; i++ )
	{
		client->ps.persistant[ i ] = persistant[ i ];
	}

	client->ps.eventSequence = eventSequence;

	// increment the spawncount so the client will detect the respawn
	client->ps.persistant[ PERS_SPAWN_COUNT ]++;
	client->ps.persistant[ PERS_SPECSTATE ] = client->sess.spectatorState;

	client->airOutTime = level.time + 12000;

	trap_GetUserinfo( index, userinfo, sizeof( userinfo ) );
	client->ps.eFlags = flags;

	//Log::Notice( "ent->client->pers->pclass = %i\n", ent->client->pers.classSelection );

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->client = &level.clients[ index ];
	ent->classname = S_PLAYER_CLASSNAME;
	if ( client->noclip )
	{
		client->cliprcontents = CONTENTS_BODY;
	}
	else
	{
		ent->r.contents = CONTENTS_BODY;
	}
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = G_PlayerDie;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags &= FL_GODMODE | FL_NOTARGET;

	// calculate each client's acceleration
	ent->evaluateAcceleration = true;

	client->ps.stats[ STAT_MISC ] = 0;

	client->ps.eFlags = flags;
	client->ps.clientNum = index;

	BG_ClassBoundingBox( ent->client->pers.classSelection, ent->r.mins, ent->r.maxs, nullptr, nullptr, nullptr );

	// clear entity values
	if ( ent->client->pers.classSelection == PCL_HUMAN_NAKED )
	{
		BG_AddUpgradeToInventory( UP_MEDKIT, client->ps.stats );
		weapon = client->pers.humanItemSelection;
	}
	else if ( client->sess.spectatorState == SPECTATOR_NOT )
	{
		weapon = BG_Class( ent->client->pers.classSelection )->startWeapon;
	}
	else
	{
		weapon = WP_NONE;
	}

	maxAmmo = BG_Weapon( weapon )->maxAmmo;
	maxClips = BG_Weapon( weapon )->maxClips;
	client->ps.stats[ STAT_WEAPON ] = weapon;
	client->ps.ammo = maxAmmo;
	client->ps.clips = maxClips;

	// We just spawned, not changing weapons
	client->ps.persistant[ PERS_NEWWEAPON ] = 0;

	client->ps.persistant[ PERS_TEAM ] = client->pers.team;

	// TODO: Check whether stats can be cleared at once instead of per field
	client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX;
	client->ps.stats[ STAT_FUEL ]    = JETPACK_FUEL_MAX;
	client->ps.stats[ STAT_CLASS ] = ent->client->pers.classSelection;
	client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
	client->ps.stats[ STAT_PREDICTION ] = 0;
	client->ps.stats[ STAT_STATE ] = 0;

	VectorSet( client->ps.grapplePoint, 0.0f, 0.0f, 1.0f );

	//clear the credits array
	// TODO: Handle in HealthComponent or ClientComponent.
	for ( i = 0; i < MAX_CLIENTS; i++ )
	{
		ent->credits[ i ].value = 0.0f;
		ent->credits[ i ].time = 0;
		ent->credits[ i ].team = TEAM_NONE;
	}

	G_SetOrigin( ent, spawn_origin );
	VectorCopy( spawn_origin, client->ps.origin );

	//give aliens some spawn velocity
	if ( client->sess.spectatorState == SPECTATOR_NOT &&
	     client->pers.team == TEAM_ALIENS )
	{
		if ( ent == spawn )
		{
			//evolution particle system
			G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, DirToByte( up ) );
		}
		else
		{
			spawn_angles[ YAW ] += 180.0f;
			AngleNormalize360( spawn_angles[ YAW ] );

			if ( spawnPoint->s.origin2[ 2 ] > 0.0f )
			{
				vec3_t forward, dir;

				AngleVectors( spawn_angles, forward, nullptr, nullptr );
				VectorAdd( spawnPoint->s.origin2, forward, dir );
				VectorNormalize( dir );
				VectorScale( dir, BG_Class( ent->client->pers.classSelection )->jumpMagnitude,
				             client->ps.velocity );
			}

			G_AddPredictableEvent( ent, EV_PLAYER_RESPAWN, 0 );
		}
	}
	else if ( client->sess.spectatorState == SPECTATOR_NOT &&
	          client->pers.team == TEAM_HUMANS )
	{
		spawn_angles[ YAW ] += 180.0f;
		AngleNormalize360( spawn_angles[ YAW ] );
	}

	// the respawned flag will be cleared after the attack and jump keys come up
	client->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
	G_SetClientViewAngle( ent, spawn_angles );

	if ( client->sess.spectatorState == SPECTATOR_NOT )
	{
		trap_LinkEntity( ent );

		// force the base weapon up
		if ( client->pers.team == TEAM_HUMANS )
		{
			G_ForceWeaponChange( ent, weapon );
		}

		client->ps.weaponstate = WEAPON_READY;
	}

	// don't allow full run speed for a bit
	client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	client->ps.pm_time = 100;

	client->respawnTime = level.time;
	ent->nextRegenTime = level.time;

	client->inactivityTime = level.time + g_inactivity.integer * 1000;
	usercmdClearButtons( client->latched_buttons );

	// set default animations
	client->ps.torsoAnim = TORSO_STAND;
	client->ps.legsAnim = LEGS_IDLE;

	if ( level.intermissiontime )
	{
		MoveClientToIntermission( ent );
	}
	else
	{
		// fire the targets of the spawn point
		if ( !spawn && spawnPoint )
		{
			G_EventFireEntity( spawnPoint, ent, ON_SPAWN );
		}

		// select the highest weapon number available, after any
		// spawn given items have fired
		client->ps.weapon = 1;

		for ( i = WP_NUM_WEAPONS - 1; i > 0; i-- )
		{
			if ( BG_InventoryContainsWeapon( i, client->ps.stats ) )
			{
				client->ps.weapon = i;
				break;
			}
		}
	}

	// run a client frame to drop exactly to the floor,
	// initialize animations and other things
	client->ps.commandTime = level.time - 100;
	ent->client->pers.cmd.serverTime = level.time;
	ClientThink( ent - g_entities );

	// positively link the client, even if the command times are weird
	if ( client->sess.spectatorState == SPECTATOR_NOT )
	{
		BG_PlayerStateToEntityState( &client->ps, &ent->s, true );
		VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
		trap_LinkEntity( ent );
	}

	// must do this here so the number of active clients is calculated
	CalculateRanks();

	// run the presend to set anything else
	ClientEndFrame( ent );

	// clear entity state values
	BG_PlayerStateToEntityState( &client->ps, &ent->s, true );

	client->pers.infoChangeTime = level.time;

	// (re)tag the client for its team
	Beacon::DeleteTags( ent );
	Beacon::Tag( ent, (team_t)ent->client->ps.persistant[ PERS_TEAM ], true );
}
Example #9
0
/*
===============
Touch_Item
===============
*/
void Touch_Item(gentity_t * ent, gentity_t * other, trace_t * trace)
{
	int respawn;
	qboolean predict;
	int bandolierFactor;

	//Makro - some checks
	if (other == NULL || ent == NULL)
		return;

	if (!other->client)
		return;
	if (other->health < 1)
		return;		// dead people can't pickup

	//Makro - even more bot hacks !
	//this way, we can remove the item from the bot's library for a few seconds
	//so bots won't get stuck in a loop between 2 items
	if ((ent->r.svFlags & MASK_BOTHACK) == MASK_BOTHACK) {
		if (ent->nextthink < level.time) {
			ent->nextthink = level.time + 45 * 1000;
		}
		return;
	}
	// the same pickup rules are used for client side and server side
	if (!BG_CanItemBeGrabbed(g_gametype.integer, &ent->s, &other->client->ps))
		return;

	predict = other->client->pers.predictItemPickup;

	if (other->client->ps.stats[STAT_HOLDABLE_ITEM] & (1 << HI_BANDOLIER))
		bandolierFactor = 2;
	else
		bandolierFactor = 1;

	//Elder: should check if the item was recently thrown ... if it was, then
	//don't allow it to be picked up ... or something like that

	// call the item-specific pickup function
	switch (ent->item->giType) {
	case IT_WEAPON:
		switch (ent->item->giTag) {
			//Blaze: Check to see if we already have the weapon,
			//If not so check and see if we have less then full ammo, if so pick up gun
			//Elder's version:
			//Accumulators (e.g. knife, grenade): if you have the weap AND the max limit, leave
			//Pistols: if you have akimbos AND max clips, leave
			//Akimbos: shouldn't pick them up b/c they shouldn't be dropped
			//Specials: if you have more than/equal to limit (remember bando later), leave
		case WP_KNIFE:
			if (((other->client->ps.stats[STAT_WEAPONS] & (1 << WP_KNIFE)) == (1 << WP_KNIFE)) &&
			    (other->client->ps.ammo[ent->item->giTag] >= RQ3_KNIFE_MAXCLIP * bandolierFactor))
				return;
			break;
		case WP_GRENADE:
			if (((other->client->ps.stats[STAT_WEAPONS] & (1 << WP_GRENADE)) == (1 << WP_GRENADE)) &&
			    (other->client->ps.ammo[ent->item->giTag] >= RQ3_GRENADE_MAXCLIP * bandolierFactor))
				return;
			break;
		case WP_PISTOL:
			//Elder: always have pistol - but extra ones give akimbo or clips
			if (((other->client->ps.stats[STAT_WEAPONS] & (1 << WP_AKIMBO)) == (1 << WP_AKIMBO)) &&
			    other->client->numClips[WP_PISTOL] >= RQ3_PISTOL_MAXCLIP * bandolierFactor) {
				//leave if we have max clips and akimbos
				return;
			}
			break;
		case WP_M3:
		case WP_HANDCANNON:
		case WP_MP5:
		case WP_M4:
		case WP_SSG3000:
			//Elder: check to see if it's in mid-air or over the limit
			if (other->client->uniqueWeapons >= g_RQ3_maxWeapons.integer + (bandolierFactor - 1) ||
			    ent->s.pos.trDelta[2] != 0)
				return;

			// Paril: fix/workaround for 4085
			// don't pick up dupe special weapons even if we could.
			if ((other->client->ps.stats[STAT_WEAPONS] & (1 << ent->item->giTag)) == (1 << ent->item->giTag))
				return;
			break;
		case WP_AKIMBO:
		default:
			//Elder: shouldn't be here
			G_Printf("Touch_Item received invalid IT_WEAPON giTag: %d\n", ent->item->giTag);
			return;
			break;
		}

		respawn = Pickup_Weapon(ent, other, bandolierFactor);

		//Elder: added pistol and knife condition
		if (ent->item->giTag == WP_GRENADE || ent->item->giTag == WP_PISTOL || ent->item->giTag == WP_KNIFE) {
			respawn = 30;
		} else {
			//Elder: moved here
			respawn = -1;	//Dont respawn weapons
		}

//              predict = qfalse;
		break;
	case IT_AMMO:
		switch (ent->item->giTag) {
			//Blaze: dont pick up the clip if we already have all the clips we can have
		case WP_KNIFE:
			if (other->client->numClips[ent->item->giTag] >= 0)
				return;	//No clips for knifes
			break;
		case WP_PISTOL:
			if (other->client->numClips[ent->item->giTag] >= RQ3_PISTOL_MAXCLIP * bandolierFactor)
				return;
			break;
		case WP_M3:
			if (other->client->numClips[ent->item->giTag] >= RQ3_M3_MAXCLIP * bandolierFactor)
				return;
			break;
		case WP_HANDCANNON:
			if (other->client->numClips[ent->item->giTag] >= RQ3_HANDCANNON_MAXCLIP * bandolierFactor)
				return;
			break;
		case WP_MP5:
			if (other->client->numClips[ent->item->giTag] >= RQ3_MP5_MAXCLIP * bandolierFactor)
				return;
			break;
		case WP_M4:
			if (other->client->numClips[ent->item->giTag] >= RQ3_M4_MAXCLIP * bandolierFactor)
				return;
			break;
		case WP_SSG3000:
			if (other->client->numClips[ent->item->giTag] >= RQ3_SSG3000_MAXCLIP * bandolierFactor)
				return;
			break;
		case WP_AKIMBO:
			if (other->client->numClips[ent->item->giTag] >= RQ3_AKIMBO_MAXCLIP * bandolierFactor)
				return;
			break;
		case WP_GRENADE:
			if (other->client->numClips[ent->item->giTag] >= 0)
				return;	//no clips for grenades
			break;
		}
		respawn = Pickup_Ammo(ent, other, bandolierFactor);
		break;
	case IT_ARMOR:
		respawn = Pickup_Armor(ent, other);
		break;
	case IT_HEALTH:
		respawn = Pickup_Health(ent, other);
		break;
	case IT_POWERUP:
		respawn = Pickup_Powerup(ent, other);
		predict = qfalse;
		break;
	case IT_TEAM:
		// NiceAss: can't pick it up if it's in mid-flight (someone dropped it)
		if (ent->s.pos.trDelta[2] != 0.0f)
			return;
		respawn = Pickup_Team(ent, other);
		break;
	case IT_HOLDABLE:
		//Elder: check to see if it's in mid-air
		if (other->client->uniqueItems >= g_RQ3_maxItems.integer || ent->s.pos.trDelta[2] != 0)
			return;
		respawn = Pickup_Holdable(ent, other);
		break;
	default:
		return;
	}

	if (!respawn) {
		return;
	}

	// play the normal pickup sound
	if (predict) {
		G_AddPredictableEvent(other, EV_ITEM_PICKUP, ent->s.modelindex);
	} else {
		G_AddEvent(other, EV_ITEM_PICKUP, ent->s.modelindex);
	}

	// powerup pickups are global broadcasts
	if (ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) {
		// if we want the global sound to play
		if (!ent->speed) {
			gentity_t *te;

			te = G_TempEntity(ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP);
			te->s.eventParm = ent->s.modelindex;
			te->r.svFlags |= SVF_BROADCAST;
		} else {
			gentity_t *te;

			te = G_TempEntity(ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP);
			te->s.eventParm = ent->s.modelindex;
			// only send this temp entity to a single client
			te->r.svFlags |= SVF_SINGLECLIENT;
			te->r.singleClient = other->s.number;
		}
	}
	// fire item targets
	G_UseTargets(ent, other);

	// wait of -1 will not respawn
	if (ent->wait == -1) {
		ent->r.svFlags |= SVF_NOCLIENT;
		ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		ent->unlinkAfterEvent = qtrue;
		return;
	}
	// non zero wait overrides respawn time
	if (ent->wait) {
		respawn = ent->wait;
	}
	// random can be used to vary the respawn time
	if (ent->random) {
		respawn += crandom() * ent->random;
		if (respawn < 1) {
			respawn = 1;
		}
	}
	// dropped items will not respawn
	if (ent->flags & FL_DROPPED_ITEM) {
		ent->freeAfterEvent = qtrue;
	}
	// picked up items still stay around, they just don't
	// draw anything.  This allows respawnable items
	// to be placed on movers.
	ent->r.svFlags |= SVF_NOCLIENT;
	ent->s.eFlags |= EF_NODRAW;
	ent->r.contents = 0;

	// ZOID
	// A negative respawn times means to never respawn this item (but don't
	// delete it).  This is used by items that are respawned by third party
	// events such as ctf flags
	if (respawn <= 0) {
		ent->nextthink = 0;
		ent->think = 0;
	} else {
		ent->nextthink = level.time + respawn * 1000;
		ent->think = RespawnItem;
	}
	trap_LinkEntity(ent);
}
Example #10
0
/*
===============
CheckGrabAttack
===============
*/
void CheckGrabAttack( gentity_t *ent )
{
	trace_t   tr;
	vec3_t    end, dir;
	gentity_t *traceEnt;

	// set aiming directions
	AngleVectors( ent->client->ps.viewangles, forward, right, up );

	CalcMuzzlePoint( ent, forward, right, up, muzzle );

	if ( ent->client->ps.weapon == WP_ALEVEL1 )
	{
		VectorMA( muzzle, LEVEL1_GRAB_RANGE, forward, end );
	}
	else if ( ent->client->ps.weapon == WP_ALEVEL1_UPG )
	{
		VectorMA( muzzle, LEVEL1_GRAB_U_RANGE, forward, end );
	}

	trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );

	if ( tr.surfaceFlags & SURF_NOIMPACT )
	{
		return;
	}

	traceEnt = &g_entities[ tr.entityNum ];

	if ( !traceEnt->takedamage )
	{
		return;
	}

	if ( traceEnt->client )
	{
		if ( traceEnt->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
		{
			return;
		}

		if ( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 )
		{
			return;
		}

		if ( !( traceEnt->client->ps.stats[ STAT_STATE ] & SS_GRABBED ) )
		{
			AngleVectors( traceEnt->client->ps.viewangles, dir, NULL, NULL );
			traceEnt->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );

			//event for client side grab effect
			G_AddPredictableEvent( ent, EV_LEV1_GRAB, 0 );
		}

		traceEnt->client->ps.stats[ STAT_STATE ] |= SS_GRABBED;

		if ( ent->client->ps.weapon == WP_ALEVEL1 )
		{
			traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_TIME;

			// Update the last combat time.
			ent->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
			traceEnt->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
		}
		else if ( ent->client->ps.weapon == WP_ALEVEL1_UPG )
		{
			traceEnt->client->grabExpiryTime = level.time + LEVEL1_GRAB_U_TIME;

			// Update the last combat time.
			ent->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
			traceEnt->client->lastCombatTime = level.time + LEVEL1_GRAB_TIME;
		}
	}
}
Example #11
0
/*
===============
Touch_Item
===============
*/
void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
	int			respawn;
	qboolean	predict;

	//instant gib
	if ((g_instantgib.integer || g_rockets.integer || g_gametype.integer == GT_CTF_ELIMINATION || g_elimination_allgametypes.integer)
                && ent->item->giType != IT_TEAM)
		return;

	//Cannot touch flag before round starts
	if(g_gametype.integer == GT_CTF_ELIMINATION && level.roundNumber != level.roundNumberStarted)
		return;

	//Cannot take ctf elimination oneway
	if(g_gametype.integer == GT_CTF_ELIMINATION && g_elimination_ctf_oneway.integer!=0 && (
			(other->client->sess.sessionTeam==TEAM_BLUE && (level.eliminationSides+level.roundNumber)%2 == 0 ) ||
			(other->client->sess.sessionTeam==TEAM_RED && (level.eliminationSides+level.roundNumber)%2 != 0 ) ))
		return;

	if (g_gametype.integer == GT_ELIMINATION || g_gametype.integer == GT_LMS)
		return;		//nothing to pick up in elimination

	if (!other->client)
		return;
	if (other->health < 1)
		return;		// dead people can't pickup

	// the same pickup rules are used for client side and server side
	if ( !BG_CanItemBeGrabbed( g_gametype.integer, &ent->s, &other->client->ps ) ) {
		return;
	}

	//In double DD we cannot "pick up" a flag we already got
	if(g_gametype.integer == GT_DOUBLE_D) {
		if( strcmp(ent->classname, "team_CTF_redflag") == 0 )
			if(other->client->sess.sessionTeam == level.pointStatusA)
				return;
		if( strcmp(ent->classname, "team_CTF_blueflag") == 0 )
			if(other->client->sess.sessionTeam == level.pointStatusB)
				return;
	}

	G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname );

	predict = other->client->pers.predictItemPickup;

	// call the item-specific pickup function
	switch( ent->item->giType ) {
	case IT_WEAPON:
		respawn = Pickup_Weapon(ent, other);
//		predict = qfalse;
		break;
	case IT_AMMO:
		respawn = Pickup_Ammo(ent, other);
//		predict = qfalse;
		break;
	case IT_ARMOR:
		respawn = Pickup_Armor(ent, other);
		break;
	case IT_HEALTH:
		respawn = Pickup_Health(ent, other);
		break;
	case IT_POWERUP:
		respawn = Pickup_Powerup(ent, other);
		predict = qfalse;
		break;
	case IT_PERSISTANT_POWERUP:
		respawn = Pickup_PersistantPowerup(ent, other);
		break;
	case IT_TEAM:
		respawn = Pickup_Team(ent, other);
                //If touching a team item remove spawnprotection
                if(other->client->spawnprotected)
                    other->client->spawnprotected = qfalse;
		break;
	case IT_HOLDABLE:
		respawn = Pickup_Holdable(ent, other);
		break;
	default:
		return;
	}

	if ( !respawn ) {
		return;
	}

	// play the normal pickup sound
	if (predict) {
		G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
	} else {
		G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
	}

	// powerup pickups are global broadcasts
	if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) {
		// if we want the global sound to play
		if (!ent->speed) {
			gentity_t	*te;

			te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
			te->s.eventParm = ent->s.modelindex;
			te->r.svFlags |= SVF_BROADCAST;
		} else {
			gentity_t	*te;

			te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
			te->s.eventParm = ent->s.modelindex;
			// only send this temp entity to a single client
			te->r.svFlags |= SVF_SINGLECLIENT;
			te->r.singleClient = other->s.number;
		}
	}

	// fire item targets
	G_UseTargets (ent, other);

	// wait of -1 will not respawn
	if ( ent->wait == -1 ) {
		ent->r.svFlags |= SVF_NOCLIENT;
		ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		ent->unlinkAfterEvent = qtrue;
		return;
	}

	// non zero wait overrides respawn time
	if ( ent->wait ) {
		respawn = ent->wait;
	}

	// random can be used to vary the respawn time
	if ( ent->random ) {
		respawn += crandom() * ent->random;
		if ( respawn < 1 ) {
			respawn = 1;
		}
	}

	// dropped items will not respawn
	if ( ent->flags & FL_DROPPED_ITEM ) {
		ent->freeAfterEvent = qtrue;
	}

	// picked up items still stay around, they just don't
	// draw anything.  This allows respawnable items
	// to be placed on movers.
	ent->r.svFlags |= SVF_NOCLIENT;
	ent->s.eFlags |= EF_NODRAW;
	ent->r.contents = 0;

	// ZOID
	// A negative respawn times means to never respawn this item (but don't 
	// delete it).  This is used by items that are respawned by third party 
	// events such as ctf flags
	if ( respawn <= 0 ) {
		ent->nextthink = 0;
		ent->think = 0;
	} else {
		ent->nextthink = level.time + respawn * 1000;
		ent->think = RespawnItem;
	}
	trap_LinkEntity( ent );
}
void explodedretch(gentity_t *ent)
{
    int       i;
    int         entityList[ MAX_GENTITIES ];
		vec3_t      range;
		vec3_t      mins, maxs;
		int         num;
		gentity_t   *enemy;
		float       creepSize = (float)650;
		int freezedcounter = 0;
    
    //gentity_t *gren;
    if(ent->client->ps.persistant[ PERS_CREDIT ] < 1) //Neeeddd fix <3
    {
        trap_SendServerCommand( ent-g_entities, "print \"^5Overmind: ^7You need 1 evos to explode.\n\"" );
    }
    else
    {
        ent->client->ps.persistant[ PERS_CREDIT ] -= 1;
        G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, 0 );
        G_RadiusDamage( ent->r.currentOrigin, ent, 200,
                     200, ent, MOD_GRENADE);
        G_Damage( ent, ent, ent, NULL, NULL, 10000, 0, MOD_UNKNOWN );
        
        
        //Slow down enemy around.
        VectorSet( range, creepSize, creepSize, creepSize );

        VectorAdd( ent->s.origin, range, maxs );
        VectorSubtract( ent->s.origin, range, mins );

        //find enemys around me
        num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
        for( i = 0; i < num; i++ )
        {
            enemy = &g_entities[ entityList[ i ] ];

            if( enemy->flags & FL_NOTARGET )
                continue;
            if( enemy->client && (enemy->client->ps.stats[ STAT_PTEAM ] != ent->client->ps.stats[ STAT_PTEAM ] ) && G_Visible( ent, enemy ) )
            {
                //enemy->client->ps.stats[ STAT_STATE ] |= SS_CREEPSLOWED;
                enemy->client->ps.stats[ STAT_STATE ] |= SS_ICEWAVED;
                enemy->client->lastCreepSlowTime = level.time + 5000;
                freezedcounter++;
                //G_SelectiveRadiusDamage( ent->s.pos.trBase, ent, (float)dmg, (float)500, ent, MOD_SLOWBLOB, ent->client->ps.stats[ STAT_PTEAM ] );
            }
        }
        if(ent->client){
        //29  	Freezing Field  	Icewave over 5 enemies in 1 icewave 
			if(ent->client->pers.badges[ 29 ] != 1  && freezedcounter >= 5)
			{
				ent->client->pers.badgeupdate[29] = 1;
				ent->client->pers.badges[29] = 1;
				G_WinBadge( ent, 29 );
			}
		}
    }
    /*
    
    if(ent->client->pers.teamSelection != PTE_HUMANS
    && ent->client->pers.teamSelection != PTE_ALIENS )
    {  
        trap_SendServerCommand( ent-g_entities, va(
        "print \"^1You must be on a team\n\"" ) );
                return qfalse;
    }

    if(ent->client->pers.classSelection == PCL_NONE)
    {  
        trap_SendServerCommand( ent-g_entities, va(
        "print \"^1You must be alive\n\"" ) );
                return qfalse;
    }
    if(ent->client->pers.energy >= 500)
    {  
        if(ent->client->pers.teamSelection == PTE_HUMANS)
        {
            dmg = 3;
        }
        if(ent->client->pers.teamSelection == PTE_ALIENS)
        {
            dmg = 1;
        }

        ent->client->pers.energy-= 500;
        G_AddEvent( ent, EV_ALIEN_BUILDABLE_EXPLOSION, 0 );

        VectorSet( range, creepSize, creepSize, creepSize );

        VectorAdd( ent->s.origin, range, maxs );
        VectorSubtract( ent->s.origin, range, mins );

        //find enemys around me
        num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
        for( i = 0; i < num; i++ )
        {
            enemy = &g_entities[ entityList[ i ] ];

            if( enemy->flags & FL_NOTARGET )
                continue;
            if( enemy->client && (enemy->client->ps.stats[ STAT_PTEAM ] != ent->client->ps.stats[ STAT_PTEAM ] ) && G_Visible( ent, enemy ) )
            {
                //enemy->client->ps.stats[ STAT_STATE ] |= SS_CREEPSLOWED;
                enemy->client->ps.stats[ STAT_STATE ] |= SS_ICEWAVED;
                enemy->client->lastCreepSlowTime = level.time + 5000;
                //G_SelectiveRadiusDamage( ent->s.pos.trBase, ent, (float)dmg, (float)500, ent, MOD_SLOWBLOB, ent->client->ps.stats[ STAT_PTEAM ] );
            }
        }
        return qtrue;
    }*/
}
Example #13
0
	virtual void execute( GameEntity *other, trace_t *trace ) 
	{
		int		respawn;
		bool	predict;
		GameEntity*	self = self_;  // Since we may delete our current think()

		if( !other->client_ )
			return;
		if( other->health_ < 1 )
			return;		// dead people can't pickup
		if( other->client_->ps_.pm_type == PM_SPECTATOR )
			return;

		// the same pickup rules are used for client side and server side
		if ( !BG_CanItemBeGrabbed( g_gametype.integer, &self->s, &other->client_->ps_, other->client_->vehicle_ ) ) 
			return;

		G_LogPrintf( "Item: %i %s\n", other->s.number, self->item_->classname );

		predict = other->client_->pers_.predictItemPickup_;

		// call the item-specific pickup function
		switch( self->item_->giType )
		{
		case IT_AMMO:
			respawn = Pickup_Ammo(self, other);
			break;
		case IT_HEALTH:
			respawn = Pickup_Health(self, other);
			break;
		case IT_FUEL:
			respawn = Pickup_Fuel(self, other);
			break;
		case IT_TEAM:
			respawn = Pickup_Team(self, other);
			break;
		default:
			return;
		}

		if ( !respawn ) 
			return;

		// play the normal pickup sound
		if( predict ) 
			G_AddPredictableEvent( other, EV_ITEM_PICKUP, self->s.modelindex );
		else 
			G_AddEvent( other, EV_ITEM_PICKUP, self->s.modelindex, true );

		// powerup pickups are global broadcasts
		if( self->item_->giType == IT_TEAM) 
		{
			// if we want the global sound to play
			if( !self->speed_ ) 
			{
				GameEntity	*te;
				te = G_TempEntity( self->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
				te->s.eventParm = self->s.modelindex;
				te->r.svFlags |= SVF_BROADCAST;
			} 
			else 
			{
				GameEntity	*te;
				te = G_TempEntity( self->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
				te->s.eventParm = self->s.modelindex;
				// only send this temp entity to a single client
				te->r.svFlags |= SVF_SINGLECLIENT;
				te->r.singleClient = other->s.number;
			}
		}

		// fire item targets
		G_UseTargets (self, other);

		// wait of -1 will not respawn
		if( self->wait_ == -1 ) 
		{
			self->r.svFlags |= SVF_NOCLIENT;
			self->s.eFlags |= EF_NODRAW;
			self->r.contents = 0;
			self->unlinkAfterEvent_ = true;
			return;
		}

		// non zero wait overrides respawn time
		if( self->wait_ ) 
			respawn = self->wait_;

		// random can be used to vary the respawn time
		if( self->random_ ) 
		{
			respawn += crandom() * self->random_;
			if ( respawn < 1 ) 
				respawn = 1;
		}

		// dropped items will not respawn
		if( self->flags_ & FL_DROPPED_ITEM ) 
			self->freeAfterEvent_ = true;

		// picked up items still stay around, they just don't
		// draw anything.  This allows respawnable items
		// to be placed on movers.
		self->r.svFlags |= SVF_NOCLIENT;
		self->s.eFlags |= EF_NODRAW;
		self->r.contents = 0;

		// ZOID
		// A negative respawn times means to never respawn this item (but don't 
		// delete it).  This is used by items that are respawned by third party 
		// events such as ctf flags
		if( respawn <= 0 ) 
		{
			self->nextthink_ = 0;
			self->setThink(0);
		} 
		else 
		{
			self->nextthink_ = theLevel.time_ + respawn * 1000;
			self->setThink(new Think_RespawnItem);
		}
		SV_LinkEntity( self );
	}
Example #14
0
void heal_touch(gentity_t *self, gentity_t *other, trace_t *trace)
{
	int       i, j, clientcount = 0;
	gentity_t *touchClients[MAX_CLIENTS];
	int       healvalue;

	memset(touchClients, 0, sizeof(gentity_t *) * MAX_CLIENTS);

	if (!other->client)
	{
		return;
	}

	if (self->timestamp > level.time)
	{
		return;
	}
	self->timestamp = level.time + 1000;

	for (i = 0; i < level.numConnectedClients; i++)
	{
		j = level.sortedClients[i];

		if (trap_EntityContactCapsule(g_entities[j].r.absmin, g_entities[j].r.absmax, self) && G_IsAllowedHeal(&g_entities[j]))
		{
			touchClients[clientcount] = &g_entities[j];
			clientcount++;
		}
	}

	if (clientcount == 0)
	{
		return;
	}

	for (i = 0; i < clientcount; i++)
	{
		if (touchClients[i]->client->sess.playerType == PC_MEDIC)
		{
			healvalue = MIN((int)(touchClients[i]->client->ps.stats[STAT_MAX_HEALTH] * 1.12) - touchClients[i]->health, self->damage);
		}
		else
		{
			healvalue = MIN(touchClients[i]->client->ps.stats[STAT_MAX_HEALTH] - touchClients[i]->health, self->damage);
		}

		if (self->health != -9999)
		{
			healvalue = MIN(healvalue, self->health);
		}
		if (healvalue <= 0)
		{
			continue;
		}

		touchClients[i]->health += healvalue;
		// add the medicheal event (to get sound, etc.)
		G_AddPredictableEvent(other, EV_ITEM_PICKUP, BG_GetItem(ITEM_HEALTH_CABINET) - bg_itemlist);

		if (self->health != -9999)
		{
			self->health -= healvalue;
		}
	}
}
Example #15
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles )
{
  int                 index;
  vec3_t              spawn_origin, spawn_angles;
  gclient_t           *client;
  int                 i;
  clientPersistant_t  saved;
  clientSession_t     savedSess;
  int                 persistant[ MAX_PERSISTANT ];
  gentity_t           *spawnPoint = NULL, *event;
  int                 flags;
  int                 savedPing;
  int                 teamLocal;
  int                 eventSequence;
  char                userinfo[ MAX_INFO_STRING ];
  vec3_t              up = { 0.0f, 0.0f, 1.0f }, implant_dir, implant_angles, spawnPoint_velocity;
  int                 maxAmmo, maxClips;
  weapon_t            weapon;
  qboolean            fromImplant = qfalse, hatchingFailed = qfalse;

  index = ent - g_entities;
  client = ent->client;

  teamLocal = client->pers.teamSelection;

  //if client is dead and following teammate, stop following before spawning
  if( client->sess.spectatorClient != -1 )
  {
    client->sess.spectatorClient = -1;
    client->sess.spectatorState = SPECTATOR_FREE;
  }

  // only start client if chosen a class and joined a team
  if( client->pers.classSelection == PCL_NONE && teamLocal == TEAM_NONE )
    client->sess.spectatorState = SPECTATOR_FREE;
  else if( client->pers.classSelection == PCL_NONE )
    client->sess.spectatorState = SPECTATOR_LOCKED;

  // if client is dead and following teammate, stop following before spawning
  if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
    G_StopFollowing( ent );

  if( origin != NULL )
    VectorCopy( origin, spawn_origin );

  if( angles != NULL )
    VectorCopy( angles, spawn_angles );

  // find a spawn point
  // do it before setting health back up, so farthest
  // ranging doesn't count this client
  if( client->sess.spectatorState != SPECTATOR_NOT )
  {
    if( teamLocal == TEAM_NONE )
      spawnPoint = G_SelectSpectatorSpawnPoint( spawn_origin, spawn_angles );
    else if( teamLocal == TEAM_ALIENS )
      spawnPoint = G_SelectAlienLockSpawnPoint( spawn_origin, spawn_angles );
    else if( teamLocal == TEAM_HUMANS )
      spawnPoint = G_SelectHumanLockSpawnPoint( spawn_origin, spawn_angles );
  }
  else
  {
    if( spawn == NULL )
    {
      G_Error( "ClientSpawn: spawn is NULL\n" );
      return;
    }

    spawnPoint = spawn;

    if( ent != spawn )
    {
      if( !spawnPoint->client ) //might be a human
      {
        //start spawn animation on spawnPoint
        G_SetBuildableAnim( spawnPoint, BANIM_SPAWN1, qtrue );

        if( spawnPoint->buildableTeam == TEAM_ALIENS )
          spawnPoint->clientSpawnTime = ALIEN_SPAWN_REPEAT_TIME;
        else if( spawnPoint->buildableTeam == TEAM_HUMANS )
          spawnPoint->clientSpawnTime = HUMAN_SPAWN_REPEAT_TIME;
      }
      else
      {
        qboolean crouch;
        int i;
        float zoffs = 0.0f;
        trace_t tr;
        vec3_t neworigin, mins, maxs;
        
        fromImplant = qtrue; //spawning from a human
        
        // move the origin a bit on the Z axis so the aliens jumps out of the chest, not knees
        // also prevents grangers from getting stuck in ceilings and floors
        crouch = spawnPoint->client->ps.pm_flags & PMF_DUCKED;
        switch( client->pers.classSelection )
        {
          case PCL_ALIEN_BUILDER0:
            if( !crouch )
              zoffs = 19.0f;
            else
              zoffs = -4.0f;
            break;
          case PCL_ALIEN_BUILDER0_UPG:
            if( !crouch )
              zoffs = 16.5f;
            else
              zoffs = -4.0f;
            break;
          case PCL_ALIEN_LEVEL0:
            if( !crouch )
              zoffs = 15.0f;
            else
              zoffs = -9.1f;
            break;
        }
        spawn_origin[ 2 ] += zoffs;
        
        // check if the spot would block
        BG_ClassBoundingBox( client->pers.classSelection, mins, maxs, NULL, NULL, NULL );
        trap_Trace( &tr, spawn_origin, mins, maxs, spawn_origin, spawnPoint->s.number, MASK_PLAYERSOLID );
        
        // try to unblock the player
        if( tr.startsolid )
        {
          Com_Printf("DEBUG: player is stuck!\n");
          for( i = 0; i < 16*2; i++ )
          {
            float a, r;
            
            VectorCopy( spawn_origin, neworigin );
            
            a = (float)i / 16.0f * 2.0f * M_PI;
            #define fmod(a,n) ((a)-(n)*floor((a)/(n)))
            r = ( i < 16 ? 5.5f : 11.0f ) * 1.0f / cos( fmod( a+0.25f*M_PI, 0.5f*M_PI ) - 0.25f*M_PI );
            neworigin[ 0 ] += cos( a ) * r;
            neworigin[ 1 ] += sin( a ) * r;
            
            trap_Trace( &tr, neworigin, mins, maxs, neworigin, spawnPoint->s.number, MASK_PLAYERSOLID );
            
            if( !tr.startsolid )
            {
             Com_Printf("DEBUG: player position fixed at iteration %i\n",i);
             VectorCopy( neworigin, spawn_origin );
             break;
            }
          }
        }
        
        //reward the player that implanted this one
        if( spawnPoint->client->impregnatedBy >= 0 )
        {
          gentity_t *granger;
          
          granger = &g_entities[ spawnPoint->client->impregnatedBy ];
          G_AddCreditToClient( granger->client, ALIEN_IMPREGNATION_REWARD, qtrue );  
          AddScore( granger, ALIEN_IMPREGNATION_REWARD_SCORE );
        }
        
        // kill the human, set up angles and velocity for the new alien
        if( !BG_InventoryContainsUpgrade( UP_BATTLESUIT, spawnPoint->client->ps.stats ) //humans without battlesuits always die
            || spawnPoint->client->ps.stats[ STAT_HEALTH ] < ALIEN_HATCHING_MAX_BATTLESUIT_HEALTH ) //battlesuits survive if high hp
        {
          //save viewangles and spawn velocity for velocity calculation
          VectorCopy( spawnPoint->client->ps.viewangles, implant_angles );
          AngleVectors( implant_angles, implant_dir, NULL, NULL );
          VectorCopy( spawnPoint->client->ps.velocity, spawnPoint_velocity );

          //fire a nice chest exploding effect
          event = G_TempEntity( spawnPoint->s.pos.trBase, EV_ALIEN_HATCH );
          VectorCopy( implant_dir, event->s.angles );

          //kill the player
          G_Damage( spawnPoint, NULL, ent, NULL, NULL, spawnPoint->client->ps.stats[ STAT_HEALTH ], DAMAGE_NO_ARMOR, MOD_ALIEN_HATCH );
        }
        else //human survives
        {
          //clear impregnation so the human won't explode again
          spawnPoint->client->isImpregnated = qfalse;
          spawnPoint->client->isImplantMature = qfalse;
          
          //make a sound
          event = G_TempEntity( spawnPoint->s.pos.trBase, EV_ALIEN_HATCH_FAILURE );

          //damage the human
          G_Damage( spawnPoint, NULL, ent, NULL, NULL, ALIEN_FAILED_HATCH_DAMAGE, DAMAGE_NO_ARMOR, MOD_ALIEN_HATCH );

          //kill the newly spawned alien
          VectorCopy( spawnPoint->client->ps.viewangles, implant_angles );
          implant_dir[0] = 0.0f;
          implant_dir[1] = 0.0f;
          implant_dir[2] = 0.0f;
          hatchingFailed = qtrue;
        }
      }
    }
  }

  // toggle the teleport bit so the client knows to not lerp
  flags = ( ent->client->ps.eFlags & EF_TELEPORT_BIT ) ^ EF_TELEPORT_BIT;
  G_UnlaggedClear( ent );

  // clear everything but the persistant data

  saved = client->pers;
  savedSess = client->sess;
  savedPing = client->ps.ping;

  for( i = 0; i < MAX_PERSISTANT; i++ )
    persistant[ i ] = client->ps.persistant[ i ];

  eventSequence = client->ps.eventSequence;
  memset( client, 0, sizeof( *client ) );

  client->pers = saved;
  client->sess = savedSess;
  client->ps.ping = savedPing;
  client->lastkilled_client = -1;

  for( i = 0; i < MAX_PERSISTANT; i++ )
    client->ps.persistant[ i ] = persistant[ i ];

  client->ps.eventSequence = eventSequence;

  // increment the spawncount so the client will detect the respawn
  client->ps.persistant[ PERS_SPAWN_COUNT ]++;
  client->ps.persistant[ PERS_SPECSTATE ] = client->sess.spectatorState;

  client->airOutTime = level.time + 12000;

  trap_GetUserinfo( index, userinfo, sizeof( userinfo ) );
  client->ps.eFlags = flags;

  //Com_Printf( "ent->client->pers->pclass = %i\n", ent->client->pers.classSelection );

  ent->s.groundEntityNum = ENTITYNUM_NONE;
  ent->client = &level.clients[ index ];
  ent->takedamage = qtrue;
  ent->inuse = qtrue;
  ent->classname = "player";
  ent->r.contents = CONTENTS_BODY;
  ent->clipmask = MASK_PLAYERSOLID;
  ent->die = player_die;
  ent->waterlevel = 0;
  ent->watertype = 0;
  ent->flags = 0;

  // calculate each client's acceleration
  ent->evaluateAcceleration = qtrue;

  client->ps.stats[ STAT_MISC ] = 0;
  client->buildTimer = 0;

  client->ps.eFlags = flags;
  client->ps.clientNum = index;

  BG_ClassBoundingBox( ent->client->pers.classSelection, ent->r.mins, ent->r.maxs, NULL, NULL, NULL );

  if( client->sess.spectatorState == SPECTATOR_NOT )
    client->ps.stats[ STAT_MAX_HEALTH ] =
      BG_Class( ent->client->pers.classSelection )->health;
  else
    client->ps.stats[ STAT_MAX_HEALTH ] = 100;

  // clear entity values
  if( ent->client->pers.classSelection == PCL_HUMAN )
  {
    BG_AddUpgradeToInventory( UP_MEDKIT, client->ps.stats );
    weapon = client->pers.humanItemSelection;
  }
  else if( client->sess.spectatorState == SPECTATOR_NOT )
    weapon = BG_Class( ent->client->pers.classSelection )->startWeapon;
  else
    weapon = WP_NONE;

  maxAmmo = BG_Weapon( weapon )->maxAmmo;
  maxClips = BG_Weapon( weapon )->maxClips;
  client->ps.stats[ STAT_WEAPON ] = weapon;
  client->ps.ammo = maxAmmo;
  client->ps.clips = maxClips;

  // We just spawned, not changing weapons
  client->ps.persistant[ PERS_NEWWEAPON ] = 0;

  ent->client->ps.stats[ STAT_CLASS ] = ent->client->pers.classSelection;
  ent->client->ps.stats[ STAT_TEAM ] = ent->client->pers.teamSelection;

  ent->client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
  ent->client->ps.stats[ STAT_STATE ] = 0;
  VectorSet( ent->client->ps.grapplePoint, 0.0f, 0.0f, 1.0f );

  // health will count down towards max_health
  ent->health = client->ps.stats[ STAT_HEALTH ] = client->ps.stats[ STAT_MAX_HEALTH ]; //* 1.25;

  //if evolving scale health
  if( ent == spawn )
  {
    ent->health *= ent->client->pers.evolveHealthFraction;
    client->ps.stats[ STAT_HEALTH ] *= ent->client->pers.evolveHealthFraction;
  }

  //clear the credits array
  for( i = 0; i < MAX_CLIENTS; i++ )
    ent->credits[ i ] = 0;

  client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX;
  
  //never impregnated after respawning
  client->isImpregnated = qfalse;
  client->isImplantMature = qfalse;
  
  G_SetOrigin( ent, spawn_origin );
  VectorCopy( spawn_origin, client->ps.origin );

#define UP_VEL  150.0f
#define F_VEL   50.0f

  //give aliens some spawn velocity
  if( client->sess.spectatorState == SPECTATOR_NOT &&
      client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
  {
    if( ent == spawn )
    {
      //evolution particle system
      G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, DirToByte( up ) );
    }
    else if( !fromImplant ) //regular egg
    {
      spawn_angles[ YAW ] += 180.0f;
      AngleNormalize360( spawn_angles[ YAW ] );

      if( spawnPoint->s.origin2[ 2 ] > 0.0f )
      {
        vec3_t  forward, dir;

        AngleVectors( spawn_angles, forward, NULL, NULL );
        VectorScale( forward, F_VEL, forward );
        VectorAdd( spawnPoint->s.origin2, forward, dir );
        VectorNormalize( dir );

        VectorScale( dir, UP_VEL, client->ps.velocity );
      }

      G_AddPredictableEvent( ent, EV_PLAYER_RESPAWN, 0 );
    }
    else //implanted egg
    {
      VectorCopy( implant_angles, spawn_angles );
      VectorScale( implant_dir, ALIEN_HATCHING_VELOCITY, client->ps.velocity );
      VectorAdd( client->ps.velocity, spawnPoint_velocity, client->ps.velocity );
    }
  }
  else if( client->sess.spectatorState == SPECTATOR_NOT &&
           client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
  {
    spawn_angles[ YAW ] += 180.0f;
    AngleNormalize360( spawn_angles[ YAW ] );
  }

  // the respawned flag will be cleared after the attack and jump keys come up
  client->ps.pm_flags |= PMF_RESPAWNED;

  trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
  G_SetClientViewAngle( ent, spawn_angles );

  if( client->sess.spectatorState == SPECTATOR_NOT )
  {
    trap_LinkEntity( ent );

    // force the base weapon up
    if( client->pers.teamSelection == TEAM_HUMANS )
      G_ForceWeaponChange( ent, weapon );

    client->ps.weaponstate = WEAPON_READY;
  }

  // don't allow full run speed for a bit
  client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
  client->ps.pm_time = 100;

  client->respawnTime = level.time;
  ent->nextRegenTime = level.time;

  client->inactivityTime = level.time + g_inactivity.integer * 1000;
  client->latched_buttons = 0;

  // set default animations
  client->ps.torsoAnim = TORSO_STAND;
  client->ps.legsAnim = LEGS_IDLE;

  if( level.intermissiontime )
    MoveClientToIntermission( ent );
  else
  {
    // fire the targets of the spawn point
    if( !spawn )
      G_UseTargets( spawnPoint, ent );

    // select the highest weapon number available, after any
    // spawn given items have fired
    client->ps.weapon = 1;

    for( i = WP_NUM_WEAPONS - 1; i > 0 ; i-- )
    {
      if( BG_InventoryContainsWeapon( i, client->ps.stats ) )
      {
        client->ps.weapon = i;
        break;
      }
    }
  }

  client->lastRantBombTime = level.time;
  
  // run a client frame to drop exactly to the floor,
  // initialize animations and other things
  client->ps.commandTime = level.time - 100;
  ent->client->pers.cmd.serverTime = level.time;
  ClientThink( ent-g_entities );

  // positively link the client, even if the command times are weird
  if( client->sess.spectatorState == SPECTATOR_NOT )
  {
    BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
    VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
    trap_LinkEntity( ent );
  }

  // must do this here so the number of active clients is calculated
  CalculateRanks( );

  // run the presend to set anything else
  ClientEndFrame( ent );

  // clear entity state values
  BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
  
  // kill him instantly after respawning if hatching failed
  if( fromImplant && hatchingFailed )
  {
    VectorCopy( spawnPoint->client->ps.velocity, client->ps.velocity );
    client->ps.stats[ STAT_HEALTH ] = ent->health = 0;
    player_die( ent, NULL, spawnPoint, 0, MOD_ALIEN_HATCH_FAILED );
  }
  
}
Example #16
0
/*
===============
Touch_Item
===============
*/
void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
	int			respawn;

	if (!other->client)
		return;
	if (other->health < 1)
		return;		// dead people can't pickup

    // RPG-X: Marcin: Press USE to pick up items. - 03/12/2008
    if ( !(other->client->pers.cmd.buttons & BUTTON_USE) || other->client->pressedUse == qtrue) {
        return;
	} else {
		other->client->pressedUse = qtrue;
	}

	// If ghosted, then end the ghost-ness in favor of the pickup.
	//RPG-X: RedTechie - Keep ghost all the time
	/*if (other->client->ps.powerups[PW_GHOST] >= level.time)
	{
		other->client->ps.powerups[PW_GHOST] = 0;	// Unghost the player.  This
	}*/

	// the same pickup rules are used for client side and server side
	if ( !BG_CanItemBeGrabbed( &ent->s, &other->client->ps, Max_Weapon(other->client->ps.weapon) )
		&& IsAdmin( other ) == qfalse )
	{
		return;
	}

	numTotalDropped--;

	G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname );

	// call the item-specific pickup function

	switch( ent->item->giType )
	{
	case IT_WEAPON:
		respawn = Pickup_Weapon(ent, other);
		break;
	case IT_AMMO:
		respawn = Pickup_Ammo(ent, other);
		break;
	case IT_ARMOR:
		respawn = Pickup_Armor(ent, other);
		break;
	case IT_HEALTH:
		respawn = Pickup_Health(ent, other);
		break;
	case IT_POWERUP:
		respawn = Pickup_Powerup(ent, other);
		break;
	case IT_TEAM:
		respawn = Pickup_Team(ent, other);
		break;
	case IT_HOLDABLE:
		respawn = Pickup_Holdable(ent, other);
		break;
	default:
		return;
	}

	if ( !respawn) {
		return;
	}

	// play the normal pickup sound
	if ( other->client->pers.predictItemPickup ) {
		G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
	} else {
		G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
	}

	// powerup pickups are global broadcasts
	if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) {
		gentity_t	*te;

		te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
		te->s.eventParm = ent->s.modelindex;
		// tell us which client fired off this global sound
		te->s.otherEntityNum = other->s.number;
		te->r.svFlags |= SVF_BROADCAST;
	}

	// fire item targets
	G_UseTargets (ent, other);

    if ( rpg_weaponsStay.integer == 1 && IsAdmin( ent->parent ) == qtrue && IsAdmin( other ) == qfalse ) {
        return;
    }

    if ( ent->item->giTag == WP_3 ) {
        Padd_Remove( ent );
    }
    
    // wait of -1 will not respawn
	if ( ent->wait == -1 ) {
		ent->r.svFlags |= SVF_NOCLIENT;
		ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		ent->unlinkAfterEvent = qtrue;
		return;
	}

	// non zero wait overrides respawn time
	if ( ent->wait ) {
		respawn = ent->wait;
	}

	// random can be used to vary the respawn time
	if ( ent->random ) {
		respawn += crandom() * ent->random;
		if ( respawn < 1 ) {
			respawn = 1;
		}
	}

	// dropped items will not respawn
	if ( ent->flags & FL_DROPPED_ITEM ) {
		ent->freeAfterEvent = qtrue;
	}

	// picked up items still stay around, they just don't
	// draw anything.  This allows respawnable items
	// to be placed on movers.

	if (ent->item->giType==IT_WEAPON || ent->item->giType==IT_POWERUP)
	{
		ent->s.eFlags |= EF_ITEMPLACEHOLDER;
	}
	else
	{
//	this line used to prevent items that were picked up from being drawn, but we now want to draw the techy grid thing instead
		ent->s.eFlags |= EF_NODRAW;
		ent->r.svFlags |= SVF_NOCLIENT;
	}

	ent->r.contents = 0;

// ***************
	// ZOID
	// A negative respawn times means to never respawn this item (but don't 
	// delete it).  This is used by items that are respawned by third party 
	// events such as ctf flags
	if ( respawn <= 0 ) {
		ent->nextthink = 0;
		ent->think = 0;
	} else {
        ent->nextthink = level.time + respawn * 1000;
		ent->think = RespawnItem;
	}
	trap_LinkEntity( ent );
}