Beispiel #1
0
/**
* @brief Get the primary weapon of the client.
* @return the primary weapon of the client
*/
weapon_t G_GetPrimaryWeaponForClient(gclient_t *client)
{
	int              i;
	bg_playerclass_t *classInfo;

	if (client->sess.sessionTeam != TEAM_ALLIES && client->sess.sessionTeam != TEAM_AXIS)
	{
		return WP_NONE;
	}

	if (client->sess.skill[SK_HEAVY_WEAPONS] < 4)
	{
		if (COM_BitCheck(client->ps.weapons, WP_THOMPSON))
		{
			return WP_THOMPSON;
		}
		if (COM_BitCheck(client->ps.weapons, WP_MP40))
		{
			return WP_MP40;
		}
	}

	classInfo = &bg_allies_playerclasses[client->sess.playerType];
	for (i = 0; i < MAX_WEAPS_PER_CLASS; i++)
	{
		if (classInfo->classWeapons[i] == WP_MP40 || classInfo->classWeapons[i] == WP_THOMPSON)
		{
			continue;
		}

		if (COM_BitCheck(client->ps.weapons, classInfo->classWeapons[i]))
		{
			return classInfo->classWeapons[i];
		}
	}

	classInfo = &bg_axis_playerclasses[client->sess.playerType];
	for (i = 0; i < MAX_WEAPS_PER_CLASS; i++)
	{
		if (classInfo->classWeapons[i] == WP_MP40 || classInfo->classWeapons[i] == WP_THOMPSON)
		{
			continue;
		}

		if (COM_BitCheck(client->ps.weapons, classInfo->classWeapons[i]))
		{
			return classInfo->classWeapons[i];
		}
	}

	return WP_NONE;
}
Beispiel #2
0
/**
* @brief Auto action when touching an item.
*
* PICKUP_ACTIVATE  (0), he will pick up items only when using +activate
* PICKUP_TOUCH     (1), he will pickup items when touched
* PICKUP_FORCE     (2), he will pickup the next item when touched (and reset to PICKUP_ACTIVATE when done)
*/
void Touch_Item_Auto(gentity_t *ent, gentity_t *other, trace_t *trace)
{
	if (other->client->pers.autoActivate == PICKUP_ACTIVATE)
	{
		return;
	}

	if (!ent->active && ent->item->giType == IT_WEAPON)
	{
		if (ent->item->giTag != WP_AMMO)
		{
			if (!COM_BitCheck(other->client->ps.weapons, ent->item->giTag))
			{
				return; // force activate only
			}
		}
	}

	ent->active = qtrue;
	Touch_Item(ent, other, trace);

	if (other->client->pers.autoActivate == PICKUP_FORCE)        // autoactivate probably forced by the "Cmd_Activate_f()" function
	{
		other->client->pers.autoActivate = PICKUP_ACTIVATE;      // so reset it.
	}
}
Beispiel #3
0
weapon_t G_GetPrimaryWeaponForClient( gclient_t *client )
{
	int i;
	bg_playerclass_t *classInfo;

	if( client->sess.sessionTeam != TEAM_ALLIES && client->sess.sessionTeam != TEAM_AXIS ) {
		return WP_NONE;
	}

	if( client->sess.skill[SK_HEAVY_WEAPONS] < 4 ||
		client->sess.playerType != PC_SOLDIER) {
		if( COM_BitCheck( client->ps.weapons, WP_THOMPSON ) )
			return WP_THOMPSON;
		if( COM_BitCheck( client->ps.weapons, WP_MP40 ) )
			return WP_MP40;
	}

	classInfo = &bg_allies_playerclasses[client->sess.playerType];

	// pheno: unlock weapons for allied team
	BG_UnlockWeapons(classInfo, client->sess.playerType, client->sess.sessionTeam);

	for( i = 0; i < MAX_WEAPS_PER_CLASS; i++) {
		if( classInfo->classWeapons[i] == WP_MP40 || classInfo->classWeapons[i] == WP_THOMPSON )
			continue;

		if( COM_BitCheck( client->ps.weapons, classInfo->classWeapons[i] ) ) {
			return classInfo->classWeapons[i];
		}
	}

	classInfo = &bg_axis_playerclasses[client->sess.playerType];

	// pheno: unlock weapons for axis team
	BG_UnlockWeapons(classInfo, client->sess.playerType, client->sess.sessionTeam);

	for( i = 0; i < MAX_WEAPS_PER_CLASS; i++) {
		if( classInfo->classWeapons[i] == WP_MP40 || classInfo->classWeapons[i] == WP_THOMPSON )
			continue;

		if( COM_BitCheck( client->ps.weapons, classInfo->classWeapons[i] ) ) {
			return classInfo->classWeapons[i];
		}
	}

	return WP_NONE;
}
/**
 * @brief Parses fireteam servercommand
 */
