Exemplo n.º 1
0
/**
 * @brief Add ammo.
 * @param ent
 * @param weapon
 * @param count
 * @param fillClip
 * @return whether any ammo was added
 */
int Add_Ammo(gentity_t *ent, weapon_t weapon, int count, qboolean fillClip)
{
	weapon_t ammoweap      = GetWeaponTableData(weapon)->ammoIndex;
	int      maxammo       = BG_MaxAmmoForWeapon(ammoweap, ent->client->sess.skill);
	int      originalCount = ent->client->ps.ammo[ammoweap];

	if (GetWeaponTableData(ammoweap)->isGrenade || ammoweap == WP_DYNAMITE || ammoweap == WP_SATCHEL_DET) // make sure if he picks it up that he get's the "launcher" too
	{
		COM_BitSet(ent->client->ps.weapons, ammoweap);
		fillClip = qtrue;   // always filter into the "clip"
	}

	if (fillClip)
	{
		Fill_Clip(&ent->client->ps, weapon);
	}

	if (GetWeaponTableData(ammoweap)->isPanzer || ammoweap == WP_FLAMETHROWER)
	{
		ent->client->ps.ammoclip[ammoweap] += count;

		if (ent->client->ps.ammoclip[ammoweap] > maxammo)
		{
			ent->client->ps.ammoclip[ammoweap] = maxammo;   // - ent->client->ps.ammoclip[BG_FindClipForWeapon(weapon)];
		}
	}
	else
	{
		ent->client->ps.ammo[ammoweap] += count;

		if (ent->client->ps.ammo[ammoweap] > maxammo)
		{
			ent->client->ps.ammo[ammoweap] = maxammo;   // - ent->client->ps.ammoclip[BG_FindClipForWeapon(weapon)];
		}
	}

	if (count >= 999)     // 'really, give /all/'
	{
		ent->client->ps.ammo[ammoweap] = count;
	}

	return (ent->client->ps.ammo[ammoweap] > originalCount);
}
Exemplo n.º 2
0
/**
 * @brief Add the specified ammount of ammo into the clip.
 * @param[in,out] ps which player
 * @param[in] weapon to add ammo for
 * @param[in] ammomove amount to add. 0 means fill the clip if possible
 * @param[in] outOfReserve amount to be added out of reserve
 * @return qboolean whether ammo was added to the clip.
 */
int AddToClip(playerState_t *ps, weapon_t weapon, int ammomove, int outOfReserve)
{
	int      inclip, maxclip;
	weapon_t ammoweap = GetWeaponTableData(weapon)->ammoIndex;

	if (!IS_VALID_WEAPON(weapon))
	{
		return qfalse;
	}

	inclip  = ps->ammoclip[GetWeaponTableData(weapon)->clipIndex];
	maxclip = GetWeaponTableData(weapon)->maxClip;

	if (!ammomove)     // amount to add to the clip not specified
	{
		ammomove = maxclip - inclip;    // max amount that can be moved into the clip
	}
	else if (ammomove > maxclip - inclip)
	{
		ammomove = maxclip - inclip;
	}

	if (outOfReserve)
	{
		// cap move amount if it's more than you've got in reserve
		if (ammomove > ps->ammo[ammoweap])
		{
			ammomove = ps->ammo[ammoweap];
		}
	}

	if (ammomove)
	{
		if (outOfReserve)
		{
			ps->ammo[ammoweap] -= ammomove;
		}
		ps->ammoclip[GetWeaponTableData(weapon)->clipIndex] += ammomove;
		return qtrue;
	}
	return qfalse;
}
Exemplo n.º 3
0
/**
 * @brief Check if a weapon can be picked up.
 * @param[in] weapon
 * @param[in] ent
 * @return
 */
qboolean G_CanPickupWeapon(weapon_t weapon, gentity_t *ent)
{
	// prevent picking up while reloading
	if (ent->client->ps.weaponstate == WEAPON_RELOADING)
	{
		return qfalse;
	}

	// prevent picking up when overheating
	if (ent->client->ps.weaponTime > 0)
	{
		return qfalse;
	}

	// get an equivalent weapon if the cleint team is different of the weapon team, if not keep the current
	if (ent->client->sess.sessionTeam != GetWeaponTableData(weapon)->team && GetWeaponTableData(weapon)->weapEquiv)
	{
		weapon = GetWeaponTableData(weapon)->weapEquiv;
	}

	return BG_WeaponIsPrimaryForClassAndTeam(ent->client->sess.playerType, ent->client->sess.sessionTeam, weapon);
}
Exemplo n.º 4
0
/**
 * @brief G_PrintAccuracyLog
 * @param[in] ent
 */
