//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #include "singleplay_gamerules.h" #ifdef CLIENT_DLL #else #include "globalstate.h" #include "player.h" #include "basecombatweapon.h" #include "gamerules.h" #include "game.h" #include "items.h" #endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #ifndef CLIENT_DLL // This allows us to test regenerative health systems on the fly void RegenerationForceOnChangeCallback( IConVar *pConVar, const char *pOldValue, float flOldValue ) { ConVarRef var( pConVar ); if ( !GlobalEntity_IsInTable( "player_regenerates_health" ) ) GlobalEntity_Add( MAKE_STRING("player_regenerates_health"), gpGlobals->mapname, ( var.GetBool() ) ? ( GLOBAL_ON ) : ( GLOBAL_OFF ) ); else GlobalEntity_SetState( MAKE_STRING("player_regenerates_health"), ( var.GetBool() ) ? ( GLOBAL_ON ) : ( GLOBAL_OFF ) ); } ConVar sv_regeneration_force_on( "sv_regeneration_force_on", "0", FCVAR_CHEAT, "Cheat to test regenerative health systems", RegenerationForceOnChangeCallback ); #endif //========================================================= //========================================================= bool CSingleplayRules::IsMultiplayer( void ) { return false; } // Needed during the conversion, but once DMG_* types have been fixed, this isn't used anymore. //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CSingleplayRules::Damage_GetTimeBased( void ) { int iDamage = ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ); return iDamage; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CSingleplayRules::Damage_GetShouldGibCorpse( void ) { int iDamage = ( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB ); return iDamage; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CSingleplayRules::Damage_GetShowOnHud( void ) { int iDamage = ( DMG_POISON | DMG_ACID | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK ); return iDamage; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CSingleplayRules::Damage_GetNoPhysicsForce( void ) { int iTimeBasedDamage = Damage_GetTimeBased(); int iDamage = ( DMG_FALL | DMG_BURN | DMG_PLASMA | DMG_DROWN | iTimeBasedDamage | DMG_CRUSH | DMG_PHYSGUN | DMG_PREVENT_PHYSICS_FORCE ); return iDamage; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CSingleplayRules::Damage_GetShouldNotBleed( void ) { int iDamage = ( DMG_POISON | DMG_ACID ); return iDamage; } //----------------------------------------------------------------------------- // Purpose: // Input : iDmgType - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSingleplayRules::Damage_IsTimeBased( int iDmgType ) { // Damage types that are time-based. return ( ( iDmgType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) ) != 0 ); } //----------------------------------------------------------------------------- // Purpose: // Input : iDmgType - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSingleplayRules::Damage_ShouldGibCorpse( int iDmgType ) { // Damage types that gib the corpse. return ( ( iDmgType & ( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB ) ) != 0 ); } //----------------------------------------------------------------------------- // Purpose: // Input : iDmgType - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSingleplayRules::Damage_ShowOnHUD( int iDmgType ) { // Damage types that have client HUD art. return ( ( iDmgType & ( DMG_POISON | DMG_ACID | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK ) ) != 0 ); } //----------------------------------------------------------------------------- // Purpose: // Input : iDmgType - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSingleplayRules::Damage_NoPhysicsForce( int iDmgType ) { // Damage types that don't have to supply a physics force & position. int iTimeBasedDamage = Damage_GetTimeBased(); return ( ( iDmgType & ( DMG_FALL | DMG_BURN | DMG_PLASMA | DMG_DROWN | iTimeBasedDamage | DMG_CRUSH | DMG_PHYSGUN | DMG_PREVENT_PHYSICS_FORCE ) ) != 0 ); } //----------------------------------------------------------------------------- // Purpose: // Input : iDmgType - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSingleplayRules::Damage_ShouldNotBleed( int iDmgType ) { // Damage types that don't make the player bleed. return ( ( iDmgType & ( DMG_POISON | DMG_ACID ) ) != 0 ); } #ifdef CLIENT_DLL #else extern CGameRules *g_pGameRules; extern bool g_fGameOver; //========================================================= //========================================================= CSingleplayRules::CSingleplayRules( void ) { } //========================================================= //========================================================= void CSingleplayRules::Think ( void ) { BaseClass::Think(); } //========================================================= //========================================================= bool CSingleplayRules::IsDeathmatch ( void ) { return false; } //========================================================= //========================================================= bool CSingleplayRules::IsCoOp( void ) { return false; } //----------------------------------------------------------------------------- // Purpose: Determine whether the player should switch to the weapon passed in // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSingleplayRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ) { //Must have ammo if ( ( pWeapon->HasAnyAmmo() == false ) && ( pWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY ) <= 0 ) ) return false; //Always take a loaded gun if we have nothing else if ( pPlayer->GetActiveWeapon() == NULL ) return true; // The given weapon must allow autoswitching to it from another weapon. if ( !pWeapon->AllowsAutoSwitchTo() ) return false; // The active weapon must allow autoswitching from it. if ( !pPlayer->GetActiveWeapon()->AllowsAutoSwitchFrom() ) return false; //Don't switch if our current gun doesn't want to be holstered if ( pPlayer->GetActiveWeapon()->CanHolster() == false ) return false; //Only switch if the weapon is better than what we're using if ( ( pWeapon != pPlayer->GetActiveWeapon() ) && ( pWeapon->GetWeight() <= pPlayer->GetActiveWeapon()->GetWeight() ) ) return false; return true; } //----------------------------------------------------------------------------- // Purpose: Find the next best weapon to use and return it. //----------------------------------------------------------------------------- CBaseCombatWeapon *CSingleplayRules::GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) { if ( pCurrentWeapon && !pCurrentWeapon->AllowsAutoSwitchFrom() ) return NULL; CBaseCombatWeapon *pBestWeapon = NULL; CBaseCombatWeapon *pWeapon; int nBestWeight = -1; //Search for the best weapon to use next based on its weight for ( int i = 0; i < pPlayer->WeaponCount(); i++ ) { pWeapon = pPlayer->GetWeapon(i); if ( pWeapon == NULL ) continue; #ifdef PORTAL2 if ( pWeapon == pCurrentWeapon ) continue; #endif // PORTAL2 // If we have an active weapon and this weapon doesn't allow autoswitching away // from another weapon, skip it. if ( pCurrentWeapon && !pWeapon->AllowsAutoSwitchTo() ) continue; // Must be eligible for switching to. if (!pPlayer->Weapon_CanSwitchTo(pWeapon)) continue; // Must be of higher quality. if ( pWeapon->GetWeight() <= nBestWeight ) continue; // We must have primary ammo if ( pWeapon->UsesClipsForAmmo1() && pWeapon->Clip1() <= 0 && !pWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY ) ) continue; // This is a better candidate than what we had. nBestWeight = pWeapon->GetWeight(); pBestWeapon = pWeapon; } return pBestWeapon; } //----------------------------------------------------------------------------- // Purpose: // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSingleplayRules::SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) { CBaseCombatWeapon *pWeapon = GetNextBestWeapon( pPlayer, pCurrentWeapon ); if ( pWeapon != NULL ) return pPlayer->Weapon_Switch( pWeapon ); return false; } //========================================================= //========================================================= bool CSingleplayRules::ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) { return true; } void CSingleplayRules::InitHUD( CBasePlayer *pl ) { } //========================================================= //========================================================= void CSingleplayRules::ClientDisconnected( edict_t *pClient ) { } //========================================================= //========================================================= float CSingleplayRules::FlPlayerFallDamage( CBasePlayer *pPlayer ) { // subtract off the speed at which a player is allowed to fall without being hurt, // so damage will be based on speed beyond that, not the entire fall return (pPlayer->m_Local.m_flFallVelocity - PLAYER_MAX_SAFE_FALL_SPEED) * DAMAGE_FOR_FALL_SPEED; } //========================================================= //========================================================= bool CSingleplayRules::AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ) { return true; } //========================================================= //========================================================= void CSingleplayRules::PlayerSpawn( CBasePlayer *pPlayer ) { // Player no longer gets all weapons to start. // He has to pick them up now. Use impulse 101 // to give him all weapons } //========================================================= //========================================================= bool CSingleplayRules::AllowAutoTargetCrosshair( void ) { return ( IsSkillLevel(SKILL_EASY) ); } //========================================================= //========================================================= int CSingleplayRules::GetAutoAimMode() { return sk_autoaim_mode.GetInt(); } //========================================================= //========================================================= bool CSingleplayRules::FPlayerCanRespawn( CBasePlayer *pPlayer ) { return true; } //========================================================= //========================================================= float CSingleplayRules::FlPlayerSpawnTime( CBasePlayer *pPlayer ) { return gpGlobals->curtime;//now! } //========================================================= // IPointsForKill - how many points awarded to anyone // that kills this player? //========================================================= int CSingleplayRules::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) { return 1; } //========================================================= // PlayerKilled - someone/something killed this player //========================================================= void CSingleplayRules::PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ) { } //========================================================= // Deathnotice //========================================================= void CSingleplayRules::DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ) { } //========================================================= // FlWeaponRespawnTime - what is the time in the future // at which this weapon may spawn? //========================================================= float CSingleplayRules::FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ) { return -1; } //========================================================= // FlWeaponRespawnTime - Returns 0 if the weapon can respawn // now, otherwise it returns the time at which it can try // to spawn again. //========================================================= float CSingleplayRules::FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ) { return 0; } //========================================================= // VecWeaponRespawnSpot - where should this weapon spawn? // Some game variations may choose to randomize spawn locations //========================================================= Vector CSingleplayRules::VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ) { return pWeapon->GetAbsOrigin(); } //========================================================= // WeaponShouldRespawn - any conditions inhibiting the // respawning of this weapon? //========================================================= int CSingleplayRules::WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ) { return GR_WEAPON_RESPAWN_NO; } //========================================================= //========================================================= bool CSingleplayRules::CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ) { return true; } //========================================================= //========================================================= void CSingleplayRules::PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem ) { } //========================================================= //========================================================= int CSingleplayRules::ItemShouldRespawn( CItem *pItem ) { return GR_ITEM_RESPAWN_NO; } //========================================================= // At what time in the future may this Item respawn? //========================================================= float CSingleplayRules::FlItemRespawnTime( CItem *pItem ) { return -1; } //========================================================= // Where should this item respawn? // Some game variations may choose to randomize spawn locations //========================================================= Vector CSingleplayRules::VecItemRespawnSpot( CItem *pItem ) { return pItem->GetAbsOrigin(); } //========================================================= // What angles should this item use to respawn? //========================================================= QAngle CSingleplayRules::VecItemRespawnAngles( CItem *pItem ) { return pItem->GetAbsAngles(); } //========================================================= //========================================================= bool CSingleplayRules::IsAllowedToSpawn( CBaseEntity *pEntity ) { return true; } //========================================================= //========================================================= void CSingleplayRules::PlayerGotAmmo( CBaseCombatCharacter *pPlayer, char *szName, int iCount ) { } //========================================================= //========================================================= float CSingleplayRules::FlHealthChargerRechargeTime( void ) { return 0;// don't recharge } //========================================================= //========================================================= int CSingleplayRules::DeadPlayerWeapons( CBasePlayer *pPlayer ) { return GR_PLR_DROP_GUN_NO; } //========================================================= //========================================================= int CSingleplayRules::DeadPlayerAmmo( CBasePlayer *pPlayer ) { return GR_PLR_DROP_AMMO_NO; } //========================================================= //========================================================= int CSingleplayRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) { // why would a single player in half life need this? return GR_NOTTEAMMATE; } //========================================================= //========================================================= bool CSingleplayRules::PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker, bool bTeamOnly ) { return !bTeamOnly || PlayerRelationship( pListener, pSpeaker ) == GR_TEAMMATE; } //========================================================= //========================================================= bool CSingleplayRules::FAllowNPCs( void ) { return true; } #endif