void CG_ParseFireteams()
{
	int        i, j;
	char       *s;
	const char *p;
	int        clnts[2];

	for (i = 0; i < MAX_CLIENTS; i++)
	{
		cgs.clientinfo[i].fireteamData = NULL;
	}

	for (i = 0; i < MAX_FIRETEAMS; i++)
	{
		char hexbuffer[11] = "0x00000000";

		p = CG_ConfigString(CS_FIRETEAMS + i);

		j = atoi(Info_ValueForKey(p, "id"));
		if (j == -1)
		{
			cg.fireTeams[i].inuse = qfalse;
			continue;
		}
		else
		{
			cg.fireTeams[i].inuse = qtrue;
			cg.fireTeams[i].ident = j;
		}

		s                      = Info_ValueForKey(p, "l");
		cg.fireTeams[i].leader = atoi(s);

		s                    = Info_ValueForKey(p, "p");
		cg.fireTeams[i].priv = (qboolean)atoi(s);

		s = Info_ValueForKey(p, "c");
		Q_strncpyz(hexbuffer + 2, s, 9);
		sscanf(hexbuffer, "%x", &clnts[1]);
		Q_strncpyz(hexbuffer + 2, s + 8, 9);
		sscanf(hexbuffer, "%x", &clnts[0]);

		for (j = 0; j < cgs.maxclients; j++)
		{
			if (COM_BitCheck(clnts, j))
			{
				cg.fireTeams[i].joinOrder[j]   = qtrue;
				cgs.clientinfo[j].fireteamData = &cg.fireTeams[i];
				//CG_Printf("%s\n", cgs.clientinfo[j].name);
			}
			else
			{
				cg.fireTeams[i].joinOrder[j] = qfalse;
			}
		}
	}

	CG_SortClientFireteam();
}
char *AIFunc_StimSoldierAttack1Start( cast_state_t *cs ) {
	gentity_t   *ent;
	//static vec3_t mins={-96,-96,0}, maxs={96,96,72};
	vec3_t pos, dir;
	trace_t tr;
	//
	cs->weaponFireTimes[cs->bs->weaponnum] = level.time;
	ent = &g_entities[cs->entityNum];
	//
	// face them
	AICast_AimAtEnemy( cs );
	// first, check if this is a good place to start the flying attack
	AngleVectors( cs->bs->ideal_viewangles, dir, NULL, NULL );
	VectorMA( cs->bs->origin, 300, dir, pos );
	pos[2] += 128;
	trap_Trace( &tr, cs->bs->origin, cs->bs->cur_ps.mins, cs->bs->cur_ps.maxs, pos, cs->entityNum, MASK_PLAYERSOLID );
	if ( tr.startsolid || tr.allsolid ) {
		return NULL;    // not a good place
	}
	// check we can attack them from there
	// select our special weapon (rocket launcher or tesla)
	if ( COM_BitCheck( cs->bs->cur_ps.weapons, WP_ROCKET_LAUNCHER ) ) {
		cs->bs->weaponnum = WP_ROCKET_LAUNCHER;
	} else if ( COM_BitCheck( cs->bs->cur_ps.weapons, WP_TESLA ) ) {
		cs->bs->weaponnum = WP_TESLA;
	} else {    // no weapon?
		G_Error( "stim soldier tried special jump attack without a tesla or rocket launcher\n" );
	}
	if ( !AICast_CheckAttackAtPos( cs->entityNum, cs->bs->enemy, pos, qfalse, qfalse ) ) {
		AICast_ChooseWeapon( cs, qfalse );
		return NULL;
	}
	// play the animation
	ent->client->ps.legsAnim =
		( ( ent->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | STIMSOLDIER_FLYJUMP_ANIM;
	ent->client->ps.legsTimer = STIMSOLDIER_FLYJUMP_DELAY;  // stay down until attack is finished
	//
	cs->aiFlags &= ~AIFL_LAND_ANIM_PLAYED;
	// play the buildup sound
	// TODO
	//
	cs->aifunc = AIFunc_StimSoldierAttack1;
	return "AIFunc_StimSoldierAttack1";
}
Beispiel #6
0
// Nico, check if ew can follow a given client
qboolean G_AllowFollow(gentity_t *ent, gentity_t *other) {

	// Nico, only referee can spec in cup mode
	if (g_cupMode.integer != 0 && ent->client->sess.referee != RL_REFEREE) {
		return qfalse;
	}

	return !other->client->sess.specLocked ||
	       COM_BitCheck(other->client->sess.specInvitedClients, ent - g_entities) ||
	       ent->client->sess.referee == RL_REFEREE;
}
Beispiel #7
0
/**
 * @brief G_GetSecondaryWeaponForClient
 * @param[in] client
 * @param primary - unused
 * @return
 *
 * @note Unused
 */
weapon_t G_GetSecondaryWeaponForClient(gclient_t *client, weapon_t primary)
{
	weapon_t secondary = WP_NONE;

	// early out if not on a team
	if (client->sess.sessionTeam != TEAM_ALLIES && client->sess.sessionTeam != TEAM_AXIS)
	{
		return WP_NONE;
	}

	// Record our secondary weapon (usually a pistol sidearm)
	// Colts
	if (COM_BitCheck(client->ps.weapons, WP_AKIMBO_SILENCEDCOLT))
	{
		secondary = WP_AKIMBO_SILENCEDCOLT;
	}
	else if (COM_BitCheck(client->ps.weapons, WP_AKIMBO_COLT))
	{
		secondary = WP_AKIMBO_COLT;
	}
	else if (COM_BitCheck(client->ps.weapons, WP_SILENCED_COLT))
	{
		secondary = WP_SILENCED_COLT;
	}
	else if (COM_BitCheck(client->ps.weapons, WP_COLT))
	{
		secondary = WP_COLT;
	}
	// Lugers
	else if (COM_BitCheck(client->ps.weapons, WP_AKIMBO_SILENCEDLUGER))
	{
		secondary = WP_AKIMBO_SILENCEDLUGER;
	}
	else if (COM_BitCheck(client->ps.weapons, WP_AKIMBO_LUGER))
	{
		secondary = WP_AKIMBO_LUGER;
	}
	else if (COM_BitCheck(client->ps.weapons, WP_SILENCER))
	{
		secondary = WP_SILENCER;
	}
	else if (COM_BitCheck(client->ps.weapons, WP_LUGER))
	{
		secondary = WP_LUGER;
	}

	return secondary;
}
Beispiel #8
0
/*
=================
TossClientItems

Toss the weapon and powerups for the killed player
=================
*/
void TossClientItems( gentity_t *self ) {
	gitem_t     *item;
	int weapon;
	gentity_t   *drop = 0;

	// drop the weapon if not a gauntlet or machinegun
	weapon = self->s.weapon;

	// make a special check to see if they are changing to a new
	// weapon that isn't the mg or gauntlet.  Without this, a client
	// can pick up a weapon, be killed, and not drop the weapon because
	// their weapon change hasn't completed yet and they are still holding the MG.

	// (SA) always drop what you were switching to
	if ( 1 ) {
		if ( self->client->ps.weaponstate == WEAPON_DROPPING ) {
			weapon = self->client->pers.cmd.weapon;
		}
		if ( !( COM_BitCheck( self->client->ps.weapons, weapon ) ) ) {
			weapon = WP_NONE;
		}
	}

	// JPW NERVE don't drop these weapon types
	if ( ( weapon == WP_FLAMETHROWER ) || ( weapon == WP_GARAND ) || ( weapon == WP_MAUSER ) || ( weapon == WP_VENOM ) ) {
		weapon = WP_NONE;
	}
	// jpw

	if ( weapon > WP_NONE && weapon < WP_MONSTER_ATTACK1 && self->client->ps.ammo[ BG_FindAmmoForWeapon( weapon_t (weapon) )] ) {
		// find the item type for this weapon
		item = BG_FindItemForWeapon( weapon_t (weapon) );
		// spawn the item

		// Rafael
		if ( !( self->client->ps.persistant[PERS_HWEAPON_USE] ) ) {
			drop = Drop_Item( self, item, 0, qfalse );
			// JPW NERVE -- fix ammo counts
			drop->count = self->client->ps.ammoclip[BG_FindClipForWeapon( weapon_t (weapon) )];
			drop->item->quantity = self->client->ps.ammoclip[BG_FindClipForWeapon( weapon_t (weapon) )];
			// jpw
		}
	}
}
Beispiel #9
0
qboolean G_CanPickupWeapon( weapon_t weapon, gentity_t* ent ) {

	// tjw: don't let players pick up a weapon they are
	//      already holding.
	if(COM_BitCheck(ent->client->ps.weapons, weapon))
		return qfalse;

	if( ent->client->sess.sessionTeam == TEAM_AXIS ) {
		if( weapon == WP_THOMPSON ) {
			weapon = WP_MP40;
		} else if( weapon == WP_CARBINE ) {
			weapon = WP_KAR98;
		} else if( weapon == WP_GARAND ) {
			weapon = WP_K43;
		}

	} else if( ent->client->sess.sessionTeam == TEAM_ALLIES ) {
		if( weapon == WP_MP40 ) {
			weapon = WP_THOMPSON;
		} else if( weapon == WP_KAR98 ) {
			weapon = WP_CARBINE;
		} else if( weapon == WP_K43 ) {
			weapon = WP_GARAND;
		}
	}

	if( g_unlockDropWeapons.integer ) {
		return qtrue;
	}

	// tjw: check heavy weapon restrictions
	if(G_IsWeaponDisabled(ent,
		weapon,
		ent->client->sess.sessionTeam,
		qtrue)) {

		return qfalse;
	}

	return BG_WeaponIsPrimaryForClassAndTeam( ent->client->sess.playerType, ent->client->sess.sessionTeam, weapon );
}
Beispiel #10
0
/*
==============
Touch_Item
	if other->client->pers.autoActivate == PICKUP_ACTIVATE	(0), he will pick up items only when using +activate
	if other->client->pers.autoActivate == PICKUP_TOUCH		(1), he will pickup items when touched
	if other->client->pers.autoActivate == PICKUP_FORCE		(2), he will pickup the next item when touched (and reset to PICKUP_ACTIVATE when done)
==============
*/
void Touch_Item_Auto( gentity_t *ent, gentity_t *other, trace_t *trace )
{
 	if( other->client->pers.autoActivate == PICKUP_ACTIVATE )
		return;

	if( !ent->active && ent->item->giType == IT_WEAPON ) {
		if( ent->item->giTag != WP_AMMO  && ent->item->giTag != WP_BINOCULARS ) {
			if ( G_GetPrimaryWeaponForClient(other->client) ||
					 (!BG_WeaponIsPrimaryForClassAndTeam( other->client->sess.playerType, TEAM_ALLIES, ent->item->giTag ) &&
						!BG_WeaponIsPrimaryForClassAndTeam( other->client->sess.playerType, TEAM_AXIS, ent->item->giTag )
					 ) ) {
			if( !COM_BitCheck( other->client->ps.weapons, ent->item->giTag ) ) {
				return;	// force activate only
				}
			}
		}
	}

	ent->active = qtrue;
	Touch_Item( ent, other, trace );

	if( other->client->pers.autoActivate == PICKUP_FORCE )		// autoactivate probably forced by the "Cmd_Activate_f()" function
		other->client->pers.autoActivate = PICKUP_ACTIVATE;		// so reset it.
}
Beispiel #11
0
int Pickup_Weapon( gentity_t *ent, gentity_t *other ) {
	int			quantity;
	qboolean	alreadyHave = qfalse;

	// JPW NERVE -- magic ammo for any two-handed weapon
	if( ent->item->giTag == WP_AMMO ) {
		AddMagicAmmo( other, ent->count );

		// if LT isn't giving ammo to self or another LT or the enemy, give him some props
		if( other->client->ps.stats[STAT_PLAYER_CLASS] != PC_FIELDOPS ) {
			if ( ent->parent && ent->parent->client && other->client->sess.sessionTeam == ent->parent->client->sess.sessionTeam ) {
				if (!(ent->parent->client->PCSpecialPickedUpCount % LT_SPECIAL_PICKUP_MOD)) {
					AddScore(ent->parent, WOLF_AMMO_UP);
					if(ent->parent && ent->parent->client) {
						G_LogPrintf("Ammo_Pack: %d %d\n", ent->parent - g_entities, other - g_entities);	// OSP
					}
				}
				ent->parent->client->PCSpecialPickedUpCount++;
				G_AddSkillPoints( ent->parent, SK_SIGNALS, 1.f );
				G_DebugAddSkillPoints( ent->parent, SK_SIGNALS, 1.f, "ammo pack picked up" ); 

				// extracted code originally here into AddMagicAmmo -xkan, 9/18/2002
				// add 1 clip of magic ammo for any two-handed weapon
			}
			return RESPAWN_SP;
		}
	}

	quantity = ent->count;

	// check if player already had the weapon
	alreadyHave = COM_BitCheck( other->client->ps.weapons, ent->item->giTag );

	// JPW NERVE  prevents drop/pickup weapon "quick reload" exploit
	if( alreadyHave ) {
		Add_Ammo( other, ent->item->giTag, quantity, qfalse );

		// Gordon: secondary weapon ammo
		if( ent->delay ) {
			Add_Ammo( other, weapAlts[ ent->item->giTag ], ent->delay, qfalse );
		}
	} else {
		if( level.time - other->client->dropWeaponTime < 1000 ) {
			return 0;
		}

		if( other->client->ps.weapon == WP_MORTAR_SET || other->client->ps.weapon == WP_MOBILE_MG42_SET ) {
			return 0;
		}

		// See if we can pick it up
		if( G_CanPickupWeapon( ent->item->giTag, other ) ) {
			weapon_t primaryWeapon = G_GetPrimaryWeaponForClient( other->client );

			if( primaryWeapon || 
				other->client->sess.playerType == PC_SOLDIER && other->client->sess.skill[SK_HEAVY_WEAPONS] >= 4 ) {

				if( primaryWeapon ) {
					// drop our primary weapon
					G_DropWeapon( other, primaryWeapon );
				}

				// now pickup the other one
				other->client->dropWeaponTime = level.time;

				// add the weapon
				COM_BitSet( other->client->ps.weapons, ent->item->giTag );

				// DHM - Fixup mauser/sniper issues
				if( ent->item->giTag == WP_FG42 ) {
					COM_BitSet( other->client->ps.weapons, WP_FG42SCOPE);
				} else if(ent->item->giTag == WP_GARAND) {
					COM_BitSet( other->client->ps.weapons, WP_GARAND_SCOPE);
				} else if( ent->item->giTag == WP_K43 ) {
					COM_BitSet( other->client->ps.weapons, WP_K43_SCOPE );
				} else if( ent->item->giTag == WP_MORTAR ) {
					COM_BitSet( other->client->ps.weapons, WP_MORTAR_SET );
				} else if( ent->item->giTag == WP_MOBILE_MG42 ) {
					COM_BitSet( other->client->ps.weapons, WP_MOBILE_MG42_SET );
				} else if( ent->item->giTag == WP_CARBINE ) {
					COM_BitSet( other->client->ps.weapons, WP_M7 );
				} else if( ent->item->giTag == WP_KAR98 ) {
					COM_BitSet( other->client->ps.weapons, WP_GPG40 );
				}

				other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = 0;
				other->client->ps.ammo[BG_FindAmmoForWeapon(ent->item->giTag)] = 0;

				if( ent->item->giTag == WP_MORTAR ) {
					other->client->ps.ammo[BG_FindClipForWeapon(ent->item->giTag)] = quantity;

					// Gordon: secondary weapon ammo
					if( ent->delay ) {
						Add_Ammo( other, weapAlts[ ent->item->giTag ], ent->delay, qfalse );
					}
				} else {
					other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = quantity;

					// Gordon: secondary weapon ammo
					if( ent->delay ) {
						other->client->ps.ammo[ weapAlts[ ent->item->giTag ] ] = ent->delay;
					}
				}
			}
		} else {
			return 0;
		}
	}

	return -1;
}
Beispiel #12
0
// ************** PLAYERS
//
// Show client info
void G_players_cmd(gentity_t *ent, unsigned int dwCommand, qboolean fValue)
{
	int i, idnum, max_rate, cnt=0, tteam;
	int user_rate, user_snaps, bots = 0;
	gclient_t *cl;
	gentity_t *cl_ent;
	char n2[MAX_NETNAME], ready[16], ref[16], ign[16], rate[256];
	char *s, *tc, *coach, userinfo[MAX_INFO_STRING];


	if(g_gamestate.integer == GS_PLAYING) {
		if(ent) {
			CP("print \"\n^3 ID^1 : ^3Player                    Nudge  Rate  MaxPkts  Snaps\n\"");
			CP(  "print \"^1-----------------------------------------------------------^7\n\"");
		} else {
			G_Printf(" ID : Player                    Nudge  Rate  MaxPkts  Snaps\n");
			G_Printf("-----------------------------------------------------------\n");
		}
	} else {
		if(ent) {
			CP("print \"\n^3Status^1   : ^3ID^1 : ^3Player                    Nudge  Rate  MaxPkts  Snaps\n\"");
			CP(  "print \"^1---------------------------------------------------------------------^7\n\"");
		} else {
			G_Printf("Status   : ID : Player                    Nudge  Rate  MaxPkts  Snaps\n");
			G_Printf("---------------------------------------------------------------------\n");
		}
	}

	max_rate = trap_Cvar_VariableIntegerValue("sv_maxrate");

	for(i=0; i<level.numConnectedClients; i++) {
		idnum = level.sortedClients[i];//level.sortedNames[i];
		cl = &level.clients[idnum];
		cl_ent = g_entities + idnum;

		SanitizeString(cl->pers.netname, n2, qtrue);
		n2[26] = 0;
		ref[0] = 0;
		ign[0] = 0;
		ready[0] = 0;

		// Rate info
		if(cl_ent->r.svFlags & SVF_BOT) {
			strcpy(rate, va("%s%s%s%s", "[BOT]", " -----", "       --", "     --"));
			bots++;
		} else if(cl->pers.connected == CON_CONNECTING) {
			strcpy(rate, va("%s", "^3>>> CONNECTING <<<"));
		} else {
			trap_GetUserinfo( idnum, userinfo, sizeof(userinfo));
			s = Info_ValueForKey( userinfo, "rate" );
			user_rate = (max_rate > 0 && atoi(s) > max_rate) ? max_rate : atoi(s);
			s = Info_ValueForKey( userinfo, "snaps" );
			user_snaps = atoi(s);

			strcpy(rate, va("%5d%6d%9d%7d", cl->pers.clientTimeNudge, user_rate, cl->pers.clientMaxPackets, user_snaps));
		}

		if(g_gamestate.integer != GS_PLAYING) {
			// Dens: bots aren't counted, but specs are since changeset 1469
			if((g_entities[idnum].r.svFlags & SVF_BOT) || cl->pers.connected == CON_CONNECTING)
				strcpy(ready, ((ent) ? "^5--------^1 :" : "-------- :"));
			else if(cl->pers.ready)
				strcpy(ready, ((ent) ? "^3(READY)^1  :" : "(READY)  :"));
			else
				strcpy(ready, ((ent) ? "NOTREADY^1 :" : "NOTREADY :"));
		}

		if(cl->sess.referee) strcpy(ref, "REF ");

		// pheno: mark ignored clients
		if ( COM_BitCheck(ent->client->sess.ignoreClients, idnum) ) {
			strcpy(ign, (( ent ) ? "^8I" : "I"));
		}

		if(cl->sess.coach_team) {
			tteam = cl->sess.coach_team;
			coach = (ent) ? "^3C" : "C";
		} else {
			tteam = cl->sess.sessionTeam;
			coach = " ";
		}

		tc = (ent) ? "^7 " : " ";
		if(g_gametype.integer >= GT_WOLF) {
			if(tteam == TEAM_AXIS) tc = (ent) ? "^1X^7" : "X";
			if(tteam == TEAM_ALLIES) tc = (ent) ? "^4L^7" : "L";
		}

		if(ent) CP(va("print \"%s%s%2d%s^1:%s %-26s^7%s  ^3%s%s\n\"", ready, tc, idnum, coach, ((ref[0])?"^3":"^7"), n2, rate, ref, ign));
		else G_Printf("%s%s%2d%s: %-26s%s  %s%s\n", ready, tc, idnum, coach, n2, rate, ref, ign);

		cnt++;
	}

	if(ent) CP(va("print \"\n^3%2d^7 total players (^3%2d^7 humans, ^3%2d^7 bots)\n\n\"",
		cnt, cnt - bots, bots));
	else G_Printf("\n%2d total players (%2d humans, %2d bots\n\n", cnt, cnt - bots, bots);

	// Team speclock info
	if(g_gametype.integer >= GT_WOLF) {
		for(i=TEAM_AXIS; i<=TEAM_ALLIES; i++) {
			if(teamInfo[i].spec_lock) {
				if(ent) CP(va("print \"** %s team is speclocked.\n\"", aTeams[i]));
				else G_Printf("** %s team is speclocked.\n", aTeams[i]);
			}
		}
	}
}
// Parses fireteam servercommand
void CG_ParseFireteams()
{
	int        i, j;
	char       *s;
	const char *p;
	int        clnts[2];

	qboolean onFireteam2;
	qboolean isLeader2;

//	qboolean onFireteam =	CG_IsOnFireteam( cg.clientNum ) ? qtrue : qfalse;
//	qboolean isLeader =		CG_IsFireTeamLeader( cg.clientNum ) ? qtrue : qfalse;

	for (i = 0; i < MAX_CLIENTS; i++)
	{
		cgs.clientinfo[i].fireteamData = NULL;
	}

	for (i = 0; i < MAX_FIRETEAMS; i++)
	{
		char hexbuffer[11] = "0x00000000";
		p = CG_ConfigString(CS_FIRETEAMS + i);

/*		s = Info_ValueForKey(p, "n");
        if(!s || !*s) {
            cg.fireTeams[i].inuse = qfalse;
            continue;
        } else {
            cg.fireTeams[i].inuse = qtrue;
        }*/

//		Q_strncpyz(cg.fireTeams[i].name, s, 32);
//		CG_Printf("Fireteam: %s\n", cg.fireTeams[i].name);

		j = atoi(Info_ValueForKey(p, "id"));
		if (j == -1)
		{
			cg.fireTeams[i].inuse = qfalse;
			continue;
		}
		else
		{
			cg.fireTeams[i].inuse = qtrue;
			cg.fireTeams[i].ident = j;
		}

		s                      = Info_ValueForKey(p, "l");
		cg.fireTeams[i].leader = atoi(s);

		s = Info_ValueForKey(p, "c");
		Q_strncpyz(hexbuffer + 2, s, 9);
		sscanf(hexbuffer, "%x", &clnts[1]);
		Q_strncpyz(hexbuffer + 2, s + 8, 9);
		sscanf(hexbuffer, "%x", &clnts[0]);

		for (j = 0; j < MAX_CLIENTS; j++)
		{
			if (COM_BitCheck(clnts, j))
			{
				cg.fireTeams[i].joinOrder[j]   = qtrue;
				cgs.clientinfo[j].fireteamData = &cg.fireTeams[i];
//				CG_Printf("%s\n", cgs.clientinfo[j].name);
			}
			else
			{
				cg.fireTeams[i].joinOrder[j] = qfalse;
			}
		}
	}

	CG_SortClientFireteam();

	onFireteam2 = CG_IsOnFireteam(cg.clientNum) ? qtrue : qfalse;
	isLeader2   = CG_IsFireTeamLeader(cg.clientNum) ? qtrue : qfalse;
}
Beispiel #14
0
/**
 * @brief G_ResetXP
 * @param[in,out] ent
 */
void G_ResetXP(gentity_t *ent)
{
	int i = 0;
	int ammo[MAX_WEAPONS], ammoclip[MAX_WEAPONS];
	int oldWeapon; //, newWeapon;

	if (!ent || !ent->client)
	{
		return;
	}

#ifdef FEATURE_RATING
	if (!g_skillRating.integer)
#endif
	{
		ent->client->sess.rank = 0;
	}

	for (i = 0; i < SK_NUM_SKILLS; i++)
	{
		ent->client->sess.skillpoints[i] = 0.0f;
		ent->client->sess.skill[i]       = 0;
	}

	G_CalcRank(ent->client);
	ent->client->ps.stats[STAT_XP]         = 0;
	ent->client->ps.persistant[PERS_SCORE] = 0;

	// zero out all weapons and grab the default weapons for a player of this XP level.
	// backup..
	Com_Memcpy(ammo, ent->client->ps.ammo, sizeof(ammo));
	Com_Memcpy(ammoclip, ent->client->ps.ammoclip, sizeof(ammoclip));
	oldWeapon = ent->client->ps.weapon;
	// Check weapon validity, maybe dump some weapons for this (now) unskilled player..
	// It also sets the (possibly new) amounts of ammo for weapons.
	SetWolfSpawnWeapons(ent->client);
	// restore..
	//newWeapon = ent->client->ps.weapon;

	for (i = WP_NONE; i < WP_NUM_WEAPONS; ++i)    //i<MAX_WEAPONS
	{   // only restore ammo for valid weapons..
		// ..they might have lost some weapons because of skill changes.
		// Also restore to the old amount of ammo, because..
		// ..SetWolfSpawnWeapons sets amount of ammo for a fresh spawning player,
		// which is usually more than the player currently has left.
		if (COM_BitCheck(ent->client->ps.weapons, i))
		{
			if (ammo[i] < ent->client->ps.ammo[i])
			{
				ent->client->ps.ammo[i] = ammo[i];
			}
			if (ammoclip[i] < ent->client->ps.ammoclip[i])
			{
				ent->client->ps.ammoclip[i] = ammoclip[i];
			}
		}
		else
		{
			ent->client->ps.ammo[i]     = 0;
			ent->client->ps.ammoclip[i] = 0;
		}
	}
	// check if the old weapon is still valid.
	// If so, restore to the last used weapon..
	if (COM_BitCheck(ent->client->ps.weapons, oldWeapon))
	{
		ent->client->ps.weapon = oldWeapon;
	}
	ClientUserinfoChanged(ent - g_entities);
}
Beispiel #15
0
/*
==============
ClientThink

This will be called once for each client frame, which will
usually be a couple times for each server frame on fast clients.

If "g_synchronousClients 1" is set, this will be called exactly
once for each server frame, which makes for smooth demo recording.
==============
*/
void ClientThink_real( gentity_t *ent ) {
	gclient_t   *client;
	pmove_t pm;
//	vec3_t		oldOrigin;
	int oldEventSequence;
	int msec;
	usercmd_t   *ucmd;
	int monsterslick = 0;
// JPW NERVE
	int i;
	vec3_t muzzlebounce;
	gitem_t *item;
	gentity_t *ent2;
	vec3_t velocity, org, offset;
	vec3_t angles,mins,maxs;
	int weapon;
	trace_t tr;
// jpw

	// Rafael wolfkick
	//int			validkick;
	//static int	wolfkicktimer = 0;

	client = ent->client;

	// don't think if the client is not yet connected (and thus not yet spawned in)
	if ( client->pers.connected != CON_CONNECTED ) {
		return;
	}

	if ( client->cameraPortal ) {
		G_SetOrigin( client->cameraPortal, client->ps.origin );
		trap_LinkEntity( client->cameraPortal );
		VectorCopy( client->cameraOrigin, client->cameraPortal->s.origin2 );
	}

	// mark the time, so the connection sprite can be removed
	ucmd = &ent->client->pers.cmd;

	ent->client->ps.identifyClient = ucmd->identClient;     // NERVE - SMF

// JPW NERVE -- update counter for capture & hold display
	if ( g_gametype.integer == GT_WOLF_CPH ) {
		client->ps.stats[STAT_CAPTUREHOLD_RED] = level.capturetimes[TEAM_RED];
		client->ps.stats[STAT_CAPTUREHOLD_BLUE] = level.capturetimes[TEAM_BLUE];
	}
// jpw

	// sanity check the command time to prevent speedup cheating
	if ( ucmd->serverTime > level.time + 200 ) {
		ucmd->serverTime = level.time + 200;
//		G_Printf("serverTime <<<<<\n" );
	}
	if ( ucmd->serverTime < level.time - 1000 ) {
		ucmd->serverTime = level.time - 1000;
//		G_Printf("serverTime >>>>>\n" );
	}

	msec = ucmd->serverTime - client->ps.commandTime;
	// following others may result in bad times, but we still want
	// to check for follow toggles
	if ( msec < 1 && client->sess.spectatorState != SPECTATOR_FOLLOW ) {
		return;
		/*
		// Ridah, fixes savegame timing issue
		if (msec < -100) {
			client->ps.commandTime = ucmd->serverTime - 100;
			msec = 100;
		} else {
			return;
		}
		*/
		// done.
	}
	if ( msec > 200 ) {
		msec = 200;
	}

	if ( pmove_msec.integer < 8 ) {
		trap_Cvar_Set( "pmove_msec", "8" );
	} else if ( pmove_msec.integer > 33 )     {
		trap_Cvar_Set( "pmove_msec", "33" );
	}

	if ( pmove_fixed.integer || client->pers.pmoveFixed ) {
		ucmd->serverTime = ( ( ucmd->serverTime + pmove_msec.integer - 1 ) / pmove_msec.integer ) * pmove_msec.integer;
		//if (ucmd->serverTime - client->ps.commandTime <= 0)
		//	return;
	}

	//
	// check for exiting intermission
	//
	if ( level.intermissiontime ) {
		ClientIntermissionThink( client );
		return;
	}

	// spectators don't do much
	// DHM - Nerve :: In limbo use SpectatorThink
	if ( client->sess.sessionTeam == TEAM_SPECTATOR || client->ps.pm_flags & PMF_LIMBO ) {
		if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
			return;
		}
		SpectatorThink( ent, ucmd );
		return;
	}

	// JPW NERVE do some time-based muzzle flip -- this never gets touched in single player (see g_weapon.c)
	// #define RIFLE_SHAKE_TIME 150 // JPW NERVE this one goes with the commented out old damped "realistic" behavior below
	#define RIFLE_SHAKE_TIME 300 // per Id request, longer recoil time
	if ( client->sniperRifleFiredTime ) {
		if ( level.time - client->sniperRifleFiredTime > RIFLE_SHAKE_TIME ) {
			client->sniperRifleFiredTime = 0;
		} else {
			VectorCopy( client->ps.viewangles,muzzlebounce );

			// JPW per Id request, longer recoil time
			muzzlebounce[PITCH] -= 2 * cos( 2.5 * ( level.time - client->sniperRifleFiredTime ) / RIFLE_SHAKE_TIME );
			muzzlebounce[YAW] += 0.5*client->sniperRifleMuzzleYaw*cos( 1.0 - ( level.time - client->sniperRifleFiredTime ) * 3 / RIFLE_SHAKE_TIME );
			muzzlebounce[PITCH] -= 0.25 * random() * ( 1.0f - ( level.time - client->sniperRifleFiredTime ) / RIFLE_SHAKE_TIME );
			muzzlebounce[YAW] += 0.5 * crandom() * ( 1.0f - ( level.time - client->sniperRifleFiredTime ) / RIFLE_SHAKE_TIME );
			SetClientViewAngle( ent,muzzlebounce );
		}
	}
	if ( client->ps.stats[STAT_PLAYER_CLASS] == PC_MEDIC ) {
		if ( level.time > client->ps.powerups[PW_REGEN] + 5000 ) {
			client->ps.powerups[PW_REGEN] = level.time;
		}
	}
	// also update weapon recharge time

	// JPW drop button drops secondary weapon so new one can be picked up
	// TTimo explicit braces to avoid ambiguous 'else'
	if ( g_gametype.integer != GT_SINGLE_PLAYER ) {
		if ( ucmd->wbuttons & WBUTTON_DROP ) {
			if ( !client->dropWeaponTime ) {
				client->dropWeaponTime = 1; // just latch it for now
				if ( ( client->ps.stats[STAT_PLAYER_CLASS] == PC_SOLDIER ) || ( client->ps.stats[STAT_PLAYER_CLASS] == PC_LT ) ) {
					for ( i = 0; i < MAX_WEAPS_IN_BANK_MP; i++ ) {
						weapon = weapBanksMultiPlayer[3][i];
						if ( COM_BitCheck( client->ps.weapons,weapon ) ) {

							item = BG_FindItemForWeapon( weapon );
							VectorCopy( client->ps.viewangles, angles );

							// clamp pitch
							if ( angles[PITCH] < -30 ) {
								angles[PITCH] = -30;
							} else if ( angles[PITCH] > 30 ) {
								angles[PITCH] = 30;
							}

							AngleVectors( angles, velocity, NULL, NULL );
							VectorScale( velocity, 64, offset );
							offset[2] += client->ps.viewheight / 2;
							VectorScale( velocity, 75, velocity );
							velocity[2] += 50 + random() * 35;

							VectorAdd( client->ps.origin,offset,org );

							VectorSet( mins, -ITEM_RADIUS, -ITEM_RADIUS, 0 );
							VectorSet( maxs, ITEM_RADIUS, ITEM_RADIUS, 2 * ITEM_RADIUS );

							trap_Trace( &tr, client->ps.origin, mins, maxs, org, ent->s.number, MASK_SOLID );
							VectorCopy( tr.endpos, org );

							ent2 = LaunchItem( item, org, velocity, client->ps.clientNum );
							COM_BitClear( client->ps.weapons,weapon );

							if ( weapon == WP_MAUSER ) {
								COM_BitClear( client->ps.weapons,WP_SNIPERRIFLE );
							}

							// Clear out empty weapon, change to next best weapon
							G_AddEvent( ent, EV_NOAMMO, 0 );

							i = MAX_WEAPS_IN_BANK_MP;
							// show_bug.cgi?id=568
							if ( client->ps.weapon == weapon ) {
								client->ps.weapon = 0;
							}
							ent2->count = client->ps.ammoclip[BG_FindClipForWeapon( weapon )];
							ent2->item->quantity = client->ps.ammoclip[BG_FindClipForWeapon( weapon )];
							client->ps.ammoclip[BG_FindClipForWeapon( weapon )] = 0;
						}
					}
				}
			}
		} else {
			client->dropWeaponTime = 0;
		}
	}
// jpw

	// check for inactivity timer, but never drop the local client of a non-dedicated server
	if ( !ClientInactivityTimer( client ) ) {
		return;
	}

	if ( reloading || client->cameraPortal ) {
		ucmd->buttons = 0;
		ucmd->forwardmove = 0;
		ucmd->rightmove = 0;
		ucmd->upmove = 0;
		ucmd->wbuttons = 0;
		ucmd->wolfkick = 0;
		if ( client->cameraPortal ) {
			client->ps.pm_type = PM_FREEZE;
		}
	} else if ( client->noclip ) {
		client->ps.pm_type = PM_NOCLIP;
	} else if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
		client->ps.pm_type = PM_DEAD;
	} else {
		client->ps.pm_type = PM_NORMAL;
	}

	// set parachute anim condition flag
	BG_UpdateConditionValue( ent->s.number, ANIM_COND_PARACHUTE, ( ent->flags & FL_PARACHUTE ) != 0, qfalse );

	// all playing clients are assumed to be in combat mode
	if ( !client->ps.aiChar ) {
		client->ps.aiState = AISTATE_COMBAT;
	}

	client->ps.gravity = g_gravity.value;

	// set speed
	client->ps.speed = g_speed.value;

	if ( client->ps.powerups[PW_HASTE] ) {
		client->ps.speed *= 1.3;
	}

	// set up for pmove
	oldEventSequence = client->ps.eventSequence;

	client->currentAimSpreadScale = (float)client->ps.aimSpreadScale / 255.0;

	memset( &pm, 0, sizeof( pm ) );

	pm.ps = &client->ps;
	pm.pmext = &client->pmext;
	pm.cmd = *ucmd;
	pm.oldcmd = client->pers.oldcmd;
	if ( pm.ps->pm_type == PM_DEAD ) {
		pm.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
		// DHM-Nerve added:: EF_DEAD is checked for in Pmove functions, but wasn't being set
		//              until after Pmove
		pm.ps->eFlags |= EF_DEAD;
		// dhm-Nerve end
	} else {
		pm.tracemask = MASK_PLAYERSOLID;
	}
	// MrE: always use capsule for AI and player
	//pm.trace = trap_TraceCapsule;//trap_Trace;
	//DHM - Nerve :: We've gone back to using normal bbox traces
	pm.trace = trap_Trace;
	pm.pointcontents = trap_PointContents;
	pm.debugLevel = g_debugMove.integer;
	pm.noFootsteps = ( g_dmflags.integer & DF_NO_FOOTSTEPS ) > 0;

	pm.pmove_fixed = pmove_fixed.integer | client->pers.pmoveFixed;
	pm.pmove_msec = pmove_msec.integer;

	pm.noWeapClips = ( g_dmflags.integer & DF_NO_WEAPRELOAD ) > 0;
	if ( ent->aiCharacter && AICast_NoReload( ent->s.number ) ) {
		pm.noWeapClips = qtrue; // ensure AI characters don't use clips if they're not supposed to.

	}
	// Ridah
//	if (ent->r.svFlags & SVF_NOFOOTSTEPS)
//		pm.noFootsteps = qtrue;

	VectorCopy( client->ps.origin, client->oldOrigin );

	// NERVE - SMF
	pm.gametype = g_gametype.integer;
	pm.ltChargeTime = g_LTChargeTime.integer;
	pm.soldierChargeTime = g_soldierChargeTime.integer;
	pm.engineerChargeTime = g_engineerChargeTime.integer;
	pm.medicChargeTime = g_medicChargeTime.integer;
	// -NERVE - SMF

	monsterslick = Pmove( &pm );

	if ( monsterslick && !( ent->flags & FL_NO_MONSTERSLICK ) ) {
		//vec3_t	dir;
		//vec3_t	kvel;
		//vec3_t	forward;
		// TTimo gcc: might be used unitialized in this function
		float angle = 0.0f;
		qboolean bogus = qfalse;

		// NE
		if ( ( monsterslick & SURF_MONSLICK_N ) && ( monsterslick & SURF_MONSLICK_E ) ) {
			angle = 45;
		}
		// NW
		else if ( ( monsterslick & SURF_MONSLICK_N ) && ( monsterslick & SURF_MONSLICK_W ) ) {
			angle = 135;
		}
		// N
		else if ( monsterslick & SURF_MONSLICK_N ) {
			angle = 90;
		}
		// SE
		else if ( ( monsterslick & SURF_MONSLICK_S ) && ( monsterslick & SURF_MONSLICK_E ) ) {
			angle = 315;
		}
		// SW
		else if ( ( monsterslick & SURF_MONSLICK_S ) && ( monsterslick & SURF_MONSLICK_W ) ) {
			angle = 225;
		}
		// S
		else if ( monsterslick & SURF_MONSLICK_S ) {
			angle = 270;
		}
		// E
		else if ( monsterslick & SURF_MONSLICK_E ) {
			angle = 0;
		}
		// W
		else if ( monsterslick & SURF_MONSLICK_W ) {
			angle = 180;
		} else
		{
			bogus = qtrue;
		}
	}

	// server cursor hints
	if ( ent->lastHintCheckTime < level.time ) {
		G_CheckForCursorHints( ent );

		ent->lastHintCheckTime = level.time + FRAMETIME;
	}

	// DHM - Nerve :: Set animMovetype to 1 if ducking
	if ( ent->client->ps.pm_flags & PMF_DUCKED ) {
		ent->s.animMovetype = 1;
	} else {
		ent->s.animMovetype = 0;
	}

	// save results of pmove
	if ( ent->client->ps.eventSequence != oldEventSequence ) {
		ent->eventTime = level.time;
		ent->r.eventTime = level.time;
	}

	// Ridah, fixes jittery zombie movement
	if ( g_smoothClients.integer ) {
		BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qtrue );
	} else {
		BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue );
	}

	if ( !( ent->client->ps.eFlags & EF_FIRING ) ) {
		client->fireHeld = qfalse;      // for grapple
	}

