halflife-photomode/dlls/gamerules.cpp
Joël Troch e0ba8cebc7 [HL25] Backport busters game mode
Also backport a define being moved at the top in "multiplay_gamerules.cpp".
And two changes related to weapons in general in "weapons.cpp".
2024-08-28 16:37:49 +02:00

409 lines
12 KiB
C++

/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//=========================================================
// GameRules.cpp
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "teamplay_gamerules.h"
#include "skill.h"
#include "game.h"
#include "UserMessages.h"
extern edict_t* EntSelectSpawnPoint(CBaseEntity* pPlayer);
CBasePlayerItem* CGameRules::FindNextBestWeapon(CBasePlayer* pPlayer, CBasePlayerItem* pCurrentWeapon)
{
if (pCurrentWeapon != nullptr && !pCurrentWeapon->CanHolster())
{
// can't put this gun away right now, so can't switch.
return nullptr;
}
const int currentWeight = pCurrentWeapon != nullptr ? pCurrentWeapon->iWeight() : -1;
CBasePlayerItem* pBest = nullptr; // this will be used in the event that we don't find a weapon in the same category.
int iBestWeight = -1; // no weapon lower than -1 can be autoswitched to
for (int i = 0; i < MAX_ITEM_TYPES; i++)
{
for (auto pCheck = pPlayer->m_rgpPlayerItems[i]; pCheck; pCheck = pCheck->m_pNext)
{
// don't reselect the weapon we're trying to get rid of
if (pCheck == pCurrentWeapon)
{
continue;
}
if (pCheck->iWeight() > -1 && pCheck->iWeight() == currentWeight)
{
// this weapon is from the same category.
if (pCheck->CanDeploy())
{
if (pPlayer->SwitchWeapon(pCheck))
{
return pCheck;
}
}
}
else if (pCheck->iWeight() > iBestWeight)
{
//ALERT ( at_console, "Considering %s\n", STRING( pCheck->pev->classname ) );
// we keep updating the 'best' weapon just in case we can't find a weapon of the same weight
// that the player was using. This will end up leaving the player with his heaviest-weighted
// weapon.
if (pCheck->CanDeploy())
{
// if this weapon is useable, flag it as the best
iBestWeight = pCheck->iWeight();
pBest = pCheck;
}
}
}
}
// if we make it here, we've checked all the weapons and found no useable
// weapon in the same catagory as the current weapon.
// if pBest is nullptr, we didn't find ANYTHING. Shouldn't be possible- should always
// at least get the crowbar, but ya never know.
return pBest;
}
bool CGameRules::GetNextBestWeapon(CBasePlayer* pPlayer, CBasePlayerItem* pCurrentWeapon, bool alwaysSearch)
{
if (auto pBest = FindNextBestWeapon(pPlayer, pCurrentWeapon); pBest != nullptr)
{
pPlayer->SwitchWeapon(pBest);
return true;
}
return false;
}
//=========================================================
//=========================================================
bool CGameRules::CanHaveAmmo(CBasePlayer* pPlayer, const char* pszAmmoName, int iMaxCarry)
{
int iAmmoIndex;
if (pszAmmoName)
{
iAmmoIndex = pPlayer->GetAmmoIndex(pszAmmoName);
if (iAmmoIndex > -1)
{
if (pPlayer->AmmoInventory(iAmmoIndex) < iMaxCarry)
{
// player has room for more of this type of ammo
return true;
}
}
}
return false;
}
//=========================================================
//=========================================================
edict_t* CGameRules::GetPlayerSpawnSpot(CBasePlayer* pPlayer)
{
edict_t* pentSpawnSpot = EntSelectSpawnPoint(pPlayer);
pPlayer->pev->origin = VARS(pentSpawnSpot)->origin + Vector(0, 0, 1);
pPlayer->pev->v_angle = g_vecZero;
pPlayer->pev->velocity = g_vecZero;
pPlayer->pev->angles = VARS(pentSpawnSpot)->angles;
pPlayer->pev->punchangle = g_vecZero;
pPlayer->pev->fixangle = 1;
return pentSpawnSpot;
}
//=========================================================
//=========================================================
bool CGameRules::CanHavePlayerItem(CBasePlayer* pPlayer, CBasePlayerItem* pWeapon)
{
// only living players can have items
if (pPlayer->pev->deadflag != DEAD_NO)
return false;
if (pWeapon->pszAmmo1())
{
if (!CanHaveAmmo(pPlayer, pWeapon->pszAmmo1(), pWeapon->iMaxAmmo1()))
{
// we can't carry anymore ammo for this gun. We can only
// have the gun if we aren't already carrying one of this type
if (pPlayer->HasPlayerItem(pWeapon))
{
return false;
}
}
}
else
{
// weapon doesn't use ammo, don't take another if you already have it.
if (pPlayer->HasPlayerItem(pWeapon))
{
return false;
}
}
// note: will fall through to here if GetItemInfo doesn't fill the struct!
return true;
}
//=========================================================
// load the SkillData struct with the proper values based on the skill level.
//=========================================================
void CGameRules::RefreshSkillData()
{
int iSkill;
iSkill = (int)CVAR_GET_FLOAT("skill");
g_iSkillLevel = iSkill;
if (iSkill < 1)
{
iSkill = 1;
}
else if (iSkill > 3)
{
iSkill = 3;
}
gSkillData.iSkillLevel = iSkill;
ALERT(at_console, "\nGAME SKILL LEVEL:%d\n", iSkill);
//Agrunt
gSkillData.agruntHealth = GetSkillCvar("sk_agrunt_health");
gSkillData.agruntDmgPunch = GetSkillCvar("sk_agrunt_dmg_punch");
// Apache
gSkillData.apacheHealth = GetSkillCvar("sk_apache_health");
// Barney
gSkillData.barneyHealth = GetSkillCvar("sk_barney_health");
// Big Momma
gSkillData.bigmommaHealthFactor = GetSkillCvar("sk_bigmomma_health_factor");
gSkillData.bigmommaDmgSlash = GetSkillCvar("sk_bigmomma_dmg_slash");
gSkillData.bigmommaDmgBlast = GetSkillCvar("sk_bigmomma_dmg_blast");
gSkillData.bigmommaRadiusBlast = GetSkillCvar("sk_bigmomma_radius_blast");
// Bullsquid
gSkillData.bullsquidHealth = GetSkillCvar("sk_bullsquid_health");
gSkillData.bullsquidDmgBite = GetSkillCvar("sk_bullsquid_dmg_bite");
gSkillData.bullsquidDmgWhip = GetSkillCvar("sk_bullsquid_dmg_whip");
gSkillData.bullsquidDmgSpit = GetSkillCvar("sk_bullsquid_dmg_spit");
// Gargantua
gSkillData.gargantuaHealth = GetSkillCvar("sk_gargantua_health");
gSkillData.gargantuaDmgSlash = GetSkillCvar("sk_gargantua_dmg_slash");
gSkillData.gargantuaDmgFire = GetSkillCvar("sk_gargantua_dmg_fire");
gSkillData.gargantuaDmgStomp = GetSkillCvar("sk_gargantua_dmg_stomp");
// Hassassin
gSkillData.hassassinHealth = GetSkillCvar("sk_hassassin_health");
// Headcrab
gSkillData.headcrabHealth = GetSkillCvar("sk_headcrab_health");
gSkillData.headcrabDmgBite = GetSkillCvar("sk_headcrab_dmg_bite");
// Hgrunt
gSkillData.hgruntHealth = GetSkillCvar("sk_hgrunt_health");
gSkillData.hgruntDmgKick = GetSkillCvar("sk_hgrunt_kick");
gSkillData.hgruntShotgunPellets = GetSkillCvar("sk_hgrunt_pellets");
gSkillData.hgruntGrenadeSpeed = GetSkillCvar("sk_hgrunt_gspeed");
// Houndeye
gSkillData.houndeyeHealth = GetSkillCvar("sk_houndeye_health");
gSkillData.houndeyeDmgBlast = GetSkillCvar("sk_houndeye_dmg_blast");
// ISlave
gSkillData.slaveHealth = GetSkillCvar("sk_islave_health");
gSkillData.slaveDmgClaw = GetSkillCvar("sk_islave_dmg_claw");
gSkillData.slaveDmgClawrake = GetSkillCvar("sk_islave_dmg_clawrake");
gSkillData.slaveDmgZap = GetSkillCvar("sk_islave_dmg_zap");
// Icthyosaur
gSkillData.ichthyosaurHealth = GetSkillCvar("sk_ichthyosaur_health");
gSkillData.ichthyosaurDmgShake = GetSkillCvar("sk_ichthyosaur_shake");
// Leech
gSkillData.leechHealth = GetSkillCvar("sk_leech_health");
gSkillData.leechDmgBite = GetSkillCvar("sk_leech_dmg_bite");
// Controller
gSkillData.controllerHealth = GetSkillCvar("sk_controller_health");
gSkillData.controllerDmgZap = GetSkillCvar("sk_controller_dmgzap");
gSkillData.controllerSpeedBall = GetSkillCvar("sk_controller_speedball");
gSkillData.controllerDmgBall = GetSkillCvar("sk_controller_dmgball");
// Nihilanth
gSkillData.nihilanthHealth = GetSkillCvar("sk_nihilanth_health");
gSkillData.nihilanthZap = GetSkillCvar("sk_nihilanth_zap");
// Scientist
gSkillData.scientistHealth = GetSkillCvar("sk_scientist_health");
// Snark
gSkillData.snarkHealth = GetSkillCvar("sk_snark_health");
gSkillData.snarkDmgBite = GetSkillCvar("sk_snark_dmg_bite");
gSkillData.snarkDmgPop = GetSkillCvar("sk_snark_dmg_pop");
// Zombie
gSkillData.zombieHealth = GetSkillCvar("sk_zombie_health");
gSkillData.zombieDmgOneSlash = GetSkillCvar("sk_zombie_dmg_one_slash");
gSkillData.zombieDmgBothSlash = GetSkillCvar("sk_zombie_dmg_both_slash");
//Turret
gSkillData.turretHealth = GetSkillCvar("sk_turret_health");
// MiniTurret
gSkillData.miniturretHealth = GetSkillCvar("sk_miniturret_health");
// Sentry Turret
gSkillData.sentryHealth = GetSkillCvar("sk_sentry_health");
// PLAYER WEAPONS
// Crowbar whack
gSkillData.plrDmgCrowbar = GetSkillCvar("sk_plr_crowbar");
// Glock Round
gSkillData.plrDmg9MM = GetSkillCvar("sk_plr_9mm_bullet");
// 357 Round
gSkillData.plrDmg357 = GetSkillCvar("sk_plr_357_bullet");
// MP5 Round
gSkillData.plrDmgMP5 = GetSkillCvar("sk_plr_9mmAR_bullet");
// M203 grenade
gSkillData.plrDmgM203Grenade = GetSkillCvar("sk_plr_9mmAR_grenade");
// Shotgun buckshot
gSkillData.plrDmgBuckshot = GetSkillCvar("sk_plr_buckshot");
// Crossbow
gSkillData.plrDmgCrossbowClient = GetSkillCvar("sk_plr_xbow_bolt_client");
gSkillData.plrDmgCrossbowMonster = GetSkillCvar("sk_plr_xbow_bolt_monster");
// RPG
gSkillData.plrDmgRPG = GetSkillCvar("sk_plr_rpg");
// Gauss gun
gSkillData.plrDmgGauss = GetSkillCvar("sk_plr_gauss");
// Egon Gun
gSkillData.plrDmgEgonNarrow = GetSkillCvar("sk_plr_egon_narrow");
gSkillData.plrDmgEgonWide = GetSkillCvar("sk_plr_egon_wide");
// Hand Grendade
gSkillData.plrDmgHandGrenade = GetSkillCvar("sk_plr_hand_grenade");
// Satchel Charge
gSkillData.plrDmgSatchel = GetSkillCvar("sk_plr_satchel");
// Tripmine
gSkillData.plrDmgTripmine = GetSkillCvar("sk_plr_tripmine");
// MONSTER WEAPONS
gSkillData.monDmg12MM = GetSkillCvar("sk_12mm_bullet");
gSkillData.monDmgMP5 = GetSkillCvar("sk_9mmAR_bullet");
gSkillData.monDmg9MM = GetSkillCvar("sk_9mm_bullet");
// MONSTER HORNET
gSkillData.monDmgHornet = GetSkillCvar("sk_hornet_dmg");
// PLAYER HORNET
gSkillData.plrDmgHornet = GetSkillCvar("sk_plr_hornet_dmg");
// HEALTH/CHARGE
gSkillData.suitchargerCapacity = GetSkillCvar("sk_suitcharger");
gSkillData.batteryCapacity = GetSkillCvar("sk_battery");
gSkillData.healthchargerCapacity = GetSkillCvar("sk_healthcharger");
gSkillData.healthkitCapacity = GetSkillCvar("sk_healthkit");
gSkillData.scientistHeal = GetSkillCvar("sk_scientist_heal");
// monster damage adj
gSkillData.monHead = GetSkillCvar("sk_monster_head");
gSkillData.monChest = GetSkillCvar("sk_monster_chest");
gSkillData.monStomach = GetSkillCvar("sk_monster_stomach");
gSkillData.monLeg = GetSkillCvar("sk_monster_leg");
gSkillData.monArm = GetSkillCvar("sk_monster_arm");
// player damage adj
gSkillData.plrHead = GetSkillCvar("sk_player_head");
gSkillData.plrChest = GetSkillCvar("sk_player_chest");
gSkillData.plrStomach = GetSkillCvar("sk_player_stomach");
gSkillData.plrLeg = GetSkillCvar("sk_player_leg");
gSkillData.plrArm = GetSkillCvar("sk_player_arm");
}
//=========================================================
// instantiate the proper game rules object
//=========================================================
CGameRules* InstallGameRules()
{
SERVER_COMMAND("exec game.cfg\n");
SERVER_EXECUTE();
if (1 == sv_busters.value)
{
g_teamplay = false;
return new CMultiplayBusters;
}
else if (0 == gpGlobals->deathmatch)
{
// generic half-life
g_teamplay = false;
return new CHalfLifeRules;
}
else
{
if (teamplay.value > 0)
{
// teamplay
g_teamplay = true;
return new CHalfLifeTeamplay;
}
if ((int)gpGlobals->deathmatch == 1)
{
// vanilla deathmatch
g_teamplay = false;
return new CHalfLifeMultiplay;
}
else
{
// vanilla deathmatch??
g_teamplay = false;
return new CHalfLifeMultiplay;
}
}
}