void G_PrintAccuracyLog(gentity_t *ent)
{
	int  i;
	char buffer[2048];

	Q_strncpyz(buffer, "WeaponStats", 2048);

	for (i = WP_KNIFE; i < WP_NUM_WEAPONS; i++)
	{
		if (GetWeaponTableData(i)->indexWeaponStat == WS_MAX)
		{
			continue;
		}

		Q_strcat(buffer, 2048, va(" %i %i %i",
		                          ent->client->pers.playerStats.weaponStats[i].kills,
		                          ent->client->pers.playerStats.weaponStats[i].killedby,
		                          ent->client->pers.playerStats.weaponStats[i].teamkills));
	}

	Q_strcat(buffer, 2048, va(" %i", ent->client->pers.playerStats.selfkills));

	for (i = 0; i < HR_NUM_HITREGIONS; i++)
	{
		Q_strcat(buffer, 2048, va(" %i", ent->client->pers.playerStats.hitRegions[i]));
	}

	Q_strcat(buffer, 2048, va(" %i", 6 /*level.numOidTriggers*/));

	for (i = 0; i < 6 /*level.numOidTriggers*/; i++)
	{
		Q_strcat(buffer, 2048, va(" %i", ent->client->pers.playerStats.objectiveStats[i]));
		Q_strcat(buffer, 2048, va(" %i", ent->client->sess.sessionTeam == TEAM_AXIS ? level.objectiveStatsAxis[i] : level.objectiveStatsAllies[i]));
	}

	trap_SendServerCommand(ent - g_entities, buffer);
}
Exemplo n.º 5
0
/**
 * @brief Local func to actual do skill upgrade, used by both MP skill system, and SP scripted skill system
 * @param[in,out] ent
 * @param[in] skill
 */