//
//	// use the precise origin for linking
//	VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
//
//	// use the snapped origin for linking so it matches client predicted versions
	VectorCopy( ent->s.pos.trBase, ent->r.currentOrigin );

	VectorCopy( pm.mins, ent->r.mins );
	VectorCopy( pm.maxs, ent->r.maxs );

	ent->waterlevel = pm.waterlevel;
	ent->watertype = pm.watertype;

	// execute client events
	ClientEvents( ent, oldEventSequence );

	// link entity now, after any personal teleporters have been used
	trap_LinkEntity( ent );
	if ( !ent->client->noclip ) {
		G_TouchTriggers( ent );
	}

	// NOTE: now copy the exact origin over otherwise clients can be snapped into solid
	VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );

	// store the client's current position for antilag traces
	G_StoreClientPosition( ent );

	// touch other objects
	ClientImpacts( ent, &pm );

	// save results of triggers and client events
	if ( ent->client->ps.eventSequence != oldEventSequence ) {
		ent->eventTime = level.time;
	}

	// swap and latch button actions
	client->oldbuttons = client->buttons;
	client->buttons = ucmd->buttons;
	client->latched_buttons = client->buttons & ~client->oldbuttons;
//	client->latched_buttons |= client->buttons & ~client->oldbuttons;	// FIXME:? (SA) MP method (causes problems for us.  activate 'sticks')

	//----(SA)	added
	client->oldwbuttons = client->wbuttons;
	client->wbuttons = ucmd->wbuttons;
	client->latched_wbuttons = client->wbuttons & ~client->oldwbuttons;
//	client->latched_wbuttons |= client->wbuttons & ~client->oldwbuttons;	// FIXME:? (SA) MP method

	// Rafael - Activate
	// Ridah, made it a latched event (occurs on keydown only)
	if ( client->latched_buttons & BUTTON_ACTIVATE ) {
		Cmd_Activate_f( ent );
	}

	if ( ent->flags & FL_NOFATIGUE ) {
		ent->client->ps.sprintTime = 20000;
	}


	// check for respawning
	if ( client->ps.stats[STAT_HEALTH] <= 0 ) {

		// DHM - Nerve
		if ( g_gametype.integer >= GT_WOLF ) {
			WolfFindMedic( ent );
		}
		// dhm - end

		// wait for the attack button to be pressed
		if ( level.time > client->respawnTime ) {
			// forcerespawn is to prevent users from waiting out powerups
			if ( ( g_gametype.integer != GT_SINGLE_PLAYER ) &&
				 ( g_forcerespawn.integer > 0 ) &&
				 ( ( level.time - client->respawnTime ) > g_forcerespawn.integer * 1000 )  &&
				 ( !( ent->client->ps.pm_flags & PMF_LIMBO ) ) ) { // JPW NERVE
				// JPW NERVE
				if ( g_gametype.integer >= GT_WOLF ) {
					limbo( ent, qtrue );
				} else {
					respawn( ent );
				}
				// jpw
				return;
			}

			// DHM - Nerve :: Single player game respawns immediately as before,
			//				  but in multiplayer, require button press before respawn
			if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
				respawn( ent );
			}
			// NERVE - SMF - we want to only respawn on jump button now
			else if ( ( ucmd->upmove > 0 ) &&
					  ( !( ent->client->ps.pm_flags & PMF_LIMBO ) ) ) { // JPW NERVE
				// JPW NERVE
				if ( g_gametype.integer >= GT_WOLF ) {
					limbo( ent, qtrue );
				} else {
					respawn( ent );
				}
				// jpw
			}
			// dhm - Nerve :: end
			// NERVE - SMF - we want to immediately go to limbo mode if gibbed
			else if ( client->ps.stats[STAT_HEALTH] <= GIB_HEALTH && !( ent->client->ps.pm_flags & PMF_LIMBO ) ) {
				if ( g_gametype.integer >= GT_WOLF ) {
					limbo( ent, qfalse );
				} else {
					respawn( ent );
				}
			}
			// -NERVE - SMF
		}
		return;
	}

	// perform once-a-second actions
	ClientTimerActions( ent, msec );
}
Beispiel #16
0
void CG_DrawMortarMarker(int px, int py, int pw, int ph, qboolean draw, mapScissor_t *scissor, int expand)
{
	if (cg.lastFiredWeapon == WP_MORTAR_SET && cg.mortarImpactTime >= 0)
	{
		if (cg.snap->ps.weapon != WP_MORTAR_SET)
		{
			cg.mortarImpactTime = 0;
		}
		else
		{
			vec4_t colour = { 1.f, 1.f, 1.f, 1.f };
			vec3_t point;

			if (scissor)
			{
				point[0] = ((cg.mortarImpactPos[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw * scissor->zoomFactor;
				point[1] = ((cg.mortarImpactPos[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph * scissor->zoomFactor;
			}
			else
			{
				point[0] = px + (((cg.mortarImpactPos[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw);
				point[1] = py + (((cg.mortarImpactPos[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph);
			}

			// don't return if the marker is culled, just don't draw it.
			if (!(scissor && CG_ScissorPointIsCulled(point, scissor)))
			{
				if (scissor)
				{
					point[0] += px - scissor->tl[0];
					point[1] += py - scissor->tl[1];
				}

				if (cg.mortarImpactOutOfMap)
				{
					if (!scissor)
					{
						// near the edge of the map, fit into it
						if (point[0] + 8.f > (px + pw))
						{
							point[0] -= 8.f;
						}
						else if (point[0] - 8.f < px)
						{
							point[0] += 8.f;
						}

						if (point[1] + 8.f > (py + ph))
						{
							point[1] -= 8.f;
						}
						else if (point[1] - 8.f < py)
						{
							point[1] += 8.f;
						}
					}
					colour[3] = .5f;
				}

				trap_R_SetColor(colour);
				CG_DrawRotatedPic(point[0] - 8.f, point[1] - 8.f, 16, 16, cgs.media.ccMortarHit, .5f - (cg.mortarFireAngles[YAW] /*- 180.f */ + 45.f) / 360.f);
				trap_R_SetColor(NULL);
			}
		}
	}

	if (COM_BitCheck(cg.snap->ps.weapons, WP_MORTAR_SET))
	{
		vec4_t colour = { 1.f, 1.f, 1.f, 1.f };
		vec3_t point;
		int    i, fadeTime;

		for (i = 0; i < MAX_CLIENTS; i++)
		{
			fadeTime = cg.time - (cg.artilleryRequestTime[i] + 25000);

			if (fadeTime < 5000)
			{
				if (fadeTime > 0)
				{
					colour[3] = 1.f - (fadeTime / 5000.f);
				}

				if (scissor)
				{
					point[0] = ((cg.artilleryRequestPos[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw * scissor->zoomFactor;
					point[1] = ((cg.artilleryRequestPos[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph * scissor->zoomFactor;
				}
				else
				{
					point[0] = px + (((cg.artilleryRequestPos[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw);
					point[1] = py + (((cg.artilleryRequestPos[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph);
				}

				// don't return if the marker is culled, just skip
				// it (so we draw the rest, if any)
				if (scissor && CG_ScissorPointIsCulled(point, scissor))
				{
					continue;
				}

				if (scissor)
				{
					point[0] += px - scissor->tl[0];
					point[1] += py - scissor->tl[1];
				}

				trap_R_SetColor(colour);
				CG_DrawPic(point[0] - 8.f, point[1] - 8.f, 16, 16, cgs.media.ccMortarTarget);
				trap_R_SetColor(NULL);
			}
		}
	}
}
Beispiel #17
0
/**
 * @brief Pick a weapon up.
 * @param[in,out] ent
 * @param[in,out] other
 * @return
 */
int Pickup_Weapon(gentity_t *ent, gentity_t *other)
{
	int      quantity;
	qboolean alreadyHave = qfalse;

	// magic ammo for any two-handed weapon
	if (ent->item->giWeapon == WP_AMMO)
	{
		AddMagicAmmo(other, ent->count);
		if (ent->parent && ent->parent->client)
		{
			other->client->pers.lastammo_client = ent->parent->s.clientNum;
		}

		// if field ops isn't giving ammo to self or the enemy, give him some props
		if (ent->parent && (ent->parent->client != other->client))
		{
			if (ent->parent && ent->parent->client && other->client->sess.sessionTeam == ent->parent->client->sess.sessionTeam)
			{
				G_AddSkillPoints(ent->parent, SK_SIGNALS, 1.f);
				G_DebugAddSkillPoints(ent->parent, SK_SIGNALS, 1.f, "ammo pack picked up");

#ifdef FEATURE_OMNIBOT
				//omni-bot event
				if (ent->parent)
				{
					Bot_Event_RecievedAmmo(other - g_entities, ent->parent);
				}
#endif
				// extracted code originally here into AddMagicAmmo
				// add 1 clip of magic ammo for any two-handed weapon
			}
			return RESPAWN_NEVER;
		}
	}

	quantity = ent->count;

	// check if player already had the weapon
	alreadyHave = COM_BitCheck(other->client->ps.weapons, ent->item->giWeapon);

	// prevents drop/pickup weapon "quick reload" exploit
	if (alreadyHave)
	{
		Add_Ammo(other, ent->item->giWeapon, quantity, qfalse);

		// secondary weapon ammo
		if (ent->delay != 0.f)
		{
			Add_Ammo(other, GetWeaponTableData(ent->item->giWeapon)->weapAlts, ent->delay, qfalse);
		}
	}
	else
	{
		if (level.time - other->client->dropWeaponTime < 1000)
		{
			return 0;
		}

		// don't pick up when MG or mortar is set
		if (GetWeaponTableData(other->client->ps.weapon)->isSetWeapon)
		{
			return 0;
		}

		// see if we can pick it up
		if (G_CanPickupWeapon(ent->item->giWeapon, other))
		{
			weapon_t primaryWeapon;

			if (other->client->sess.playerType == PC_SOLDIER && other->client->sess.skill[SK_HEAVY_WEAPONS] >= 4)
			{
				primaryWeapon = G_GetPrimaryWeaponForClientSoldier(ent->item->giWeapon, other->client);
			}
			else
			{
				primaryWeapon = G_GetPrimaryWeaponForClient(other->client);
			}

			// added parens around ambiguous &&
			if (primaryWeapon)
			{
				// drop our primary weapon
				G_DropWeapon(other, primaryWeapon);

				// now pickup the other one
				other->client->dropWeaponTime = level.time;

				// add the weapon
				COM_BitSet(other->client->ps.weapons, ent->item->giWeapon);

				// fixup mauser/sniper issues
				if (GetWeaponTableData(ent->item->giWeapon)->weapAlts != WP_NONE)
				{
					weapon_t weapAlts = GetWeaponTableData(ent->item->giWeapon)->weapAlts;

					if (GetWeaponTableData(weapAlts)->isRiflenade || GetWeaponTableData(weapAlts)->isScoped || GetWeaponTableData(weapAlts)->isSetWeapon)
					{
						COM_BitSet(other->client->ps.weapons, weapAlts);
					}
				}

				other->client->ps.ammoclip[GetWeaponTableData(ent->item->giWeapon)->clipIndex] = 0;
				other->client->ps.ammo[GetWeaponTableData(ent->item->giWeapon)->ammoIndex]     = 0;

				if (GetWeaponTableData(ent->item->giWeapon)->isMortar)
				{
					other->client->ps.ammo[GetWeaponTableData(ent->item->giWeapon)->clipIndex] = quantity;

					// secondary weapon ammo
					if (ent->delay != 0.f)
					{
						Add_Ammo(other, GetWeaponTableData(ent->item->giWeapon)->weapAlts, ent->delay, qfalse);
					}
				}
				else
				{
					other->client->ps.ammoclip[GetWeaponTableData(ent->item->giWeapon)->clipIndex] = quantity;

					// secondary weapon ammo
					if (ent->delay != 0.f)
					{
						other->client->ps.ammo[GetWeaponTableData(ent->item->giWeapon)->weapAlts] = ent->delay;
					}
				}
			}
		}
		else
		{
			return 0;
		}
	}

#ifdef FEATURE_OMNIBOT
	Bot_Event_AddWeapon(other->client->ps.clientNum, Bot_WeaponGameToBot(ent->item->giWeapon));
#endif

	return RESPAWN_NEVER;
}
Beispiel #18
0
static int PM_Weapon_CheckForRechamber(int time) {
	return 0;
	#define int_ptr_val(x) (*(int*)((int)x))
	pmove_t *xm = *(pmove_t**)(int)pm;
	
	#define ps_off(type, off) (*(type*)((int)xm->ps + off))
	
	int *weaponstate = (int*)((int)xm->ps + 180);
	int *weapons = *(int**)((int)xm->ps + 796);
	int weapon = *(int*)((int)xm->ps + 176);
	int *weaponTime = (int*)((int)xm->ps + 44);
	int *weaponDelay = (int*)((int)xm->ps + 48);
	
	int v2 = *(int*)((int)pml + 132);
	
	if(!int_ptr_val(v2 + 712))
		return 0;
	
	if(!COM_BitCheck(weapons, weapon))
		return 0;

	if(*weaponstate == WEAPON_RECHAMBERING) {
		if(time) {
			COM_BitClear(weapons, weapon);
			PM_AddEvent(EV_EJECT_BRASS);
			if(*weaponTime)
				return 1;
		}
	}
	
	if(!*weaponTime || ((*weaponstate - WEAPON_FIRING) > WEAPON_RAISING && *weaponstate != WEAPON_MELEE_WINDUP && *weaponstate != WEAPON_MELEE_RELAX && !*weaponDelay)) {
		if(*weaponstate == WEAPON_RECHAMBERING) {
			if(xm->cmd.wbuttons) {
				int *v9 = (int*)((int)xm->ps + 980);
				if(*v9 & 0xFFFFFDFF) {
					if(xm->ps->pm_type <= 5) {
						int v6 = *v9 & 0x200;
						BYTE1(v6) ^= 2;
						*v9 = v6;
					}
				}
			}
			*weaponstate = WEAPON_READY;
			return 0;
		}
	}
	
	if(*weaponstate == WEAPON_READY) {
		if(xm->ps->pm_type > 5 || !xm->cmd.wbuttons)
			goto label_27;
			/*
			
        v8 = 0.75 < *(float *)(v2 + 184);
        v9 = 0;
        v10 = 0.75 == *(float *)(v2 + 184);
        if ( (HIBYTE(v7) & 0x45) == 1 )
        {
          if ( *(_DWORD *)(v2 + 4) > 5 || !*(_BYTE *)(xm + 10) )
            goto LABEL_27;
          v11 = *(_DWORD *)(v2 + 980) & 0x200;
          BYTE1(v11) ^= 2u;
          LOBYTE(v11) = 7;
        }
        else
        {
          if ( *(_DWORD *)(v2 + 4) > 5 || !*(_BYTE *)(xm + 10) )
            goto LABEL_27;
          v11 = *(_DWORD *)(v2 + 980) & 0x200;
          BYTE1(v11) ^= 2u;
          LOBYTE(v11) = 4;
        }
        *(_DWORD *)(v2 + 980) = v11;
		*/
			//set cool stuff for keys?
		//ps_off(int,980) = 
		label_27:
		*weaponstate = WEAPON_RECHAMBERING;
		*weaponTime = int_ptr_val(v2 + 472);
		
		int v13 = int_ptr_val(v2 + 476);
		/*
		if(v13 && v13 < *weaponTime)
			*weaponDelay = v13;
		else
			*weaponDelay = 1;*/
		PM_AddEvent(EV_RECHAMBER_WEAPON);
	}
	
	return 0;
	#undef int_ptr_val
}
Beispiel #19
0
/**
* @brief Get the primary weapon of the client.
* @return the primary weapon of the soldier client
*/
weapon_t G_GetPrimaryWeaponForClientSoldier(weapon_t weapon, gclient_t *client)
{
	int              i;
	bg_playerclass_t *classInfo;

	if (client->sess.sessionTeam != TEAM_ALLIES && client->sess.sessionTeam != TEAM_AXIS)
	{
		return WP_NONE;
	}

	if (COM_BitCheck(client->ps.weapons, WP_PANZERFAUST) ||
	    COM_BitCheck(client->ps.weapons, WP_BAZOOKA) ||
	    COM_BitCheck(client->ps.weapons, WP_FLAMETHROWER) ||
	    COM_BitCheck(client->ps.weapons, WP_MOBILE_MG42) ||
	    COM_BitCheck(client->ps.weapons, WP_MOBILE_BROWNING) ||
	    COM_BitCheck(client->ps.weapons, WP_MORTAR) ||
	    COM_BitCheck(client->ps.weapons, WP_MORTAR2))
	{
		// if weapons are SMS & HW, return SMS if picking up SMS
		if (COM_BitCheck(client->ps.weapons, WP_MP40) && weapon == WP_THOMPSON)
		{
			return WP_MP40;
		}
		else if (COM_BitCheck(client->ps.weapons, WP_THOMPSON) && weapon == WP_MP40)
		{
			return WP_THOMPSON;
		}
		else
		{
			// if weapons are SMS & HW, return HW if picking up HW
			classInfo = &bg_allies_playerclasses[client->sess.playerType];
			for (i = 0; i < MAX_WEAPS_PER_CLASS; i++)
			{
				if (classInfo->classWeapons[i] == WP_MP40 || classInfo->classWeapons[i] == WP_THOMPSON)
				{
					continue;
				}

				if (COM_BitCheck(client->ps.weapons, classInfo->classWeapons[i]))
				{
					return classInfo->classWeapons[i];
				}
			}

			classInfo = &bg_axis_playerclasses[client->sess.playerType];
			for (i = 0; i < MAX_WEAPS_PER_CLASS; i++)
			{
				if (classInfo->classWeapons[i] == WP_MP40 || classInfo->classWeapons[i] == WP_THOMPSON)
				{
					continue;
				}

				if (COM_BitCheck(client->ps.weapons, classInfo->classWeapons[i]))
				{
					return classInfo->classWeapons[i];
				}
			}
		}
	}
	else
	{
		// if weapons are SMS and pistols, return SMS if picking up SMS or HW
		if (COM_BitCheck(client->ps.weapons, WP_THOMPSON))
		{
			return WP_THOMPSON;
		}
		if (COM_BitCheck(client->ps.weapons, WP_MP40))
		{
			return WP_MP40;
		}
	}

	return WP_NONE;
}
Beispiel #20
0
/**
* @brief Pick a weapon up.
*/
int Pickup_Weapon(gentity_t *ent, gentity_t *other)
{
	int      quantity;
	qboolean alreadyHave = qfalse;

	// magic ammo for any two-handed weapon
	if (ent->item->giTag == WP_AMMO)
	{
		AddMagicAmmo(other, ent->count);
		if (ent->parent && ent->parent->client)
		{
			other->client->pers.lastammo_client = ent->parent->s.clientNum;
		}

		// if LT isn't giving ammo to self or another LT or the enemy, give him some props
		if (other->client->ps.stats[STAT_PLAYER_CLASS] != PC_FIELDOPS)
		{
			if (ent->parent && ent->parent->client && other->client->sess.sessionTeam == ent->parent->client->sess.sessionTeam)
			{
				if (!(ent->parent->client->PCSpecialPickedUpCount % LT_SPECIAL_PICKUP_MOD))
				{
					AddScore(ent->parent, WOLF_AMMO_UP);
					if (ent->parent && ent->parent->client)
					{
						G_LogPrintf("Ammo_Pack: %d %d\n", (int)(ent->parent - g_entities), (int)(other - g_entities));
					}
				}
				ent->parent->client->PCSpecialPickedUpCount++;
				G_AddSkillPoints(ent->parent, SK_SIGNALS, 1.f);
				G_DebugAddSkillPoints(ent->parent, SK_SIGNALS, 1.f, "ammo pack picked up");

#ifdef FEATURE_OMNIBOT
				//omni-bot event
				if (ent->parent)
				{
					Bot_Event_RecievedAmmo(other - g_entities, ent->parent);
				}
#endif

				// extracted code originally here into AddMagicAmmo
				// add 1 clip of magic ammo for any two-handed weapon
			}
			return RESPAWN_NEVER;
		}
	}

	quantity = ent->count;

	// check if player already had the weapon
	alreadyHave = COM_BitCheck(other->client->ps.weapons, ent->item->giTag);

	// prevents drop/pickup weapon "quick reload" exploit
	if (alreadyHave)
	{
		Add_Ammo(other, ent->item->giTag, quantity, qfalse);

		// secondary weapon ammo
		if (ent->delay)
		{
			Add_Ammo(other, weaponTable[ent->item->giTag].weapAlts, ent->delay, qfalse);
		}
	}
	else
	{
		if (level.time - other->client->dropWeaponTime < 1000)
		{
			return 0;
		}

		// don't pick up when MG or mortar is set
		if (IS_MORTAR_WEAPON_SET(other->client->ps.weapon) || IS_MG_WEAPON_SET(other->client->ps.weapon))
		{
			return 0;
		}

		// see if we can pick it up
		if (G_CanPickupWeapon(ent->item->giTag, other))
		{
			weapon_t primaryWeapon;

			if (other->client->sess.playerType == PC_SOLDIER && other->client->sess.skill[SK_HEAVY_WEAPONS] >= 4)
			{
				primaryWeapon = G_GetPrimaryWeaponForClientSoldier(ent->item->giTag, other->client);
			}
			else
			{
				primaryWeapon = G_GetPrimaryWeaponForClient(other->client);
			}

			// added parens around ambiguous &&
			if (primaryWeapon)
			{
				// drop our primary weapon
				G_DropWeapon(other, primaryWeapon);

				// now pickup the other one
				other->client->dropWeaponTime = level.time;

				// add the weapon
				COM_BitSet(other->client->ps.weapons, ent->item->giTag);

				// fixup mauser/sniper issues
				switch (ent->item->giTag)
				{
				case WP_FG42:
					COM_BitSet(other->client->ps.weapons, WP_FG42SCOPE);
					break;
				case  WP_GARAND:
					COM_BitSet(other->client->ps.weapons, WP_GARAND_SCOPE);
					break;
				case  WP_K43:
					COM_BitSet(other->client->ps.weapons, WP_K43_SCOPE);
					break;
				case  WP_MORTAR:
					COM_BitSet(other->client->ps.weapons, WP_MORTAR_SET);
					break;
				case  WP_MORTAR2:
					COM_BitSet(other->client->ps.weapons, WP_MORTAR2_SET);
					break;
				case  WP_MOBILE_MG42:
					COM_BitSet(other->client->ps.weapons, WP_MOBILE_MG42_SET);
					break;
				case WP_MOBILE_BROWNING:
					COM_BitSet(other->client->ps.weapons, WP_MOBILE_BROWNING_SET);
					break;
				case  WP_CARBINE:
					COM_BitSet(other->client->ps.weapons, WP_M7);
					break;
				case WP_KAR98:
					COM_BitSet(other->client->ps.weapons, WP_GPG40);
					break;
				default:
					break;
				}

				other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = 0;
				other->client->ps.ammo[BG_FindAmmoForWeapon(ent->item->giTag)]     = 0;

				if (ent->item->giTag == WP_MORTAR || ent->item->giTag == WP_MORTAR2)
				{
					other->client->ps.ammo[BG_FindClipForWeapon(ent->item->giTag)] = quantity;

					// secondary weapon ammo
					if (ent->delay)
					{
						Add_Ammo(other, weaponTable[ent->item->giTag].weapAlts, ent->delay, qfalse);
					}
				}
				else
				{
					other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = quantity;

					// secondary weapon ammo
					if (ent->delay)
					{
						other->client->ps.ammo[weaponTable[ent->item->giTag].weapAlts] = ent->delay;
					}
				}
			}
		}
		else
		{
			return 0;
		}
	}

#ifdef FEATURE_OMNIBOT
	Bot_Event_AddWeapon(other->client->ps.clientNum, Bot_WeaponGameToBot(ent->item->giTag));
#endif

	return RESPAWN_NEVER;
}
Beispiel #21
0
/*
============
AICast_Think

  entry point for all cast AI
============
*/
void AICast_Think( int client, float thinktime ) {
	gentity_t       *ent;
	cast_state_t    *cs;
	int i;
	int animIndex;
	animation_t     *anim;

//	if (saveGamePending || (strlen( g_missionStats.string ) > 2 )) {
//		return;
//	}

	//
	// get the cast ready for processing
	//
	cs = AICast_GetCastState( client );
	ent = &g_entities[client];
	//
	// make sure we are using the right AAS data for this entity (one's that don't get set will default to the player's AAS data)
	trap_AAS_SetCurrentWorld( cs->aasWorldIndex );
	//
	// make sure we have a valid navigation system
	//
	if ( !trap_AAS_Initialized() ) {
		return;
	}
	//
	trap_EA_ResetInput( client, NULL );
	cs->aiFlags &= ~AIFL_VIEWLOCKED;
	//cs->bs->weaponnum = ent->client->ps.weapon;
	//
	// turn off flags that are set each frame if needed
	ent->client->ps.eFlags &= ~( EF_NOSWINGANGLES | EF_MONSTER_EFFECT | EF_MONSTER_EFFECT2 | EF_MONSTER_EFFECT3 );
	// conditional flags
	if ( ent->aiCharacter == AICHAR_ZOMBIE ) {
		if ( COM_BitCheck( ent->client->ps.weapons, WP_MONSTER_ATTACK1 ) ) {
			cs->aiFlags |= AIFL_NO_FLAME_DAMAGE;
			SET_FLAMING_ZOMBIE( ent->s, 1 );
		} else {
			SET_FLAMING_ZOMBIE( ent->s, 0 );
		}
	}
	//
	// if we're dead, do special stuff only
	if ( ent->health <= 0 || cs->revivingTime || cs->rebirthTime ) {
		//
		if ( cs->revivingTime && cs->revivingTime < level.time ) {
			// start us thinking again
			ent->client->ps.pm_type = PM_NORMAL;
			cs->revivingTime = 0;
		}
		//
		if ( cs->rebirthTime && cs->rebirthTime < level.time ) {
			vec3_t mins, maxs;
			int touch[10], numTouch;
			float oldmaxZ;

			oldmaxZ = ent->r.maxs[2];

			// make sure the area is clear
			AIChar_SetBBox( ent, cs );

			VectorAdd( ent->r.currentOrigin, ent->r.mins, mins );
			VectorAdd( ent->r.currentOrigin, ent->r.maxs, maxs );
			trap_UnlinkEntity( ent );

			numTouch = trap_EntitiesInBox( mins, maxs, touch, 10 );

			if ( numTouch ) {
				for ( i = 0; i < numTouch; i++ ) {
					//if (!g_entities[touch[i]].client || g_entities[touch[i]].r.contents == CONTENTS_BODY)
					if ( g_entities[touch[i]].r.contents & MASK_PLAYERSOLID ) {
						break;
					}
				}
				if ( i == numTouch ) {
					numTouch = 0;
				}
			}

			if ( numTouch == 0 ) {    // ok to spawn

				// give them health when they start reviving, so we won't gib after
				// just a couple shots while reviving
				ent->health =
					ent->client->ps.stats[STAT_HEALTH] =
						ent->client->ps.stats[STAT_MAX_HEALTH] =
							( ( cs->attributes[STARTING_HEALTH] - 50 ) > 30 ? ( cs->attributes[STARTING_HEALTH] - 50 ) : 30 );

				ent->r.contents = CONTENTS_BODY;
				ent->clipmask = MASK_PLAYERSOLID;
				ent->takedamage = qtrue;
				ent->waterlevel = 0;
				ent->watertype = 0;
				ent->flags = 0;
				ent->die = AICast_Die;
				ent->client->ps.eFlags &= ~EF_DEAD;
				ent->s.eFlags &= ~EF_DEAD;

				cs->rebirthTime = 0;
				cs->deathTime = 0;

				// play the revive animation
				cs->revivingTime = level.time + BG_AnimScriptEvent( &ent->client->ps, ANIM_ET_REVIVE, qfalse, qtrue );;
			} else {
				// can't spawn yet, so set bbox back, and wait
				ent->r.maxs[2] = oldmaxZ;
				ent->client->ps.maxs[2] = ent->r.maxs[2];
			}
			trap_LinkEntity( ent );
		}
		// ZOMBIE should set effect flag if really dead
		if ( cs->aiCharacter == AICHAR_ZOMBIE && !ent->r.contents ) {
			ent->client->ps.eFlags |= EF_MONSTER_EFFECT2;
		}
		//
		if ( ent->health > GIB_HEALTH && cs->deathTime && cs->deathTime < ( level.time - 3000 ) ) {
/*
			// been dead for long enough, set our animation to the end frame
			switch ( ent->s.legsAnim & ~ANIM_TOGGLEBIT ) {
			case BOTH_DEATH1:
			case BOTH_DEAD1:
				anim = BOTH_DEAD1;
				break;
			case BOTH_DEATH2:
			case BOTH_DEAD2:
				anim = BOTH_DEAD2;
				break;
			case BOTH_DEATH3:
			case BOTH_DEAD3:
				anim = BOTH_DEAD3;
				break;
			default:
				G_Error( "%s has unknown death animation\n", ent->classname);
			}
			ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
			ent->client->ps.legsAnim = ( ( ent->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
*/
			cs->deathTime = 0;
			ent->r.svFlags &= ~SVF_BROADCAST;
		}
		//
		// no more thinking required
		return;
	}
	//
	// set some anim conditions
	if ( cs->secondDeadTime ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SECONDLIFE, qtrue, qfalse );
	} else {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SECONDLIFE, qfalse, qfalse );
	}
	// set health value
	if ( ent->health <= 0.25 * cs->attributes[STARTING_HEALTH] ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 3, qfalse );
	} else if ( ent->health <= 0.5 * cs->attributes[STARTING_HEALTH] ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 2, qfalse );
	} else {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 1, qfalse );
	}
	//
	cs->speedScale = 1.0;           // reset each frame, set if required
	cs->actionFlags = 0;            // FIXME: move this to a Cast AI movement init function!
	//retrieve the current client state
	BotAI_GetClientState( client, &( cs->bs->cur_ps ) );
	//
	// setup movement speeds for the given state
	// walking
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_WALK );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[WALKING_SPEED] = anim->moveSpeed;
	}
	// crouching
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_WALKCR );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[CROUCHING_SPEED] = anim->moveSpeed;
	}
	// running
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_RUN );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[RUNNING_SPEED] = anim->moveSpeed;
	}
	// update crouch speed scale
	ent->client->ps.crouchSpeedScale = cs->attributes[CROUCHING_SPEED] / cs->attributes[RUNNING_SPEED];
	//
	// only enable headlook if we want to this frame
	ent->client->ps.eFlags &= ~EF_HEADLOOK;
	if ( cs->bs->enemy >= 0 ) {
		ent->client->ps.eFlags &= ~EF_STAND_IDLE2;  // never use alt idle if fighting
	}
	//
	// check for dead leader
	if ( cs->leaderNum >= 0 && g_entities[cs->leaderNum].health <= 0 ) {
		cs->leaderNum = -1;
	}
	//
#if 0
	// HACK for village2, if they are stuck, find a good position (there is a friendly guy placed inside a table)
	{
		trace_t tr;
		vec3_t org;
		trap_Trace( &tr, cs->bs->cur_ps.origin, cs->bs->cur_ps.mins, cs->bs->cur_ps.maxs, cs->bs->cur_ps.origin, cs->entityNum, CONTENTS_SOLID );
		while ( tr.startsolid ) {
			VectorCopy( cs->bs->cur_ps.origin, org );
			org[0] += 96 * crandom();
			org[1] += 96 * crandom();
			org[2] += 16 * crandom();
			trap_Trace( &tr, org, cs->bs->cur_ps.mins, cs->bs->cur_ps.maxs, org, cs->entityNum, CONTENTS_SOLID );
			G_SetOrigin( &g_entities[cs->entityNum], org );
			VectorCopy( org, g_entities[cs->entityNum].client->ps.origin );
		}
	}
#endif
	//add the delta angles to the cast's current view angles
	for ( i = 0; i < 3; i++ ) {
		cs->bs->viewangles[i] = AngleMod( cs->bs->viewangles[i] + SHORT2ANGLE( cs->bs->cur_ps.delta_angles[i] ) );
	}
	//
	//increase the local time of the cast
	cs->bs->ltime += thinktime;
	//
	cs->bs->thinktime = thinktime;
	//origin of the cast
	VectorCopy( cs->bs->cur_ps.origin, cs->bs->origin );
	//eye coordinates of the cast
	VectorCopy( cs->bs->cur_ps.origin, cs->bs->eye );
	cs->bs->eye[2] += cs->bs->cur_ps.viewheight;
	//get the area the cast is in
	cs->bs->areanum = BotPointAreaNum( cs->bs->origin );
	// clear flags each frame
	cs->bs->flags = 0;
	//
	// check enemy health
	if ( cs->bs->enemy >= 0 && g_entities[cs->bs->enemy].health <= 0 ) {
		cs->bs->enemy = -1;
	}
	//
	// if the previous movetype was temporary, set it back
	if ( cs->movestateType == MSTYPE_TEMPORARY ) {
		cs->movestate = MS_DEFAULT;
		cs->movestateType = MSTYPE_NONE;
	}
	// crouching?
	if (    ( cs->bs->attackcrouch_time > trap_AAS_Time() ) &&
			( ( cs->lastAttackCrouch > level.time - 500 ) || ( cs->thinkFuncChangeTime < level.time - 1000 ) ) ) {
		// if we are not moving, and we are firing, always stand, unless we are allowed to crouch + fire
		if ( VectorLength( cs->bs->cur_ps.velocity ) || ( cs->lastWeaponFired < level.time - 2000 ) || ( cs->aiFlags & AIFL_ATTACK_CROUCH ) ) {
			cs->lastAttackCrouch = level.time;
			trap_EA_Crouch( cs->bs->client );
		}
	}
	//
	//if (cs->bs->enemy >= 0) {
	//update the attack inventory values
	AICast_UpdateBattleInventory( cs, cs->bs->enemy );
	//}
	//
	// if we don't have ammo for the current weapon, get rid of it
	if ( !( COM_BitCheck( cs->bs->cur_ps.weapons, cs->bs->weaponnum ) ) || !AICast_GotEnoughAmmoForWeapon( cs, cs->bs->weaponnum ) ) {
		// select a weapon
		AICast_ChooseWeapon( cs, qfalse );
		// if still no ammo, select a blank weapon
		//if (!AICast_GotEnoughAmmoForWeapon( cs, cs->bs->weaponnum )) {
		//	cs->bs->weaponnum = WP_NONE;
		//}
	}
	//
	// in query mode, we do special handling (pause scripting, check for transition to alert/combat, etc)
	if ( cs->aiState == AISTATE_QUERY ) {
		AICast_QueryThink( cs );
	} else if ( cs->pauseTime < level.time )     {
		// do the thinking
		AICast_ProcessAIFunctions( cs, thinktime );
		//
		// make sure the correct weapon is selected
		trap_EA_SelectWeapon( cs->bs->client, cs->bs->weaponnum );
		//
		// process current script if it exists
		cs->castScriptStatusCurrent = cs->castScriptStatus;
		AICast_ScriptRun( cs, qfalse );
	}
	//
	// set special movestate if necessary
	if ( cs->movestateType != MSTYPE_NONE ) {
		switch ( cs->movestate ) {
		case MS_WALK:
			cs->actionFlags |= CASTACTION_WALK;
			break;
		case MS_CROUCH:
			trap_EA_Crouch( cs->entityNum );
			break;
		default:
			break; // TTimo gcc: MS_DEFAULT MS_RUN not handled in switch
		}
	}
	//
	//subtract the delta angles
	for ( i = 0; i < 3; i++ ) {
		cs->bs->viewangles[i] = AngleMod( cs->bs->viewangles[i] - SHORT2ANGLE( cs->bs->cur_ps.delta_angles[i] ) );
	}
}
Beispiel #22
0
int Pickup_Weapon( gentity_t *ent, gentity_t *other ) {
	int			quantity;
	qboolean	alreadyHave = qfalse;

	// JPW NERVE -- magic ammo for any two-handed weapon
	if( ent->item->giTag == WP_AMMO ) {
		AddMagicAmmo( other, ent->count );
		// tjw: added for g_shortcuts
		if(ent->parent && ent->parent->client)
			other->client->pers.lastammo_client = ent->parent->s.clientNum;
		// if LT isn't giving ammo to self or another LT or the enemy, give him some props
		if( other->client->ps.stats[STAT_PLAYER_CLASS] != PC_FIELDOPS ) {
			if ( ent->parent && ent->parent->client && other->client->sess.sessionTeam == ent->parent->client->sess.sessionTeam ) {
				if (!(ent->parent->client->PCSpecialPickedUpCount % LT_SPECIAL_PICKUP_MOD)) {
					AddScore(ent->parent, WOLF_AMMO_UP);
					if(ent->parent && ent->parent->client) {
						G_LogPrintf("Ammo_Pack: %d %d\n", ent->parent - g_entities, other - g_entities);	// OSP
					}
				}
				ent->parent->client->PCSpecialPickedUpCount++;

				// forty - #474 - don't give xp if we're picking up our own ammo packs.
				if(other != ent->parent) {
					G_AddSkillPoints( ent->parent, SK_SIGNALS, 1.f );
					G_DebugAddSkillPoints( ent->parent, SK_SIGNALS, 1.f, "ammo pack picked up" );
				}

				//omni-bot event
				if ( ent->parent )
					Bot_Event_RecievedAmmo(other-g_entities, ent->parent);

				// extracted code originally here into AddMagicAmmo -xkan, 9/18/2002
				// add 1 clip of magic ammo for any two-handed weapon
			}
			return RESPAWN_SP;
		}
	}

	if( ent->item->giTag == WP_BINOCULARS &&
			(g_weapons.integer & WPF_DROP_BINOCS) ) {
		COM_BitSet( other->client->ps.weapons, WP_BINOCULARS );
		other->client->ps.ammo[BG_FindAmmoForWeapon(WP_BINOCULARS)] = 1;
		other->client->ps.stats[STAT_KEYS] |= ( 1 << INV_BINOCS );
		other->client->sess.numBinocs++;
	}

	quantity = ent->count;

	// check if player already had the weapon
	alreadyHave = COM_BitCheck( other->client->ps.weapons, ent->item->giTag );

	// JPW NERVE  prevents drop/pickup weapon "quick reload" exploit
	if( alreadyHave ) {
		Add_Ammo( other, ent->item->giTag, quantity, qfalse );

		// Gordon: secondary weapon ammo
		if( ent->delay ) {
			Add_Ammo( other, weapAlts[ ent->item->giTag ], ent->delay, qfalse );
		}
	} else {
		if( level.time - other->client->dropWeaponTime < 1000 ) {
			return 0;
		}

		if( other->client->ps.weapon == WP_MORTAR_SET || other->client->ps.weapon == WP_MOBILE_MG42_SET ) {
			return 0;
		}

		// See if we can pick it up
		if( G_CanPickupWeapon( ent->item->giTag, other ) ) {
			weapon_t primaryWeapon = G_GetPrimaryWeaponForClient( other->client );

			// rain - added parens around ambiguous &&
			if( 1 || // Terifire, for dropweapon
				(other->client->sess.playerType == PC_SOLDIER && other->client->sess.skill[SK_HEAVY_WEAPONS] >= 4) ) {

				// gabriel: If a lvl 4 soldier is picking un a mp40/thompson,
				// don't allow the soldier to have both an mp40 and a thompson
				if ((ent->item->giTag == WP_MP40) &&
					COM_BitCheck( other->client->ps.weapons, WP_THOMPSON)) {

					G_DropWeapon( other, WP_THOMPSON);
				} else if ((ent->item->giTag == WP_THOMPSON) &&
					COM_BitCheck( other->client->ps.weapons, WP_MP40)) {

					G_DropWeapon( other, WP_MP40);
				} else if( primaryWeapon ) { // Otherwise, function normally
					// drop our primary weapon
					G_DropWeapon( other, primaryWeapon );
				}

				// now pickup the other one
				other->client->dropWeaponTime = level.time;

				// add the weapon
				COM_BitSet( other->client->ps.weapons, ent->item->giTag );

				// DHM - Fixup mauser/sniper issues
				if( ent->item->giTag == WP_FG42 ) {
					COM_BitSet( other->client->ps.weapons, WP_FG42SCOPE);
				} else if(ent->item->giTag == WP_GARAND) {
					COM_BitSet( other->client->ps.weapons, WP_GARAND_SCOPE);
				} else if( ent->item->giTag == WP_K43 ) {
					COM_BitSet( other->client->ps.weapons, WP_K43_SCOPE );
				} else if( ent->item->giTag == WP_MORTAR ) {
					COM_BitSet( other->client->ps.weapons, WP_MORTAR_SET );
				} else if( ent->item->giTag == WP_MOBILE_MG42 ) {
					COM_BitSet( other->client->ps.weapons, WP_MOBILE_MG42_SET );
				} else if( ent->item->giTag == WP_CARBINE ) {
					COM_BitSet( other->client->ps.weapons, WP_M7 );
				} else if( ent->item->giTag == WP_KAR98 ) {
					COM_BitSet( other->client->ps.weapons, WP_GPG40 );
				}

				other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = 0;
				other->client->ps.ammo[BG_FindAmmoForWeapon(ent->item->giTag)] = 0;

				if( ent->item->giTag == WP_MORTAR ) {
					other->client->ps.ammo[BG_FindClipForWeapon(ent->item->giTag)] = quantity;

					// Gordon: secondary weapon ammo
					if( ent->delay ) {
						Add_Ammo( other, weapAlts[ ent->item->giTag ], ent->delay, qfalse );
					}
/*	quad: maybe make a g_weapons flag for this?
				} else if ((ent->item->giTag == WP_THOMPSON || ent->item->giTag == WP_MP40)) { // TODO: ???? (quad)
					// redeye - NQ style weapon switching with full ammo
					// note: I wrote this code before source of NQ was available, so this is less
					// good than NQ's implementation but still better than original ETPub
					int weap = BG_FindClipForWeapon(ent->item->giTag);
					int ammoweap = BG_FindAmmoForWeapon(ent->item->giTag);
					int max_ammo_per_clip = GetAmmoTableData(ammoweap)->maxclip;
					int ammo_in_clips = quantity - max_ammo_per_clip;

					if (quantity <= max_ammo_per_clip)
					{
						other->client->ps.ammoclip[weap] = quantity;
						other->client->ps.ammo[weap] = 0;
					}
					else
					{
						other->client->ps.ammoclip[weap] = max_ammo_per_clip;
						other->client->ps.ammo[weap] = ammo_in_clips;
					}
*/
				} else {
					other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = quantity;

					// Gordon: secondary weapon ammo
					if( ent->delay ) {
						other->client->ps.ammo[ weapAlts[ ent->item->giTag ] ] = ent->delay;
					}
				}
			}
		} else {
			return 0;
		}
	}

	// TAT 1/6/2003 - If we are a bot, call the pickup function
#ifndef NO_BOT_SUPPORT
	if( other->r.svFlags & SVF_BOT )
		BotPickupWeapon( other->s.number, ent->item->giTag, alreadyHave );
#endif

	Bot_Event_AddWeapon(other->client->ps.clientNum, Bot_WeaponGameToBot(ent->item->giTag));
	return -1;
}
Beispiel #23
0
int Pickup_Weapon( gentity_t *ent, gentity_t *other ) {
	int quantity;
	qboolean alreadyHave = qfalse;
	int i,weapon;         // JPW NERVE

// JPW NERVE -- magic ammo for any two-handed weapon
	if ( ent->item->giTag == WP_AMMO ) {
// if LT isn't giving ammo to self or another LT or the enemy, give him some props
		if ( other->client->ps.stats[STAT_PLAYER_CLASS] != PC_LT ) {
			if ( ent->parent ) {
				if ( other->client->sess.sessionTeam == ent->parent->client->sess.sessionTeam ) {
					if ( ent->parent->client ) {
						if ( !( ent->parent->client->PCSpecialPickedUpCount % LT_SPECIAL_PICKUP_MOD ) ) {
							AddScore( ent->parent, WOLF_AMMO_UP );
						}
						ent->parent->client->PCSpecialPickedUpCount++;
					}
				}
			}
		}

		// everybody likes grenades -- abuse weapon var as grenade type and i as max # grenades class can carry
		switch ( other->client->ps.stats[STAT_PLAYER_CLASS] ) {
		case PC_LT: // redundant but added for completeness/flexibility
		case PC_MEDIC:
			i = 1;
			break;
		case PC_SOLDIER:
			i = 4;
			break;
		case PC_ENGINEER:
			i = 8;
			break;
		default:
			i = 1;
			break;
		}
		if ( other->client->sess.sessionTeam == TEAM_RED ) {
			weapon = WP_GRENADE_LAUNCHER;
		} else {
			weapon = WP_GRENADE_PINEAPPLE;
		}
		if ( other->client->ps.ammoclip[BG_FindClipForWeapon( weapon )] < i ) {
			other->client->ps.ammoclip[BG_FindClipForWeapon( weapon )]++;
		}
		COM_BitSet( other->client->ps.weapons,weapon );

		// TTimo - add 8 pistol bullets
		if ( other->client->sess.sessionTeam == TEAM_RED ) {
			weapon = WP_LUGER;
		} else {
			weapon = WP_COLT;
		}
//		G_Printf("filling magazine for weapon %d colt/luger (%d rounds)\n", weapon, ammoTable[weapon].maxclip);
		other->client->ps.ammo[BG_FindAmmoForWeapon( weapon )] += ammoTable[weapon].maxclip;
		if ( other->client->ps.ammo[BG_FindAmmoForWeapon( weapon )] > ammoTable[weapon].maxclip * 4 ) {
			other->client->ps.ammo[BG_FindAmmoForWeapon( weapon )] = ammoTable[weapon].maxclip * 4;
		}

		// and some two-handed ammo
		for ( i = 0; i < MAX_WEAPS_IN_BANK_MP; i++ ) {
			weapon = weapBanksMultiPlayer[3][i];
			if ( COM_BitCheck( other->client->ps.weapons, weapon ) ) {
//				G_Printf("filling magazine for weapon %d (%d rounds)\n",weapon,ammoTable[weapon].maxclip);
				if ( weapon == WP_FLAMETHROWER ) { // FT doesn't use magazines so refill tank
					other->client->ps.ammoclip[BG_FindAmmoForWeapon( WP_FLAMETHROWER )] = ammoTable[weapon].maxclip;
				} else {
					other->client->ps.ammo[BG_FindAmmoForWeapon( weapon )] += ammoTable[weapon].maxclip;
					if ( other->client->ps.ammo[BG_FindAmmoForWeapon( weapon )] > ammoTable[weapon].maxclip * 3 ) {
						other->client->ps.ammo[BG_FindAmmoForWeapon( weapon )] = ammoTable[weapon].maxclip * 3;
					}
				}
				return RESPAWN_SP;
			}
		}
		return RESPAWN_SP;
	}
// jpw
	if ( ent->count < 0 ) {
		quantity = 0; // None for you, sir!
	} else {
		if ( ent->count ) {
			quantity = ent->count;
		} else {
//----(SA) modified
// JPW NERVE did this so ammocounts work right on dropped weapons
			if ( g_gametype.integer != GT_SINGLE_PLAYER ) {
				quantity = ent->item->quantity;
			} else {
// jpw
				quantity = ( random() * ( ent->item->quantity - 1 ) ) + 1;  // giving 1-<item default count>
			}
		}
	}

	// check if player already had the weapon
	alreadyHave = COM_BitCheck( other->client->ps.weapons, ent->item->giTag );

	// add the weapon
	COM_BitSet( other->client->ps.weapons, ent->item->giTag );

	// DHM - Fixup mauser/sniper issues
	if ( ent->item->giTag == WP_MAUSER ) {
		COM_BitSet( other->client->ps.weapons, WP_SNIPERRIFLE );
	}
	if ( ent->item->giTag == WP_SNIPERRIFLE ) {
		COM_BitSet( other->client->ps.weapons, WP_MAUSER );
	}

	//----(SA)	added
	// snooper == automatic garand mod
	if ( ent->item->giTag == WP_SNOOPERSCOPE ) {
		COM_BitSet( other->client->ps.weapons, WP_GARAND );
	}
	// fg42scope == automatic fg42 mod
	else if ( ent->item->giTag == WP_FG42SCOPE ) {
		COM_BitSet( other->client->ps.weapons, WP_FG42 );
	} else if ( ent->item->giTag == WP_GARAND ) {
		COM_BitSet( other->client->ps.weapons, WP_SNOOPERSCOPE );
	}
	//----(SA)	end

// JPW NERVE  prevents drop/pickup weapon "quick reload" exploit
	if ( alreadyHave ) {
		Add_Ammo( other, ent->item->giTag, quantity, !alreadyHave );
	} else {
		other->client->ps.ammoclip[BG_FindClipForWeapon( ent->item->giTag )] = quantity;
	}
// jpw

	// single player has no respawns	(SA)
	if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
		return RESPAWN_SP;
	}

	if ( g_gametype.integer == GT_TEAM ) {
		return g_weaponTeamRespawn.integer;
	}

	return g_weaponRespawn.integer;
}
Beispiel #24
0
/*
=================
TossClientItems

Toss the weapon and powerups for the killed player
=================
*/
void TossClientItems( gentity_t *self ) {
	gitem_t     *item;
	vec3_t forward;
	int weapon;
	float angle;
	int i;
	gentity_t   *drop = 0;

	// drop the weapon if not a gauntlet or machinegun
	weapon = self->s.weapon;

	switch ( self->aiCharacter ) {
	case AICHAR_ZOMBIE:
	case AICHAR_WARZOMBIE:
	case AICHAR_LOPER:
		return;         //----(SA)	removed DK's special case
	default:
		break;
	}

	AngleVectors( self->r.currentAngles, forward, NULL, NULL );

	G_ThrowChair( self, forward, qtrue ); // drop chair if you're holding one  //----(SA)	added

	// make a special check to see if they are changing to a new
	// weapon that isn't the mg or gauntlet.  Without this, a client
	// can pick up a weapon, be killed, and not drop the weapon because
	// their weapon change hasn't completed yet and they are still holding the MG.

// (SA) always drop what you were switching to
	if ( 1 ) {
//	if ( weapon == WP_MACHINEGUN || weapon == WP_GRAPPLING_HOOK ) {
		if ( self->client->ps.weaponstate == WEAPON_DROPPING || self->client->ps.weaponstate == WEAPON_DROPPING_TORELOAD ) {
			weapon = self->client->pers.cmd.weapon;
		}
		if ( !( COM_BitCheck( self->client->ps.weapons, weapon ) ) ) {
			weapon = WP_NONE;
		}
	}

//----(SA)	added
	if ( weapon == WP_SNOOPERSCOPE ) {
		weapon = WP_GARAND;
	}
	if ( weapon == WP_FG42SCOPE ) {
		weapon = WP_FG42;
	}
	if ( weapon == WP_AKIMBO ) { //----(SA)	added
		weapon = WP_COLT;
	}
//----(SA)	end


	if ( weapon > WP_NONE && weapon < WP_MONSTER_ATTACK1 && self->client->ps.ammo[ BG_FindAmmoForWeapon( weapon )] ) {
		// find the item type for this weapon
		item = BG_FindItemForWeapon( weapon );
		// spawn the item

		// Rafael
		if ( !( self->client->ps.persistant[PERS_HWEAPON_USE] ) ) {
			drop = Drop_Item( self, item, 0, qfalse );
		}
	}

	if ( g_gametype.integer == GT_SINGLE_PLAYER ) {  // dropped items stay forever in SP
		if ( drop ) {
			drop->nextthink = 0;
		}
	}

	if ( g_gametype.integer != GT_TEAM ) {  // drop all the powerups if not in teamplay
		angle = 45;
		for ( i = 1 ; i < PW_NUM_POWERUPS ; i++ ) {
			if ( self->client->ps.powerups[ i ] > level.time ) {
				item = BG_FindItemForPowerup( i );
				if ( !item ) {
					continue;
				}
				drop = Drop_Item( self, item, angle, qfalse );
				// decide how many seconds it has left
				drop->count = ( self->client->ps.powerups[ i ] - level.time ) / 1000;
				if ( drop->count < 1 ) {
					drop->count = 1;
				}
				drop->nextthink = 0;    // stay forever
				angle += 45;
			}
		}
	}
}