void G_UpgradeSkill(gentity_t *ent, skillType_t skill)
{
	int i;

#ifdef FEATURE_LUA
	// *LUA* API callbacks
	if (G_LuaHook_UpgradeSkill(g_entities - ent, skill))
	{
		return;
	}
#endif

	// See if this is the first time we've reached this skill level
	for (i = 0; i < SK_NUM_SKILLS; i++)
	{
		if (i == skill)
		{
			continue;
		}

		if (ent->client->sess.skill[skill] <= ent->client->sess.skill[i])
		{
			break;
		}
	}

	G_DebugAddSkillLevel(ent, skill);

#ifdef FEATURE_RATING
	if (g_skillRating.integer)
	{
		ent->client->sess.rank = (int)(MAX(ent->client->sess.mu - 3 * ent->client->sess.sigma, 0.f) / (2 * MU) * NUM_EXPERIENCE_LEVELS);

		if (ent->client->sess.rank > 10)
		{
			ent->client->sess.rank = 10;
		}
	}
	else
	{
#endif
	if (i == SK_NUM_SKILLS)
	{
		// increase rank
		ent->client->sess.rank++;
	}

	if (ent->client->sess.rank >= 4)
	{
		int cnt = 0;

		// count the number of maxed out skills
		for (i = 0; i < SK_NUM_SKILLS; i++)
		{
			if (ent->client->sess.skill[i] >= 4)
			{
				cnt++;
			}
		}

		ent->client->sess.rank = cnt + 3;
		if (ent->client->sess.rank > 10)
		{
			ent->client->sess.rank = 10;
		}
	}
#ifdef FEATURE_RATING
}
#endif

	ClientUserinfoChanged(ent - g_entities);

	// Give em rightaway
	if (skill == SK_BATTLE_SENSE && ent->client->sess.skill[skill] == 1)
	{
		AddWeaponToPlayer(ent->client, WP_BINOCULARS, 1, 0, qfalse);
		ent->client->ps.stats[STAT_KEYS] |= (1 << INV_BINOCS);
	}
	else if (skill == SK_FIRST_AID && ent->client->sess.playerType == PC_MEDIC && ent->client->sess.skill[skill] == 4)
	{
		AddWeaponToPlayer(ent->client, WP_MEDIC_ADRENALINE, ent->client->ps.ammo[GetWeaponTableData(WP_MEDIC_ADRENALINE)->ammoIndex], ent->client->ps.ammoclip[GetWeaponTableData(WP_MEDIC_ADRENALINE)->clipIndex], qfalse);
	}
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
/**
 * @brief Drop Weapon
 * @param[in] ent
 * @param[in] weapon
 */
void G_DropWeapon(gentity_t *ent, weapon_t weapon)
{
	vec3_t    angles, velocity, org, offset, mins, maxs;
	gclient_t *client = ent->client;
	gentity_t *ent2;
	gitem_t   *item;
	trace_t   tr;

	if (!IS_VALID_WEAPON(weapon))
	{
		return;
	}

	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.f;
	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 (GetWeaponTableData(weapon)->weapAlts != WP_NONE)
	{
		weapon_t weapAlts = GetWeaponTableData(weapon)->weapAlts;

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

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

	if (weapon == client->ps.weapon)
	{
		client->ps.weapon = 0;
	}

	if (GetWeaponTableData(weapon)->isMortarSet)
	{
		ent2->count = client->ps.ammo[GetWeaponTableData(weapon)->ammoIndex] + client->ps.ammoclip[GetWeaponTableData(weapon)->clipIndex];
	}
	else
	{
		ent2->count = client->ps.ammoclip[GetWeaponTableData(weapon)->clipIndex];
	}

	if (weapon == WP_KAR98 || weapon == WP_CARBINE)
	{
		ent2->delay = client->ps.ammo[GetWeaponTableData(GetWeaponTableData(weapon)->weapAlts)->ammoIndex];
	}
	else
	{
		ent2->delay = 0;
	}

	//  ent2->item->quantity = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; // um, modifying an item is not a good idea
	client->ps.ammoclip[GetWeaponTableData(weapon)->clipIndex] = 0;

#ifdef FEATURE_OMNIBOT
	Bot_Event_RemoveWeapon(client->ps.clientNum, Bot_WeaponGameToBot(weapon));
#endif
}
Exemplo n.º 8
0
/**
 * @brief CG_TransitionPlayerState
 * @param[in] ps
 * @param[in] ops
 */
void CG_TransitionPlayerState(playerState_t *ps, playerState_t *ops)
{
#ifdef FEATURE_MULTIVIEW
	// MV client handling
	if (cg.mvTotalClients > 0)
	{
		if (ps->clientNum != ops->clientNum)
		{
			cg.thisFrameTeleport = qtrue;

			// clear voicechat
			cg.predictedPlayerEntity.voiceChatSpriteTime   = 0; // CHECKME: should we do this here?
			cg_entities[ps->clientNum].voiceChatSpriteTime = 0;

			*ops = *ps;
		}
		CG_CheckLocalSounds(ps, ops);
		return;
	}
#endif

	// check for changing follow mode
	if (ps->clientNum != ops->clientNum)
	{
		cg.thisFrameTeleport = qtrue;

		// clear voicechat
		cg.predictedPlayerEntity.voiceChatSpriteTime   = 0;
		cg_entities[ps->clientNum].voiceChatSpriteTime = 0;

		// make sure we don't get any unwanted transition effects
		*ops = *ps;

		// After Limbo, make sure and do a CG_Respawn
		if (ps->clientNum == cg.clientNum)
		{
			ops->persistant[PERS_SPAWN_COUNT]--;
		}
	}

	if (ps->eFlags & EF_FIRING)
	{
		cg.lastFiredWeaponTime = 0;
		cg.weaponFireTime     += cg.frametime;
	}
	else
	{
		if (cg.weaponFireTime > 500 /*&& cg.weaponFireTime*/)
		{
			cg.lastFiredWeaponTime = cg.time;
		}

		cg.weaponFireTime = 0;
	}

	// damage events (player is getting wounded)
	if (ps->damageEvent != ops->damageEvent && ps->damageCount)
	{
		CG_DamageFeedback(ps->damageYaw, ps->damagePitch, ps->damageCount);
	}

	// respawning
	if (ps->persistant[PERS_SPAWN_COUNT] != ops->persistant[PERS_SPAWN_COUNT])
	{
		CG_Respawn(ps->persistant[PERS_REVIVE_COUNT] != ops->persistant[PERS_REVIVE_COUNT] ? qtrue : qfalse);
	}

	if (cg.mapRestart)
	{
		CG_Respawn(qfalse);
		cg.mapRestart = qfalse;
	}

	if (cg.snap->ps.pm_type != PM_INTERMISSION
	    && ps->persistant[PERS_TEAM] != TEAM_SPECTATOR)
	{
		CG_CheckLocalSounds(ps, ops);
	}

	if (ps->eFlags & EF_PRONE_MOVING)
	{
		if (ps->weapon == WP_BINOCULARS)
		{
			if (ps->eFlags & EF_ZOOMING)
			{
				trap_SendConsoleCommand("-zoom\n");
			}
		}
		else if (GetWeaponTableData(ps->weapon)->type & WEAPON_TYPE_SCOPED)
		{
			CG_FinishWeaponChange(ps->weapon, GetWeaponTableData(ps->weapon)->weapAlts);
		}

		if (!(ops->eFlags & EF_PRONE_MOVING))
		{
			// this screws up auto-switching when dynamite planted or grenade thrown/out of ammo
			//CG_FinishWeaponChange( cg.weaponSelect, ps->nextWeapon );

			cg.proneMovingTime = cg.time;
		}
	}
	else if (ops->eFlags & EF_PRONE_MOVING)
	{
		cg.proneMovingTime = -cg.time;
	}

	if (!(ps->eFlags & EF_PRONE) && (ops->eFlags & EF_PRONE))
	{
		if (CHECKBITWISE(GetWeaponTableData(cg.weaponSelect)->type, WEAPON_TYPE_MG | WEAPON_TYPE_SET))
		{
			CG_FinishWeaponChange(cg.weaponSelect, ps->nextWeapon);
		}
	}

	// don't let players run with rifles -- speed 80 == crouch, 128 == walk, 256 == run until player start to don't run
	if ((GetWeaponTableData(ps->weapon)->type & WEAPON_TYPE_SCOPED) && VectorLength(ps->velocity) > 127)
	{
		CG_FinishWeaponChange(ps->weapon, GetWeaponTableData(ps->weapon)->weapAlts);
	}

	// run events
	CG_CheckPlayerstateEvents(ps, ops);

	// smooth the ducking viewheight change
	if (ps->viewheight != ops->viewheight)
	{
		cg.duckChange = ps->viewheight - ops->viewheight;
		cg.duckTime   = cg.time;
	}
}
Exemplo n.º 9
0
/**
 * @brief A respawn happened this snapshot
 * @param[in] revived
 */
void CG_Respawn(qboolean revived)
{
	static int oldTeam = -1;
	static int oldCls  = -1;
	cg.serverRespawning = qfalse;   // just in case

	// no error decay on player movement
	cg.thisFrameTeleport = qtrue;

	// need to reset client-side weapon animations
	cg.predictedPlayerState.weapAnim    = ((cg.predictedPlayerState.weapAnim & ANIM_TOGGLEBIT) ^ ANIM_TOGGLEBIT) | GetWeaponTableData(cg.snap->ps.weapon)->idleAnim;      // reset weapon animations
	cg.predictedPlayerState.weaponstate = WEAPON_READY; // hmm, set this?  what to?

	// display weapons available
	cg.weaponSelectTime = cg.time;

	cg.cursorHintIcon = 0;
	cg.cursorHintTime = 0;

	// select the weapon the server says we are using
	cg.weaponSelect = cg.snap->ps.weapon;

	// clear even more things on respawn
	cg.zoomedBinoc = qfalse;
	cg.zoomed      = qfalse;
	cg.zoomTime = 0;
	cg.zoomval  = 0;

	trap_SendConsoleCommand("-zoom\n");
	cg.binocZoomTime = 0;

	// ensure scoped weapons are reset after revive
	if (revived)
	{
		if (GetWeaponTableData(cg.snap->ps.weapon)->type & WEAPON_TYPE_SCOPED)
		{
			CG_FinishWeaponChange(cg.snap->ps.weapon, GetWeaponTableData(cg.snap->ps.weapon)->weapAlts);
		}
	}

	// clear pmext
	Com_Memset(&cg.pmext, 0, sizeof(cg.pmext));

	cg.pmext.bAutoReload = (qboolean)(cg_autoReload.integer > 0);

	cg.pmext.sprintTime = SPRINTTIME;

	if (!revived)
	{
		cgs.limboLoadoutSelected = qfalse;

		// reset switch back weapon
		cg.switchbackWeapon = WP_NONE;
	}

	// Saves the state of sidearm (riflenade weapon is considered as one too)
	// Puts the silencer on if class is COVERTOPS
	// Puts riflenade on if current weapon is riflenade weapon
	if (cg.predictedPlayerState.stats[STAT_PLAYER_CLASS] == PC_COVERTOPS)
	{
		cg.pmext.silencedSideArm = 1;
	}
	else if (GetWeaponTableData(cg.predictedPlayerState.weapon)->type & WEAPON_TYPE_RIFLENADE)
	{
		cg.pmext.silencedSideArm = 2;
	}

	cg.proneMovingTime = 0;

	// reset fog to world fog (if present)
	trap_R_SetFog(FOG_CMD_SWITCHFOG, FOG_MAP, 20, 0, 0, 0, 0);

	// try to exec a cfg file if it is found
	if (!revived)
	{
		if ((cgs.clientinfo[cg.clientNum].team == TEAM_AXIS || cgs.clientinfo[cg.clientNum].team == TEAM_ALLIES) && (cgs.clientinfo[cg.clientNum].cls != oldCls))
		{
			CG_execFile(va("autoexec_%s", BG_ClassnameForNumberFilename(cgs.clientinfo[cg.clientNum].cls)));
			oldCls = cgs.clientinfo[cg.clientNum].cls;
		}
		if (cgs.clientinfo[cg.clientNum].team != oldTeam)
		{
			CG_execFile(va("autoexec_%s", BG_TeamnameForNumber(cgs.clientinfo[cg.clientNum].team)));
			oldTeam = cgs.clientinfo[cg.clientNum].team;
		}
	}
}