2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include "../idlib/precompiled.h"
# pragma hdrstop
# include "Game_local.h"
# include "../framework/Common_local.h"
# include "PredictedValue_impl.h"
idCVar flashlight_batteryDrainTimeMS ( " flashlight_batteryDrainTimeMS " , " 30000 " , CVAR_INTEGER , " amount of time (in MS) it takes for full battery to drain ( - 1 = = no battery drain ) " ) ;
idCVar flashlight_batteryChargeTimeMS ( " flashlight_batteryChargeTimeMS " , " 3000 " , CVAR_INTEGER , " amount of time (in MS) it takes to fully recharge battery " ) ;
idCVar flashlight_minActivatePercent ( " flashlight_minActivatePercent " , " .25 " , CVAR_FLOAT , " ( 0.0 - 1.0 ) minimum amount of battery ( % ) needed to turn on flashlight " ) ;
idCVar flashlight_batteryFlickerPercent ( " flashlight_batteryFlickerPercent " , " .1 " , CVAR_FLOAT , " chance of flickering when battery is low " ) ;
// No longer userinfo, but I don't want to rename the cvar
idCVar ui_showGun ( " ui_showGun " , " 1 " , CVAR_GAME | CVAR_ARCHIVE | CVAR_BOOL , " show gun " ) ;
// Client-authoritative stuff
idCVar pm_clientAuthoritative_debug ( " pm_clientAuthoritative_debug " , " 0 " , CVAR_BOOL , " " ) ;
idCVar pm_controllerShake_damageMaxMag ( " pm_controllerShake_damageMaxMag " , " 60.0f " , CVAR_FLOAT , " " ) ;
idCVar pm_controllerShake_damageMaxDur ( " pm_controllerShake_damageMaxDur " , " 60.0f " , CVAR_FLOAT , " " ) ;
idCVar pm_clientAuthoritative_warnDist ( " pm_clientAuthoritative_warnDist " , " 100.0f " , CVAR_FLOAT , " " ) ;
idCVar pm_clientAuthoritative_minDistZ ( " pm_clientAuthoritative_minDistZ " , " 1.0f " , CVAR_FLOAT , " " ) ;
idCVar pm_clientAuthoritative_minDist ( " pm_clientAuthoritative_minDist " , " -1.0f " , CVAR_FLOAT , " " ) ;
idCVar pm_clientAuthoritative_Lerp ( " pm_clientAuthoritative_Lerp " , " 0.9f " , CVAR_FLOAT , " " ) ;
idCVar pm_clientAuthoritative_Divergence ( " pm_clientAuthoritative_Divergence " , " 200.0f " , CVAR_FLOAT , " " ) ;
idCVar pm_clientInterpolation_Divergence ( " pm_clientInterpolation_Divergence " , " 5000.0f " , CVAR_FLOAT , " " ) ;
idCVar pm_clientAuthoritative_minSpeedSquared ( " pm_clientAuthoritative_minSpeedSquared " , " 1000.0f " , CVAR_FLOAT , " " ) ;
extern idCVar g_demoMode ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Player control of the Doom Marine .
This object handles all player movement and world interaction .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// distance between ladder rungs (actually is half that distance, but this sounds better)
const int LADDER_RUNG_DISTANCE = 32 ;
// amount of health per dose from the health station
const int HEALTH_PER_DOSE = 10 ;
// time before a weapon dropped to the floor disappears
const int WEAPON_DROP_TIME = 20 * 1000 ;
// time before a next or prev weapon switch happens
const int WEAPON_SWITCH_DELAY = 150 ;
// how many units to raise spectator above default view height so it's in the head of someone
const int SPECTATE_RAISE = 25 ;
const int HEALTHPULSE_TIME = 333 ;
// minimum speed to bob and play run/walk animations at
const float MIN_BOB_SPEED = 5.0f ;
// Special team used for spectators that we ONLY store on lobby. The local team property on player remains as 0 or 1.
const float LOBBY_SPECTATE_TEAM_FOR_VOICE_CHAT = 2 ;
const idEventDef EV_Player_GetButtons ( " getButtons " , NULL , ' d ' ) ;
const idEventDef EV_Player_GetMove ( " getMove " , NULL , ' v ' ) ;
const idEventDef EV_Player_GetViewAngles ( " getViewAngles " , NULL , ' v ' ) ;
const idEventDef EV_Player_StopFxFov ( " stopFxFov " ) ;
const idEventDef EV_Player_EnableWeapon ( " enableWeapon " ) ;
const idEventDef EV_Player_DisableWeapon ( " disableWeapon " ) ;
const idEventDef EV_Player_GetCurrentWeapon ( " getCurrentWeapon " , NULL , ' s ' ) ;
const idEventDef EV_Player_GetPreviousWeapon ( " getPreviousWeapon " , NULL , ' s ' ) ;
const idEventDef EV_Player_SelectWeapon ( " selectWeapon " , " s " ) ;
const idEventDef EV_Player_GetWeaponEntity ( " getWeaponEntity " , NULL , ' e ' ) ;
const idEventDef EV_Player_OpenPDA ( " openPDA " ) ;
const idEventDef EV_Player_InPDA ( " inPDA " , NULL , ' d ' ) ;
const idEventDef EV_Player_ExitTeleporter ( " exitTeleporter " ) ;
const idEventDef EV_Player_StopAudioLog ( " stopAudioLog " ) ;
const idEventDef EV_Player_HideTip ( " hideTip " ) ;
const idEventDef EV_Player_LevelTrigger ( " levelTrigger " ) ;
const idEventDef EV_SpectatorTouch ( " spectatorTouch " , " et " ) ;
const idEventDef EV_Player_GiveInventoryItem ( " giveInventoryItem " , " s " ) ;
const idEventDef EV_Player_RemoveInventoryItem ( " removeInventoryItem " , " s " ) ;
const idEventDef EV_Player_GetIdealWeapon ( " getIdealWeapon " , NULL , ' s ' ) ;
const idEventDef EV_Player_SetPowerupTime ( " setPowerupTime " , " dd " ) ;
const idEventDef EV_Player_IsPowerupActive ( " isPowerupActive " , " d " , ' d ' ) ;
2012-11-28 15:47:07 +00:00
const idEventDef EV_Player_WeaponAvailable ( " weaponAvailable " , " s " , ' d ' ) ;
2012-11-26 18:58:24 +00:00
const idEventDef EV_Player_StartWarp ( " startWarp " ) ;
const idEventDef EV_Player_StopHelltime ( " stopHelltime " , " d " ) ;
const idEventDef EV_Player_ToggleBloom ( " toggleBloom " , " d " ) ;
const idEventDef EV_Player_SetBloomParms ( " setBloomParms " , " ff " ) ;
CLASS_DECLARATION ( idActor , idPlayer )
2012-11-28 15:47:07 +00:00
EVENT ( EV_Player_GetButtons , idPlayer : : Event_GetButtons )
EVENT ( EV_Player_GetMove , idPlayer : : Event_GetMove )
EVENT ( EV_Player_GetViewAngles , idPlayer : : Event_GetViewAngles )
EVENT ( EV_Player_StopFxFov , idPlayer : : Event_StopFxFov )
EVENT ( EV_Player_EnableWeapon , idPlayer : : Event_EnableWeapon )
EVENT ( EV_Player_DisableWeapon , idPlayer : : Event_DisableWeapon )
EVENT ( EV_Player_GetCurrentWeapon , idPlayer : : Event_GetCurrentWeapon )
EVENT ( EV_Player_GetPreviousWeapon , idPlayer : : Event_GetPreviousWeapon )
EVENT ( EV_Player_SelectWeapon , idPlayer : : Event_SelectWeapon )
EVENT ( EV_Player_GetWeaponEntity , idPlayer : : Event_GetWeaponEntity )
EVENT ( EV_Player_OpenPDA , idPlayer : : Event_OpenPDA )
EVENT ( EV_Player_InPDA , idPlayer : : Event_InPDA )
EVENT ( EV_Player_ExitTeleporter , idPlayer : : Event_ExitTeleporter )
EVENT ( EV_Player_StopAudioLog , idPlayer : : Event_StopAudioLog )
EVENT ( EV_Player_HideTip , idPlayer : : Event_HideTip )
EVENT ( EV_Player_LevelTrigger , idPlayer : : Event_LevelTrigger )
EVENT ( EV_Gibbed , idPlayer : : Event_Gibbed )
EVENT ( EV_Player_GiveInventoryItem , idPlayer : : Event_GiveInventoryItem )
EVENT ( EV_Player_RemoveInventoryItem , idPlayer : : Event_RemoveInventoryItem )
EVENT ( EV_Player_GetIdealWeapon , idPlayer : : Event_GetIdealWeapon )
EVENT ( EV_Player_WeaponAvailable , idPlayer : : Event_WeaponAvailable )
EVENT ( EV_Player_SetPowerupTime , idPlayer : : Event_SetPowerupTime )
EVENT ( EV_Player_IsPowerupActive , idPlayer : : Event_IsPowerupActive )
EVENT ( EV_Player_StartWarp , idPlayer : : Event_StartWarp )
EVENT ( EV_Player_StopHelltime , idPlayer : : Event_StopHelltime )
EVENT ( EV_Player_ToggleBloom , idPlayer : : Event_ToggleBloom )
EVENT ( EV_Player_SetBloomParms , idPlayer : : Event_SetBloomParms )
2012-11-26 18:58:24 +00:00
END_CLASS
const int MAX_RESPAWN_TIME = 10000 ;
const int RAGDOLL_DEATH_TIME = 3000 ;
const int MAX_PDAS = 64 ;
const int MAX_PDA_ITEMS = 128 ;
const int STEPUP_TIME = 200 ;
const int MAX_INVENTORY_ITEMS = 20 ;
/*
= = = = = = = = = = = = = =
idInventory : : Clear
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : Clear ( )
{
2012-11-26 18:58:24 +00:00
maxHealth = 0 ;
weapons = 0 ;
powerups = 0 ;
armor = 0 ;
maxarmor = 0 ;
deplete_armor = 0 ;
deplete_rate = 0.0f ;
deplete_ammount = 0 ;
nextArmorDepleteTime = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < ammo . Num ( ) ; + + i )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] . Set ( 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ClearPowerUps ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set to -1 so that the gun knows to have a full clip the first time we get it and at the start of the level
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < clip . Num ( ) ; + + i )
{
2012-11-26 18:58:24 +00:00
clip [ i ] . Set ( - 1 ) ;
}
items . DeleteContents ( true ) ;
2012-11-28 15:47:07 +00:00
memset ( pdasViewed , 0 , 4 * sizeof ( pdasViewed [ 0 ] ) ) ;
2012-11-26 18:58:24 +00:00
pdas . Clear ( ) ;
videos . Clear ( ) ;
emails . Clear ( ) ;
selVideo = 0 ;
selEMail = 0 ;
selPDA = 0 ;
selAudio = 0 ;
pdaOpened = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
levelTriggers . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
nextItemPickup = 0 ;
nextItemNum = 1 ;
onePickupTime = 0 ;
pickupItemNames . Clear ( ) ;
objectiveNames . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ammoPredictTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastGiveTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ammoPulse = false ;
weaponPulse = false ;
armorPulse = false ;
}
/*
= = = = = = = = = = = = = =
idInventory : : GivePowerUp
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : GivePowerUp ( idPlayer * player , int powerup , int msec )
{
2012-11-26 18:58:24 +00:00
powerups | = 1 < < powerup ;
powerupEndTime [ powerup ] = gameLocal . time + msec ;
}
/*
= = = = = = = = = = = = = =
idInventory : : ClearPowerUps
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : ClearPowerUps ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_POWERUPS ; i + + )
{
2012-11-26 18:58:24 +00:00
powerupEndTime [ i ] = 0 ;
}
powerups = 0 ;
}
/*
= = = = = = = = = = = = = =
idInventory : : GetPersistantData
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : GetPersistantData ( idDict & dict )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
2012-11-28 15:47:07 +00:00
idDict * item ;
2012-11-26 18:58:24 +00:00
idStr key ;
2012-11-28 15:47:07 +00:00
const idKeyValue * kv ;
const char * name ;
2012-11-26 18:58:24 +00:00
// armor
dict . SetInt ( " armor " , armor ) ;
2012-11-28 15:47:07 +00:00
// don't bother with powerups, maxhealth, maxarmor, or the clip
2012-11-26 18:58:24 +00:00
// ammo
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
2012-11-26 18:58:24 +00:00
name = idWeapon : : GetAmmoNameForNum ( ( ammo_t ) i ) ;
2012-11-28 15:47:07 +00:00
if ( name )
{
2012-11-26 18:58:24 +00:00
dict . SetInt ( name , ammo [ i ] . Get ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//Save the clip data
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
dict . SetInt ( va ( " clip%i " , i ) , clip [ i ] . Get ( ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// items
num = 0 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < items . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
item = items [ i ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// copy all keys with "inv_"
kv = item - > MatchPrefix ( " inv_ " ) ;
2012-11-28 15:47:07 +00:00
if ( kv )
{
while ( kv )
{
2012-11-26 18:58:24 +00:00
sprintf ( key , " item_%i %s " , num , kv - > GetKey ( ) . c_str ( ) ) ;
dict . Set ( key , kv - > GetValue ( ) ) ;
kv = item - > MatchPrefix ( " inv_ " , kv ) ;
}
num + + ;
}
}
dict . SetInt ( " items " , num ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// pdas viewed
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < 4 ; i + + )
{
dict . SetInt ( va ( " pdasViewed_%i " , i ) , pdasViewed [ i ] ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dict . SetInt ( " selPDA " , selPDA ) ;
dict . SetInt ( " selVideo " , selVideo ) ;
dict . SetInt ( " selEmail " , selEMail ) ;
dict . SetInt ( " selAudio " , selAudio ) ;
dict . SetInt ( " pdaOpened " , pdaOpened ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// pdas
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < pdas . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( key , " pda_%i " , i ) ;
dict . Set ( key , pdas [ i ] - > GetName ( ) ) ;
}
dict . SetInt ( " pdas " , pdas . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// video cds
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < videos . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( key , " video_%i " , i ) ;
dict . Set ( key , videos [ i ] - > GetName ( ) ) ;
}
dict . SetInt ( " videos " , videos . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// emails
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < emails . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( key , " email_%i " , i ) ;
dict . Set ( key , emails [ i ] - > GetName ( ) ) ;
}
dict . SetInt ( " emails " , emails . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// weapons
dict . SetInt ( " weapon_bits " , weapons ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dict . SetInt ( " levelTriggers " , levelTriggers . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < levelTriggers . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( key , " levelTrigger_Level_%i " , i ) ;
dict . Set ( key , levelTriggers [ i ] . levelName ) ;
sprintf ( key , " levelTrigger_Trigger_%i " , i ) ;
dict . Set ( key , levelTriggers [ i ] . triggerName ) ;
}
}
/*
= = = = = = = = = = = = = =
idInventory : : RestoreInventory
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : RestoreInventory ( idPlayer * owner , const idDict & dict )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
2012-11-28 15:47:07 +00:00
idDict * item ;
2012-11-26 18:58:24 +00:00
idStr key ;
idStr itemname ;
2012-11-28 15:47:07 +00:00
const idKeyValue * kv ;
const char * name ;
2012-11-26 18:58:24 +00:00
Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// health/armor
maxHealth = dict . GetInt ( " maxhealth " , " 100 " ) ;
armor = dict . GetInt ( " armor " , " 50 " ) ;
maxarmor = dict . GetInt ( " maxarmor " , " 100 " ) ;
deplete_armor = dict . GetInt ( " deplete_armor " , " 0 " ) ;
deplete_rate = dict . GetFloat ( " deplete_rate " , " 2.0 " ) ;
deplete_ammount = dict . GetInt ( " deplete_ammount " , " 1 " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the clip and powerups aren't restored
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ammo
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
2012-11-26 18:58:24 +00:00
name = idWeapon : : GetAmmoNameForNum ( ( ammo_t ) i ) ;
2012-11-28 15:47:07 +00:00
if ( name )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] = dict . GetInt ( name ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//Restore the clip data
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
clip [ i ] = dict . GetInt ( va ( " clip%i " , i ) , " -1 " ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// items
num = dict . GetInt ( " items " ) ;
items . SetNum ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
item = new ( TAG_ENTITY ) idDict ( ) ;
2012-11-26 18:58:24 +00:00
items [ i ] = item ;
sprintf ( itemname , " item_%i " , i ) ;
kv = dict . MatchPrefix ( itemname ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
2012-11-26 18:58:24 +00:00
key = kv - > GetKey ( ) ;
key . Strip ( itemname ) ;
item - > Set ( key , kv - > GetValue ( ) ) ;
kv = dict . MatchPrefix ( itemname , kv ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// pdas viewed
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < 4 ; i + + )
{
pdasViewed [ i ] = dict . GetInt ( va ( " pdasViewed_%i " , i ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
selPDA = dict . GetInt ( " selPDA " ) ;
selEMail = dict . GetInt ( " selEmail " ) ;
selVideo = dict . GetInt ( " selVideo " ) ;
selAudio = dict . GetInt ( " selAudio " ) ;
pdaOpened = dict . GetBool ( " pdaOpened " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// pdas
num = dict . GetInt ( " pdas " ) ;
pdas . SetNum ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( itemname , " pda_%i " , i ) ;
2012-11-28 15:47:07 +00:00
pdas [ i ] = static_cast < const idDeclPDA * > ( declManager - > FindType ( DECL_PDA , dict . GetString ( itemname , " default " ) ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// videos
num = dict . GetInt ( " videos " ) ;
videos . SetNum ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( itemname , " video_%i " , i ) ;
2012-11-28 15:47:07 +00:00
videos [ i ] = static_cast < const idDeclVideo * > ( declManager - > FindType ( DECL_VIDEO , dict . GetString ( itemname , " default " ) ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// emails
num = dict . GetInt ( " emails " ) ;
emails . SetNum ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( itemname , " email_%i " , i ) ;
2012-11-28 15:47:07 +00:00
emails [ i ] = static_cast < const idDeclEmail * > ( declManager - > FindType ( DECL_EMAIL , dict . GetString ( itemname , " default " ) ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// weapons are stored as a number for persistant data, but as strings in the entityDef
weapons = dict . GetInt ( " weapon_bits " , " 0 " ) ;
2012-11-28 15:47:07 +00:00
if ( g_skill . GetInteger ( ) > = 3 | | cvarSystem - > GetCVarBool ( " fs_buildresources " ) )
{
2012-11-26 18:58:24 +00:00
Give ( owner , dict , " weapon " , dict . GetString ( " weapon_nightmare " ) , NULL , false , ITEM_GIVE_FEEDBACK | ITEM_GIVE_UPDATE_STATE ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Give ( owner , dict , " weapon " , dict . GetString ( " weapon " ) , NULL , false , ITEM_GIVE_FEEDBACK | ITEM_GIVE_UPDATE_STATE ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
num = dict . GetInt ( " levelTriggers " ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
sprintf ( itemname , " levelTrigger_Level_%i " , i ) ;
idLevelTriggerInfo lti ;
lti . levelName = dict . GetString ( itemname ) ;
sprintf ( itemname , " levelTrigger_Trigger_%i " , i ) ;
lti . triggerName = dict . GetString ( itemname ) ;
levelTriggers . Append ( lti ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = =
idInventory : : Save
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( maxHealth ) ;
savefile - > WriteInt ( weapons ) ;
savefile - > WriteInt ( powerups ) ;
savefile - > WriteInt ( armor ) ;
savefile - > WriteInt ( maxarmor ) ;
savefile - > WriteInt ( ammoPredictTime ) ;
savefile - > WriteInt ( deplete_armor ) ;
savefile - > WriteFloat ( deplete_rate ) ;
savefile - > WriteInt ( deplete_ammount ) ;
savefile - > WriteInt ( nextArmorDepleteTime ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( ammo [ i ] . Get ( ) ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( clip [ i ] . Get ( ) ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_POWERUPS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( powerupEndTime [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( items . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < items . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteDict ( items [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( pdasViewed [ 0 ] ) ;
savefile - > WriteInt ( pdasViewed [ 1 ] ) ;
savefile - > WriteInt ( pdasViewed [ 2 ] ) ;
savefile - > WriteInt ( pdasViewed [ 3 ] ) ;
savefile - > WriteInt ( selPDA ) ;
savefile - > WriteInt ( selVideo ) ;
savefile - > WriteInt ( selEMail ) ;
savefile - > WriteInt ( selAudio ) ;
savefile - > WriteBool ( pdaOpened ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( pdas . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < pdas . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( pdas [ i ] - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( pdaSecurity . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < pdaSecurity . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( pdaSecurity [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( videos . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < videos . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( videos [ i ] - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( emails . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < emails . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( emails [ i ] - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( nextItemPickup ) ;
savefile - > WriteInt ( nextItemNum ) ;
savefile - > WriteInt ( onePickupTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( pickupItemNames . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < pickupItemNames . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( pickupItemNames [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( objectiveNames . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < objectiveNames . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteMaterial ( objectiveNames [ i ] . screenshot ) ;
savefile - > WriteString ( objectiveNames [ i ] . text ) ;
savefile - > WriteString ( objectiveNames [ i ] . title ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( levelTriggers . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < levelTriggers . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( levelTriggers [ i ] . levelName ) ;
savefile - > WriteString ( levelTriggers [ i ] . triggerName ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( ammoPulse ) ;
savefile - > WriteBool ( weaponPulse ) ;
savefile - > WriteBool ( armorPulse ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( lastGiveTime ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
savefile - > WriteInt ( rechargeAmmo [ i ] . ammo ) ;
savefile - > WriteInt ( rechargeAmmo [ i ] . rechargeTime ) ;
savefile - > WriteString ( rechargeAmmo [ i ] . ammoName ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = =
idInventory : : Restore
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
int i , num ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( maxHealth ) ;
savefile - > ReadInt ( weapons ) ;
savefile - > ReadInt ( powerups ) ;
savefile - > ReadInt ( armor ) ;
savefile - > ReadInt ( maxarmor ) ;
savefile - > ReadInt ( ammoPredictTime ) ;
savefile - > ReadInt ( deplete_armor ) ;
savefile - > ReadFloat ( deplete_rate ) ;
savefile - > ReadInt ( deplete_ammount ) ;
savefile - > ReadInt ( nextArmorDepleteTime ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
2012-11-26 18:58:24 +00:00
int savedAmmo = 0 ;
savefile - > ReadInt ( savedAmmo ) ;
ammo [ i ] . Set ( savedAmmo ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
2012-11-26 18:58:24 +00:00
int savedClip = 0 ;
savefile - > ReadInt ( savedClip ) ;
clip [ i ] . Set ( savedClip ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_POWERUPS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( powerupEndTime [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
idDict * itemdict = new ( TAG_ENTITY ) idDict ;
2012-11-26 18:58:24 +00:00
savefile - > ReadDict ( itemdict ) ;
items . Append ( itemdict ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// pdas
savefile - > ReadInt ( pdasViewed [ 0 ] ) ;
savefile - > ReadInt ( pdasViewed [ 1 ] ) ;
savefile - > ReadInt ( pdasViewed [ 2 ] ) ;
savefile - > ReadInt ( pdasViewed [ 3 ] ) ;
savefile - > ReadInt ( selPDA ) ;
savefile - > ReadInt ( selVideo ) ;
savefile - > ReadInt ( selEMail ) ;
savefile - > ReadInt ( selAudio ) ;
savefile - > ReadBool ( pdaOpened ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
idStr strPda ;
savefile - > ReadString ( strPda ) ;
2012-11-28 15:47:07 +00:00
pdas . Append ( static_cast < const idDeclPDA * > ( declManager - > FindType ( DECL_PDA , strPda ) ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// pda security clearances
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
idStr invName ;
savefile - > ReadString ( invName ) ;
pdaSecurity . Append ( invName ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// videos
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
idStr strVideo ;
savefile - > ReadString ( strVideo ) ;
2012-11-28 15:47:07 +00:00
videos . Append ( static_cast < const idDeclVideo * > ( declManager - > FindType ( DECL_VIDEO , strVideo ) ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// email
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
idStr strEmail ;
savefile - > ReadString ( strEmail ) ;
2012-11-28 15:47:07 +00:00
emails . Append ( static_cast < const idDeclEmail * > ( declManager - > FindType ( DECL_EMAIL , strEmail ) ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( nextItemPickup ) ;
savefile - > ReadInt ( nextItemNum ) ;
savefile - > ReadInt ( onePickupTime ) ;
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
idStr itemName ;
savefile - > ReadString ( itemName ) ;
pickupItemNames . Append ( itemName ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
idObjectiveInfo obj ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadMaterial ( obj . screenshot ) ;
savefile - > ReadString ( obj . text ) ;
savefile - > ReadString ( obj . title ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
objectiveNames . Append ( obj ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
idLevelTriggerInfo lti ;
savefile - > ReadString ( lti . levelName ) ;
savefile - > ReadString ( lti . triggerName ) ;
levelTriggers . Append ( lti ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( ammoPulse ) ;
savefile - > ReadBool ( weaponPulse ) ;
savefile - > ReadBool ( armorPulse ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( lastGiveTime ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
savefile - > ReadInt ( rechargeAmmo [ i ] . ammo ) ;
savefile - > ReadInt ( rechargeAmmo [ i ] . rechargeTime ) ;
2012-11-26 18:58:24 +00:00
idStr name ;
2012-11-28 15:47:07 +00:00
savefile - > ReadString ( name ) ;
strcpy ( rechargeAmmo [ i ] . ammoName , name ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = =
idInventory : : AmmoIndexForAmmoClass
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ammo_t idInventory : : AmmoIndexForAmmoClass ( const char * ammo_classname ) const
{
2012-11-26 18:58:24 +00:00
return idWeapon : : GetAmmoNumForName ( ammo_classname ) ;
}
/*
= = = = = = = = = = = = = =
idInventory : : AmmoIndexForAmmoClass
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idInventory : : MaxAmmoForAmmoClass ( const idPlayer * owner , const char * ammo_classname ) const
{
2012-11-26 18:58:24 +00:00
return owner - > spawnArgs . GetInt ( va ( " max_%s " , ammo_classname ) , " 0 " ) ;
}
/*
= = = = = = = = = = = = = =
idInventory : : AmmoPickupNameForIndex
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idInventory : : AmmoPickupNameForIndex ( ammo_t ammonum ) const
{
2012-11-26 18:58:24 +00:00
return idWeapon : : GetAmmoPickupNameForNum ( ammonum ) ;
}
/*
= = = = = = = = = = = = = =
idInventory : : WeaponIndexForAmmoClass
mapping could be prepared in the constructor
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idInventory : : WeaponIndexForAmmoClass ( const idDict & spawnArgs , const char * ammo_classname ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
const char * weapon_classname ;
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
2012-11-26 18:58:24 +00:00
weapon_classname = spawnArgs . GetString ( va ( " def_weapon%d " , i ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! weapon_classname )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * decl = gameLocal . FindEntityDef ( weapon_classname , false ) ;
if ( ! decl )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( ammo_classname , decl - > dict . GetString ( " ammoType " ) ) )
{
2012-11-26 18:58:24 +00:00
return i ;
}
}
return - 1 ;
}
/*
= = = = = = = = = = = = = =
idInventory : : AmmoIndexForWeaponClass
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ammo_t idInventory : : AmmoIndexForWeaponClass ( const char * weapon_classname , int * ammoRequired )
{
const idDeclEntityDef * decl = gameLocal . FindEntityDef ( weapon_classname , false ) ;
if ( ! decl )
{
2012-11-26 18:58:24 +00:00
//gameLocal.Error( "Unknown weapon in decl '%s'", weapon_classname );
return 0 ;
}
2012-11-28 15:47:07 +00:00
if ( ammoRequired )
{
2012-11-26 18:58:24 +00:00
* ammoRequired = decl - > dict . GetInt ( " ammoRequired " ) ;
}
ammo_t ammo_i = AmmoIndexForAmmoClass ( decl - > dict . GetString ( " ammoType " ) ) ;
return ammo_i ;
}
/*
= = = = = = = = = = = = = =
idInventory : : AddPickupName
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : AddPickupName ( const char * name , idPlayer * owner ) //_D3XP
{
2012-11-26 18:58:24 +00:00
int num = pickupItemNames . Num ( ) ;
2012-11-28 15:47:07 +00:00
if ( ( num = = 0 ) | | ( pickupItemNames [ num - 1 ] . Icmp ( name ) ! = 0 ) )
{
if ( idStr : : Cmpn ( name , STRTABLE_ID , STRTABLE_ID_LENGTH ) = = 0 )
{
2012-11-26 18:58:24 +00:00
pickupItemNames . Append ( idLocalization : : GetString ( name ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
pickupItemNames . Append ( name ) ;
}
}
}
/*
= = = = = = = = = = = = = =
idInventory : : Give
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idInventory : : Give ( idPlayer * owner , const idDict & spawnArgs , const char * statname , const char * value ,
idPredictedValue < int > * idealWeapon , bool updateHud , unsigned int giveFlags )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
const char * pos ;
const char * end ;
2012-11-26 18:58:24 +00:00
int len ;
idStr weaponString ;
int max ;
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * weaponDecl ;
2012-11-26 18:58:24 +00:00
bool tookWeapon ;
int amount ;
2012-11-28 15:47:07 +00:00
const char * name ;
if ( ! idStr : : Icmp ( statname , " ammo_bloodstone " ) )
{
i = AmmoIndexForAmmoClass ( statname ) ;
2012-11-26 18:58:24 +00:00
max = MaxAmmoForAmmoClass ( owner , statname ) ;
2012-11-28 15:47:07 +00:00
if ( max < = 0 )
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
//No Max
ammo [ i ] + = atoi ( value ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
//Already at or above the max so don't allow the give
2012-11-28 15:47:07 +00:00
if ( ammo [ i ] . Get ( ) > = max )
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] = max ;
}
return false ;
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
//We were below the max so accept the give but cap it at the max
ammo [ i ] + = atoi ( value ) ;
2012-11-28 15:47:07 +00:00
if ( ammo [ i ] . Get ( ) > max )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] = max ;
}
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmpn ( statname , " ammo_ " , 5 ) )
{
2012-11-26 18:58:24 +00:00
i = AmmoIndexForAmmoClass ( statname ) ;
max = MaxAmmoForAmmoClass ( owner , statname ) ;
2012-11-28 15:47:07 +00:00
if ( ammo [ i ] . Get ( ) > = max )
{
2012-11-26 18:58:24 +00:00
return false ;
}
// Add ammo for the feedback flag because it's predicted.
// If it is a misprediction, the client will be corrected in
// a snapshot.
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
2012-11-26 18:58:24 +00:00
amount = atoi ( value ) ;
2012-11-28 15:47:07 +00:00
if ( amount )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] + = amount ;
2012-11-28 15:47:07 +00:00
if ( ( max > 0 ) & & ( ammo [ i ] . Get ( ) > max ) )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] = max ;
}
ammoPulse = true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
name = AmmoPickupNameForIndex ( i ) ;
2012-11-28 15:47:07 +00:00
if ( idStr : : Length ( name ) )
{
2012-11-26 18:58:24 +00:00
AddPickupName ( name , owner ) ; //_D3XP
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " armor " ) )
{
if ( armor > = maxarmor )
{
2012-11-26 18:58:24 +00:00
return false ; // can't hold any more, so leave the item
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
amount = atoi ( value ) ;
2012-11-28 15:47:07 +00:00
if ( amount )
{
2012-11-26 18:58:24 +00:00
armor + = amount ;
2012-11-28 15:47:07 +00:00
if ( armor > maxarmor )
{
2012-11-26 18:58:24 +00:00
armor = maxarmor ;
}
nextArmorDepleteTime = 0 ;
armorPulse = true ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( idStr : : FindText ( statname , " inclip_ " ) = = 0 )
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
idStr temp = statname ;
2012-11-28 15:47:07 +00:00
i = atoi ( temp . Mid ( 7 , 2 ) ) ;
if ( i ! = - 1 )
{
2012-11-26 18:58:24 +00:00
// set, don't add. not going over the clip size limit.
SetClipAmmoForWeapon ( i , atoi ( value ) ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " invulnerability " ) )
{
2012-11-26 18:58:24 +00:00
owner - > GivePowerUp ( INVULNERABILITY , SEC2MS ( atof ( value ) ) , giveFlags ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " helltime " ) )
{
2012-11-26 18:58:24 +00:00
owner - > GivePowerUp ( HELLTIME , SEC2MS ( atof ( value ) ) , giveFlags ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " envirosuit " ) )
{
2012-11-26 18:58:24 +00:00
owner - > GivePowerUp ( ENVIROSUIT , SEC2MS ( atof ( value ) ) , giveFlags ) ;
owner - > GivePowerUp ( ENVIROTIME , SEC2MS ( atof ( value ) ) , giveFlags ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " berserk " ) )
{
2012-11-26 18:58:24 +00:00
owner - > GivePowerUp ( BERSERK , SEC2MS ( atof ( value ) ) , giveFlags ) ;
2012-11-28 15:47:07 +00:00
//} else if ( !idStr::Icmp( statname, "haste" ) ) {
// owner->GivePowerUp( HASTE, SEC2MS( atof( value ) ) );
}
else if ( ! idStr : : Icmp ( statname , " adrenaline " ) )
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
GivePowerUp ( owner , ADRENALINE , SEC2MS ( atof ( value ) ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " mega " ) )
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
GivePowerUp ( owner , MEGAHEALTH , SEC2MS ( atof ( value ) ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " weapon " ) )
{
2012-11-26 18:58:24 +00:00
tookWeapon = false ;
2012-11-28 15:47:07 +00:00
for ( pos = value ; pos ! = NULL ; pos = end )
{
2012-11-26 18:58:24 +00:00
end = strchr ( pos , ' , ' ) ;
2012-11-28 15:47:07 +00:00
if ( end )
{
2012-11-26 18:58:24 +00:00
len = end - pos ;
end + + ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
len = strlen ( pos ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStr weaponName ( pos , 0 , len ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the number of the matching weapon name
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
if ( weaponName = = spawnArgs . GetString ( va ( " def_weapon%d " , i ) ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( i > = MAX_WEAPONS )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Unknown weapon '%s' " , weaponName . c_str ( ) ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// cache the media for this weapon
weaponDecl = gameLocal . FindEntityDef ( weaponName , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't pickup "no ammo" weapon types twice
// not for D3 SP .. there is only one case in the game where you can get a no ammo
// weapon when you might already have it, in that case it is more conistent to pick it up
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & ( weapons & ( 1 < < i ) ) & & ( weaponDecl ! = NULL ) & & ! weaponDecl - > dict . GetInt ( " ammoRequired " ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) | | ( weaponName = = " weapon_fists " ) | | ( weaponName = = " weapon_soulcube " ) )
{
if ( ( weapons & ( 1 < < i ) ) = = 0 | | common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
tookWeapon = true ;
// This is done during "feedback" so that clients can predict the ideal weapon.
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
idLobbyBase & lobby = session - > GetActingGameStateLobbyBase ( ) ;
lobbyUserID_t & lobbyUserID = gameLocal . lobbyUserIDs [ owner - > entityNumber ] ;
if ( lobby . GetLobbyUserWeaponAutoSwitch ( lobbyUserID ) & & idealWeapon ! = NULL & & i ! = owner - > weapon_bloodstone_active1 & & i ! = owner - > weapon_bloodstone_active2 & & i ! = owner - > weapon_bloodstone_active3 )
{
2012-11-26 18:58:24 +00:00
idealWeapon - > Set ( i ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
if ( updateHud & & lastGiveTime + 1000 < gameLocal . time )
{
if ( owner - > hud )
{
2012-11-26 18:58:24 +00:00
owner - > hud - > GiveWeapon ( owner , i ) ;
}
lastGiveTime = gameLocal . time ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weaponPulse = true ;
weapons | = ( 1 < < i ) ;
2012-11-28 15:47:07 +00:00
if ( weaponName ! = " weapon_pda " )
{
for ( int index = 0 ; index < NUM_QUICK_SLOTS ; + + index )
{
if ( owner - > GetQuickSlot ( index ) = = - 1 )
{
2012-11-26 18:58:24 +00:00
owner - > SetQuickSlot ( index , i ) ;
break ;
}
}
}
}
}
}
}
return tookWeapon ;
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " item " ) | | ! idStr : : Icmp ( statname , " icon " ) | | ! idStr : : Icmp ( statname , " name " ) )
{
2012-11-26 18:58:24 +00:00
// ignore these as they're handled elsewhere
return false ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// unknown item
gameLocal . Warning ( " Unknown stat '%s' added to player's inventory " , statname ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = =
idInventoy : : Drop
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : Drop ( const idDict & spawnArgs , const char * weapon_classname , int weapon_index )
{
2012-11-26 18:58:24 +00:00
// remove the weapon bit
// also remove the ammo associated with the weapon as we pushed it in the item
assert ( weapon_index ! = - 1 | | weapon_classname ) ;
2012-11-28 15:47:07 +00:00
if ( weapon_index = = - 1 )
{
for ( weapon_index = 0 ; weapon_index < MAX_WEAPONS ; weapon_index + + )
{
if ( ! idStr : : Icmp ( weapon_classname , spawnArgs . GetString ( va ( " def_weapon%d " , weapon_index ) ) ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( weapon_index > = MAX_WEAPONS )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Unknown weapon '%s' " , weapon_classname ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( ! weapon_classname )
{
2012-11-26 18:58:24 +00:00
weapon_classname = spawnArgs . GetString ( va ( " def_weapon%d " , weapon_index ) ) ;
}
weapons & = ( 0xffffffff ^ ( 1 < < weapon_index ) ) ;
ammo_t ammo_i = AmmoIndexForWeaponClass ( weapon_classname , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( ammo_i & & ammo_i < AMMO_NUMTYPES )
{
2012-11-26 18:58:24 +00:00
clip [ weapon_index ] = - 1 ;
ammo [ ammo_i ] = 0 ;
}
}
/*
= = = = = = = = = = = = = = =
idInventory : : HasAmmo
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idInventory : : HasAmmo ( ammo_t type , int amount )
{
if ( ( type = = 0 ) | | ! amount )
{
2012-11-26 18:58:24 +00:00
// always allow weapons that don't use ammo to fire
return - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we have infinite ammo
2012-11-28 15:47:07 +00:00
if ( ammo [ type ] . Get ( ) < 0 )
{
2012-11-26 18:58:24 +00:00
return - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// return how many shots we can fire
return ammo [ type ] . Get ( ) / amount ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idInventory : : HasAmmo
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idInventory : : HasAmmo ( const char * weapon_classname , bool includeClip , idPlayer * owner ) //_D3XP
{
2012-11-26 18:58:24 +00:00
int ammoRequired ;
ammo_t ammo_i = AmmoIndexForWeaponClass ( weapon_classname , & ammoRequired ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int ammoCount = HasAmmo ( ammo_i , ammoRequired ) ;
2012-11-28 15:47:07 +00:00
if ( includeClip & & owner )
{
ammoCount + = Max ( 0 , clip [ owner - > SlotForWeapon ( weapon_classname ) ] . Get ( ) ) ;
2012-11-26 18:58:24 +00:00
}
return ammoCount ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idInventory : : HasEmptyClipCannotRefill
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idInventory : : HasEmptyClipCannotRefill ( const char * weapon_classname , idPlayer * owner )
{
int clipSize = clip [ owner - > SlotForWeapon ( weapon_classname ) ] . Get ( ) ;
if ( clipSize )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * decl = gameLocal . FindEntityDef ( weapon_classname , false ) ;
if ( decl = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Unknown weapon in decl '%s' " , weapon_classname ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
int minclip = decl - > dict . GetInt ( " minclipsize " ) ;
if ( ! minclip )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ammo_t ammo_i = AmmoIndexForAmmoClass ( decl - > dict . GetString ( " ammoType " ) ) ;
int ammoRequired = decl - > dict . GetInt ( " ammoRequired " ) ;
int ammoCount = HasAmmo ( ammo_i , ammoRequired ) ;
2012-11-28 15:47:07 +00:00
if ( ammoCount < minclip )
{
2012-11-26 18:58:24 +00:00
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = =
idInventory : : UseAmmo
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idInventory : : UseAmmo ( ammo_t type , int amount )
{
if ( g_infiniteAmmo . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
if ( ! HasAmmo ( type , amount ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// take an ammo away if not infinite
2012-11-28 15:47:07 +00:00
if ( ammo [ type ] . Get ( ) > = 0 )
{
2012-11-26 18:58:24 +00:00
const int currentAmmo = GetInventoryAmmoForType ( type ) ;
SetInventoryAmmoForType ( type , currentAmmo - amount ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = =
idInventory : : UpdateArmor
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : UpdateArmor ( )
{
if ( deplete_armor ! = 0.0f & & deplete_armor < armor )
{
if ( ! nextArmorDepleteTime )
{
2012-11-26 18:58:24 +00:00
nextArmorDepleteTime = gameLocal . time + deplete_rate * 1000 ;
2012-11-28 15:47:07 +00:00
}
else if ( gameLocal . time > nextArmorDepleteTime )
{
2012-11-26 18:58:24 +00:00
armor - = deplete_ammount ;
2012-11-28 15:47:07 +00:00
if ( armor < deplete_armor )
{
2012-11-26 18:58:24 +00:00
armor = deplete_armor ;
}
nextArmorDepleteTime = gameLocal . time + deplete_rate * 1000 ;
}
}
}
/*
= = = = = = = = = = = = = = =
idInventory : : InitRechargeAmmo
= = = = = = = = = = = = = = =
* Loads any recharge ammo definitions from the ammo_types entity definitions .
*/
2012-11-28 15:47:07 +00:00
void idInventory : : InitRechargeAmmo ( idPlayer * owner )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
memset ( rechargeAmmo , 0 , sizeof ( rechargeAmmo ) ) ;
const idKeyValue * kv = owner - > spawnArgs . MatchPrefix ( " ammorecharge_ " ) ;
while ( kv )
{
2012-11-26 18:58:24 +00:00
idStr key = kv - > GetKey ( ) ;
2012-11-28 15:47:07 +00:00
idStr ammoname = key . Right ( key . Length ( ) - strlen ( " ammorecharge_ " ) ) ;
int ammoType = AmmoIndexForAmmoClass ( ammoname ) ;
rechargeAmmo [ ammoType ] . ammo = ( atof ( kv - > GetValue ( ) . c_str ( ) ) * 1000 ) ;
strcpy ( rechargeAmmo [ ammoType ] . ammoName , ammoname ) ;
2012-11-26 18:58:24 +00:00
kv = owner - > spawnArgs . MatchPrefix ( " ammorecharge_ " , kv ) ;
}
}
/*
= = = = = = = = = = = = = = =
idInventory : : RechargeAmmo
= = = = = = = = = = = = = = =
* Called once per frame to update any ammo amount for ammo types that recharge .
*/
2012-11-28 15:47:07 +00:00
void idInventory : : RechargeAmmo ( idPlayer * owner )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
if ( rechargeAmmo [ i ] . ammo > 0 )
{
if ( ! rechargeAmmo [ i ] . rechargeTime )
{
2012-11-26 18:58:24 +00:00
//Initialize the recharge timer.
rechargeAmmo [ i ] . rechargeTime = gameLocal . time ;
}
int elapsed = gameLocal . time - rechargeAmmo [ i ] . rechargeTime ;
2012-11-28 15:47:07 +00:00
if ( elapsed > = rechargeAmmo [ i ] . ammo )
{
int intervals = ( gameLocal . time - rechargeAmmo [ i ] . rechargeTime ) / rechargeAmmo [ i ] . ammo ;
2012-11-26 18:58:24 +00:00
ammo [ i ] + = intervals ;
2012-11-28 15:47:07 +00:00
int max = MaxAmmoForAmmoClass ( owner , rechargeAmmo [ i ] . ammoName ) ;
if ( max > 0 )
{
if ( ammo [ i ] . Get ( ) > max )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] = max ;
}
}
2012-11-28 15:47:07 +00:00
rechargeAmmo [ i ] . rechargeTime + = intervals * rechargeAmmo [ i ] . ammo ;
2012-11-26 18:58:24 +00:00
}
}
}
}
/*
= = = = = = = = = = = = = = =
idInventory : : CanGive
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idInventory : : CanGive ( idPlayer * owner , const idDict & spawnArgs , const char * statname , const char * value )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( statname , " ammo_bloodstone " ) )
{
int max = MaxAmmoForAmmoClass ( owner , statname ) ;
int i = AmmoIndexForAmmoClass ( statname ) ;
if ( max < = 0 )
{
2012-11-26 18:58:24 +00:00
//No Max
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
//Already at or above the max so don't allow the give
2012-11-28 15:47:07 +00:00
if ( ammo [ i ] . Get ( ) > = max )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] = max ;
return false ;
}
return true ;
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " item " ) | | ! idStr : : Icmp ( statname , " icon " ) | | ! idStr : : Icmp ( statname , " name " ) )
{
2012-11-26 18:58:24 +00:00
// ignore these as they're handled elsewhere
//These items should not be considered as succesful gives because it messes up the max ammo items
return false ;
}
return true ;
}
/*
= = = = = = = = = = = = = = =
idInventory : : SetClipAmmoForWeapon
Ammo is predicted on clients . This function ensures the frame the prediction occurs
is stored so the predicted value doesn ' t get overwritten by snapshots . Of course
the snapshot - reading function must check this value .
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : SetClipAmmoForWeapon ( const int weapon , const int amount )
{
2012-11-26 18:58:24 +00:00
clip [ weapon ] = amount ;
}
/*
= = = = = = = = = = = = = = =
idInventory : : SetInventoryAmmoForType
Ammo is predicted on clients . This function ensures the frame the prediction occurs
is stored so the predicted value doesn ' t get overwritten by snapshots . Of course
the snapshot - reading function must check this value .
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : SetInventoryAmmoForType ( int ammoType , const int amount )
{
2012-11-26 18:58:24 +00:00
ammo [ ammoType ] = amount ;
}
/*
= = = = = = = = = = = = = = =
idInventory : : GetClipAmmoForWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idInventory : : GetClipAmmoForWeapon ( const int weapon ) const
{
2012-11-26 18:58:24 +00:00
return clip [ weapon ] . Get ( ) ;
}
/*
= = = = = = = = = = = = = = =
idInventory : : GetInventoryAmmoForType
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idInventory : : GetInventoryAmmoForType ( const int ammoType ) const
{
2012-11-26 18:58:24 +00:00
return ammo [ ammoType ] . Get ( ) ;
}
/*
= = = = = = = = = = = = = = =
idInventory : : WriteAmmoToSnapshot
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : WriteAmmoToSnapshot ( idBitMsg & msg ) const
{
for ( int i = 0 ; i < AMMO_NUMTYPES ; i + + )
{
2012-11-26 18:58:24 +00:00
msg . WriteBits ( ammo [ i ] . Get ( ) , ASYNC_PLAYER_INV_AMMO_BITS ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_WEAPONS ; i + + )
{
2012-11-26 18:58:24 +00:00
msg . WriteBits ( clip [ i ] . Get ( ) , ASYNC_PLAYER_INV_CLIP_BITS ) ;
}
}
/*
= = = = = = = = = = = = = = =
idInventory : : ReadAmmoFromSnapshot
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : ReadAmmoFromSnapshot ( const idBitMsg & msg , const int ownerEntityNumber )
{
for ( int i = 0 ; i < ammo . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
const int snapshotAmmo = msg . ReadBits ( ASYNC_PLAYER_INV_AMMO_BITS ) ;
ammo [ i ] . UpdateFromSnapshot ( snapshotAmmo , ownerEntityNumber ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < clip . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
const int snapshotClip = msg . ReadBits ( ASYNC_PLAYER_INV_CLIP_BITS ) ;
clip [ i ] . UpdateFromSnapshot ( snapshotClip , ownerEntityNumber ) ;
}
}
/*
= = = = = = = = = = = = = = =
idInventory : : ReadAmmoFromSnapshot
Doesn ' t really matter what remote client ' s ammo count is , so just set it to 999.
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idInventory : : SetRemoteClientAmmo ( const int ownerEntityNumber )
{
for ( int i = 0 ; i < ammo . Num ( ) ; + + i )
{
2012-11-26 18:58:24 +00:00
ammo [ i ] . UpdateFromSnapshot ( 999 , ownerEntityNumber ) ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : idPlayer
= = = = = = = = = = = = = =
*/
idPlayer : : idPlayer ( ) :
previousViewQuat ( 0.0f , 0.0f , 0.0f , 1.0f ) ,
nextViewQuat ( 0.0f , 0.0f , 0.0f , 1.0f ) ,
idealWeapon ( - 1 ) ,
serverOverridePositionTime ( 0 ) ,
2012-11-28 15:47:07 +00:00
clientFireCount ( 0 )
{
2012-11-26 18:58:24 +00:00
noclip = false ;
godmode = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnAnglesSet = false ;
spawnAngles = ang_zero ;
viewAngles = ang_zero ;
cmdAngles = ang_zero ;
independentWeaponPitchAngle = 0.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
oldButtons = 0 ;
buttonMask = 0 ;
oldImpulseSequence = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastHitTime = 0 ;
lastSndHitTime = 0 ;
lastSavingThrowTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
laserSightHandle = - 1 ;
memset ( & laserSightRenderEntity , 0 , sizeof ( laserSightRenderEntity ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weapon = NULL ;
primaryObjective = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hudManager = new idMenuHandler_HUD ( ) ;
hud = NULL ;
objectiveSystemOpen = false ;
memset ( quickSlot , - 1 , sizeof ( quickSlot ) ) ;
2012-11-28 15:47:07 +00:00
pdaMenu = new ( TAG_SWF ) idMenuHandler_PDA ( ) ;
2012-11-26 18:58:24 +00:00
pdaVideoMat = NULL ;
mpMessages = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mountedObject = NULL ;
enviroSuitLight = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
heartRate = BASE_HEARTRATE ;
heartInfo . Init ( 0 , 0 , 0 , 0 ) ;
lastHeartAdjust = 0 ;
lastHeartBeat = 0 ;
lastDmgTime = 0 ;
deathClearContentsTime = 0 ;
lastArmorPulse = - 10000 ;
stamina = 0.0f ;
healthPool = 0.0f ;
nextHealthPulse = 0 ;
healthPulse = false ;
nextHealthTake = 0 ;
healthTake = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
forceScoreBoard = false ;
forceRespawn = false ;
spectating = false ;
spectator = 0 ;
wantSpectate = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
carryingFlag = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastHitToggle = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
minRespawnTime = 0 ;
maxRespawnTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
firstPersonViewOrigin = vec3_zero ;
firstPersonViewAxis = mat3_identity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hipJoint = INVALID_JOINT ;
chestJoint = INVALID_JOINT ;
headJoint = INVALID_JOINT ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bobFoot = 0 ;
bobFrac = 0.0f ;
bobfracsin = 0.0f ;
bobCycle = 0 ;
xyspeed = 0.0f ;
stepUpTime = 0 ;
stepUpDelta = 0.0f ;
idealLegsYaw = 0.0f ;
legsYaw = 0.0f ;
legsForward = true ;
oldViewYaw = 0.0f ;
viewBobAngles = ang_zero ;
viewBob = vec3_zero ;
landChange = 0 ;
landTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
currentWeapon = - 1 ;
previousWeapon = - 1 ;
weaponSwitchTime = 0 ;
weaponEnabled = true ;
weapon_soulcube = - 1 ;
weapon_pda = - 1 ;
weapon_fists = - 1 ;
weapon_chainsaw = - 1 ;
weapon_bloodstone = - 1 ;
weapon_bloodstone_active1 = - 1 ;
weapon_bloodstone_active2 = - 1 ;
weapon_bloodstone_active3 = - 1 ;
harvest_lock = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hudPowerup = - 1 ;
lastHudPowerup = - 1 ;
hudPowerupDuration = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
skinIndex = 0 ;
skin = NULL ;
powerUpSkin = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numProjectileKills = 0 ;
numProjectilesFired = 0 ;
numProjectileHits = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
airless = false ;
airMsec = 0 ;
lastAirDamage = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gibDeath = false ;
gibsLaunched = false ;
gibsDir = vec3_zero ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
zoomFov . Init ( 0 , 0 , 0 , 0 ) ;
centerView . Init ( 0 , 0 , 0 , 0 ) ;
fxFov = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
influenceFov = 0 ;
influenceActive = 0 ;
influenceRadius = 0.0f ;
influenceEntity = NULL ;
influenceMaterial = NULL ;
influenceSkin = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
privateCameraView = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( loggedViewAngles , 0 , sizeof ( loggedViewAngles ) ) ;
memset ( loggedAccel , 0 , sizeof ( loggedAccel ) ) ;
currentLoggedAccel = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
focusTime = 0 ;
focusGUIent = NULL ;
focusUI = NULL ;
focusCharacter = NULL ;
talkCursor = 0 ;
focusVehicle = NULL ;
cursor = NULL ;
oldMouseX = 0 ;
oldMouseY = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastDamageDef = 0 ;
lastDamageDir = vec3_zero ;
lastDamageLocation = 0 ;
smoothedFrame = 0 ;
smoothedOriginUpdated = false ;
smoothedOrigin = vec3_zero ;
smoothedAngles = ang_zero ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fl . networkSync = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
doingDeathSkin = false ;
weaponGone = false ;
useInitialSpawns = false ;
tourneyRank = 0 ;
lastSpectateTeleport = 0 ;
tourneyLine = 0 ;
hiddenWeapon = false ;
tipUp = false ;
objectiveUp = false ;
teleportEntity = NULL ;
teleportKiller = - 1 ;
respawning = false ;
leader = false ;
lastSpectateChange = 0 ;
lastTeleFX = - 9999 ;
weaponCatchup = false ;
clientFireCount = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
MPAim = - 1 ;
lastMPAim = - 1 ;
lastMPAimTime = 0 ;
MPAimFadeTime = 0 ;
MPAimHighlight = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnedTime = 0 ;
lastManOver = false ;
lastManPlayAgain = false ;
lastManPresent = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
isTelefragged = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
isLagged = false ;
isChatting = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
selfSmooth = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
playedTimeSecs = 0 ;
playedTimeResidual = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ResetControllerShake ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( pdaHasBeenRead , 0 , sizeof ( pdaHasBeenRead ) ) ;
memset ( videoHasBeenViewed , 0 , sizeof ( videoHasBeenViewed ) ) ;
memset ( audioHasBeenHeard , 0 , sizeof ( audioHasBeenHeard ) ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : LinkScriptVariables
set up conditions for animation
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : LinkScriptVariables ( )
{
AI_FORWARD . LinkTo ( scriptObject , " AI_FORWARD " ) ;
AI_BACKWARD . LinkTo ( scriptObject , " AI_BACKWARD " ) ;
AI_STRAFE_LEFT . LinkTo ( scriptObject , " AI_STRAFE_LEFT " ) ;
AI_STRAFE_RIGHT . LinkTo ( scriptObject , " AI_STRAFE_RIGHT " ) ;
AI_ATTACK_HELD . LinkTo ( scriptObject , " AI_ATTACK_HELD " ) ;
AI_WEAPON_FIRED . LinkTo ( scriptObject , " AI_WEAPON_FIRED " ) ;
AI_JUMP . LinkTo ( scriptObject , " AI_JUMP " ) ;
AI_DEAD . LinkTo ( scriptObject , " AI_DEAD " ) ;
AI_CROUCH . LinkTo ( scriptObject , " AI_CROUCH " ) ;
AI_ONGROUND . LinkTo ( scriptObject , " AI_ONGROUND " ) ;
AI_ONLADDER . LinkTo ( scriptObject , " AI_ONLADDER " ) ;
AI_HARDLANDING . LinkTo ( scriptObject , " AI_HARDLANDING " ) ;
AI_SOFTLANDING . LinkTo ( scriptObject , " AI_SOFTLANDING " ) ;
AI_RUN . LinkTo ( scriptObject , " AI_RUN " ) ;
AI_PAIN . LinkTo ( scriptObject , " AI_PAIN " ) ;
AI_RELOAD . LinkTo ( scriptObject , " AI_RELOAD " ) ;
AI_TELEPORT . LinkTo ( scriptObject , " AI_TELEPORT " ) ;
AI_TURN_LEFT . LinkTo ( scriptObject , " AI_TURN_LEFT " ) ;
AI_TURN_RIGHT . LinkTo ( scriptObject , " AI_TURN_RIGHT " ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = =
idPlayer : : SetupWeaponEntity
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetupWeaponEntity ( )
{
2012-11-26 18:58:24 +00:00
int w ;
2012-11-28 15:47:07 +00:00
const char * weap ;
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
// get rid of old weapon
weapon . GetEntity ( ) - > Clear ( ) ;
currentWeapon = - 1 ;
2012-11-28 15:47:07 +00:00
}
else if ( ! common - > IsClient ( ) )
{
weapon = static_cast < idWeapon * > ( gameLocal . SpawnEntityType ( idWeapon : : Type , NULL ) ) ;
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > SetOwner ( this ) ;
currentWeapon = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// flashlight
2012-11-28 15:47:07 +00:00
flashlight = static_cast < idWeapon * > ( gameLocal . SpawnEntityType ( idWeapon : : Type , NULL ) ) ;
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > SetFlashlightOwner ( this ) ;
//FlashlightOff();
}
2012-11-28 15:47:07 +00:00
for ( w = 0 ; w < MAX_WEAPONS ; w + + )
{
2012-11-26 18:58:24 +00:00
weap = spawnArgs . GetString ( va ( " def_weapon%d " , w ) ) ;
2012-12-11 22:48:55 +00:00
if ( weap ! = NULL & & * weap ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
idWeapon : : CacheWeapon ( weap ) ;
}
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : Init
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Init ( )
{
const char * value ;
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
noclip = false ;
godmode = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
oldButtons = 0 ;
oldImpulseSequence = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
currentWeapon = - 1 ;
idealWeapon = - 1 ;
previousWeapon = - 1 ;
weaponSwitchTime = 0 ;
weaponEnabled = true ;
weapon_soulcube = SlotForWeapon ( " weapon_soulcube " ) ;
weapon_pda = SlotForWeapon ( " weapon_pda " ) ;
weapon_fists = SlotForWeapon ( " weapon_fists " ) ;
weapon_flashlight = SlotForWeapon ( " weapon_flashlight " ) ;
weapon_chainsaw = SlotForWeapon ( " weapon_chainsaw " ) ;
weapon_bloodstone = SlotForWeapon ( " weapon_bloodstone_passive " ) ;
weapon_bloodstone_active1 = SlotForWeapon ( " weapon_bloodstone_active1 " ) ;
weapon_bloodstone_active2 = SlotForWeapon ( " weapon_bloodstone_active2 " ) ;
weapon_bloodstone_active3 = SlotForWeapon ( " weapon_bloodstone_active3 " ) ;
harvest_lock = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastDmgTime = 0 ;
lastArmorPulse = - 10000 ;
lastHeartAdjust = 0 ;
lastHeartBeat = 0 ;
heartInfo . Init ( 0 , 0 , 0 , 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bobCycle = 0 ;
bobFrac = 0.0f ;
landChange = 0 ;
landTime = 0 ;
zoomFov . Init ( 0 , 0 , 0 , 0 ) ;
centerView . Init ( 0 , 0 , 0 , 0 ) ;
fxFov = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
influenceFov = 0 ;
influenceActive = 0 ;
influenceRadius = 0.0f ;
influenceEntity = NULL ;
influenceMaterial = NULL ;
influenceSkin = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mountedObject = NULL ;
2012-11-28 15:47:07 +00:00
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > PostEventMS ( & EV_Remove , 0 ) ;
}
enviroSuitLight = NULL ;
healthRecharge = false ;
lastHealthRechargeTime = 0 ;
rechargeSpeed = 500 ;
new_g_damageScale = 1.f ;
bloomEnabled = false ;
bloomSpeed = 1.f ;
bloomIntensity = - 0.01f ;
2012-11-28 15:47:07 +00:00
inventory . InitRechargeAmmo ( this ) ;
2012-11-26 18:58:24 +00:00
hudPowerup = - 1 ;
lastHudPowerup = - 1 ;
hudPowerupDuration = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
currentLoggedAccel = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
focusTime = 0 ;
focusGUIent = NULL ;
focusUI = NULL ;
focusCharacter = NULL ;
talkCursor = 0 ;
focusVehicle = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove any damage effects
playerView . ClearEffects ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// damage values
fl . takedamage = true ;
ClearPain ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// restore persistent data
RestorePersistantInfo ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bobCycle = 0 ;
stamina = 0.0f ;
healthPool = 0.0f ;
nextHealthPulse = 0 ;
healthPulse = false ;
nextHealthTake = 0 ;
healthTake = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetupWeaponEntity ( ) ;
currentWeapon = - 1 ;
previousWeapon = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
heartRate = BASE_HEARTRATE ;
AdjustHeartRate ( BASE_HEARTRATE , 0.0f , 0.0f , true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idealLegsYaw = 0.0f ;
legsYaw = 0.0f ;
legsForward = true ;
oldViewYaw = 0.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the pm_ cvars
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) | | common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
kv = spawnArgs . MatchPrefix ( " pm_ " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
2012-11-26 18:58:24 +00:00
cvarSystem - > SetCVarString ( kv - > GetKey ( ) , kv - > GetValue ( ) ) ;
kv = spawnArgs . MatchPrefix ( " pm_ " , kv ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// disable stamina on hell levels
2012-11-28 15:47:07 +00:00
if ( gameLocal . world & & gameLocal . world - > spawnArgs . GetBool ( " no_stamina " ) )
{
2012-11-26 18:58:24 +00:00
pm_stamina . SetFloat ( 0.0f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stamina always initialized to maximum
stamina = pm_stamina . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// air always initialized to maximum too
airMsec = pm_airMsec . GetFloat ( ) ;
airless = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gibDeath = false ;
gibsLaunched = false ;
gibsDir . Zero ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the gravity
physicsObj . SetGravity ( gameLocal . GetGravity ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// start out standing
SetEyeHeight ( pm_normalviewheight . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stepUpTime = 0 ;
stepUpDelta = 0.0f ;
viewBobAngles . Zero ( ) ;
viewBob . Zero ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
value = spawnArgs . GetString ( " model " ) ;
2012-11-28 15:47:07 +00:00
if ( value ! = NULL & & ( * value ! = 0 ) )
{
2012-11-26 18:58:24 +00:00
SetModel ( value ) ;
}
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > SetCursorState ( this , CURSOR_TALK , 0 ) ;
hud - > SetCursorState ( this , CURSOR_IN_COMBAT , 1 ) ;
hud - > SetCursorState ( this , CURSOR_ITEM , 0 ) ;
hud - > SetCursorState ( this , CURSOR_GRABBER , 0 ) ;
hud - > SetCursorState ( this , CURSOR_NONE , 0 ) ;
hud - > UpdateCursorState ( ) ;
2012-11-28 15:47:07 +00:00
}
if ( ( common - > IsMultiplayer ( ) | | g_testDeath . GetBool ( ) ) & & skin )
{
2012-11-26 18:58:24 +00:00
SetSkin ( skin ) ;
renderEntity . shaderParms [ 6 ] = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( spawnArgs . GetString ( " spawn_skin " , NULL , & value ) )
{
2012-11-26 18:58:24 +00:00
skin = declManager - > FindSkin ( value ) ;
SetSkin ( skin ) ;
renderEntity . shaderParms [ 6 ] = 0.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
value = spawnArgs . GetString ( " bone_hips " , " " ) ;
hipJoint = animator . GetJointHandle ( value ) ;
2012-11-28 15:47:07 +00:00
if ( hipJoint = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Joint '%s' not found for 'bone_hips' on '%s' " , value , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
value = spawnArgs . GetString ( " bone_chest " , " " ) ;
chestJoint = animator . GetJointHandle ( value ) ;
2012-11-28 15:47:07 +00:00
if ( chestJoint = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Joint '%s' not found for 'bone_chest' on '%s' " , value , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
value = spawnArgs . GetString ( " bone_head " , " " ) ;
headJoint = animator . GetJointHandle ( value ) ;
2012-11-28 15:47:07 +00:00
if ( headJoint = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Joint '%s' not found for 'bone_head' on '%s' " , value , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// initialize the script variables
AI_FORWARD = false ;
AI_BACKWARD = false ;
AI_STRAFE_LEFT = false ;
AI_STRAFE_RIGHT = false ;
AI_ATTACK_HELD = false ;
AI_WEAPON_FIRED = false ;
AI_JUMP = false ;
AI_DEAD = false ;
AI_CROUCH = false ;
AI_ONGROUND = true ;
AI_ONLADDER = false ;
AI_HARDLANDING = false ;
AI_SOFTLANDING = false ;
AI_RUN = false ;
AI_PAIN = false ;
AI_RELOAD = false ;
AI_TELEPORT = false ;
AI_TURN_LEFT = false ;
AI_TURN_RIGHT = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset the script object
ConstructScriptObject ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// execute the script so the script object's constructor takes effect immediately
scriptThread - > Execute ( ) ;
forceScoreBoard = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
privateCameraView = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastSpectateChange = 0 ;
lastTeleFX = - 9999 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hiddenWeapon = false ;
tipUp = false ;
objectiveUp = false ;
teleportEntity = NULL ;
teleportKiller = - 1 ;
leader = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetPrivateCameraView ( NULL ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
MPAim = - 1 ;
lastMPAim = - 1 ;
lastMPAimTime = 0 ;
MPAimFadeTime = 0 ;
MPAimHighlight = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//isChatting = false;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
achievementManager . Init ( this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
flashlightBattery = flashlight_batteryDrainTimeMS . GetInteger ( ) ; // fully charged
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
aimAssist . Init ( this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// laser sight for 3DTV
memset ( & laserSightRenderEntity , 0 , sizeof ( laserSightRenderEntity ) ) ;
laserSightRenderEntity . hModel = renderModelManager - > FindModel ( " _BEAM " ) ;
laserSightRenderEntity . customShader = declManager - > FindMaterial ( " stereoRenderLaserSight " ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : Spawn
Prepare any resources used by the player .
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Spawn ( )
{
2012-11-26 18:58:24 +00:00
idStr temp ;
idBounds bounds ;
2012-11-28 15:47:07 +00:00
if ( entityNumber > = MAX_CLIENTS )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " entityNum > MAX_CLIENTS for player. Player may only be spawned with a client. " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// allow thinking during cinematics
cinematic = true ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
// always start in spectating state waiting to be spawned in
// do this before SetClipModel to get the right bounding box
spectating = true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set our collision model
physicsObj . SetSelf ( this ) ;
SetClipModel ( ) ;
physicsObj . SetMass ( spawnArgs . GetFloat ( " mass " , " 100 " ) ) ;
physicsObj . SetContents ( CONTENTS_BODY ) ;
physicsObj . SetClipMask ( MASK_PLAYERSOLID ) ;
SetPhysics ( & physicsObj ) ;
InitAASLocation ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
skin = renderEntity . customSkin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// only the local player needs guis
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) | | IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
// load HUD
2012-11-28 15:47:07 +00:00
if ( hudManager ! = NULL )
{
2012-11-26 18:58:24 +00:00
hudManager - > Initialize ( " hud " , common - > SW ( ) ) ;
hudManager - > ActivateMenu ( true ) ;
hud = hudManager - > GetHud ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load cursor
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " cursor " , " " , temp ) )
{
2012-11-26 18:58:24 +00:00
cursor = uiManager - > FindGui ( temp , true , common - > IsMultiplayer ( ) , common - > IsMultiplayer ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( cursor )
{
2012-11-26 18:58:24 +00:00
cursor - > Activate ( true , gameLocal . time ) ;
}
2012-11-28 15:47:07 +00:00
if ( pdaMenu ! = NULL )
{
2012-11-26 18:58:24 +00:00
pdaMenu - > Initialize ( " pda " , common - > SW ( ) ) ;
}
objectiveSystemOpen = false ;
2012-11-28 15:47:07 +00:00
}
if ( common - > IsMultiplayer ( ) & & mpMessages = = NULL )
{
2012-11-26 18:58:24 +00:00
mpMessages = new idSWF ( " mp_messages " , common - > SW ( ) ) ;
mpMessages - > Activate ( true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetLastHitTime ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load the armor sound feedback
declManager - > FindSound ( " player_sounds_hitArmor " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set up conditions for animation
LinkScriptVariables ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animator . RemoveOriginOffset ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// create combat collision hull for exact collision detection
SetCombatModel ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// init the damage effects
playerView . SetPlayerEntity ( this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// supress model in non-player views, but allow it in mirrors and remote views
2012-11-28 15:47:07 +00:00
renderEntity . suppressSurfaceInViewID = entityNumber + 1 ;
2012-11-26 18:58:24 +00:00
// don't project shadow on self or weapon
renderEntity . noSelfShadow = true ;
2012-11-28 15:47:07 +00:00
idAFAttachment * headEnt = head . GetEntity ( ) ;
if ( headEnt )
{
headEnt - > GetRenderEntity ( ) - > suppressSurfaceInViewID = entityNumber + 1 ;
2012-11-26 18:58:24 +00:00
headEnt - > GetRenderEntity ( ) - > noSelfShadow = true ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
Init ( ) ;
Hide ( ) ; // properly hidden if starting as a spectator
2012-11-28 15:47:07 +00:00
if ( ! common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
// set yourself ready to spawn. idMultiplayerGame will decide when/if appropriate and call SpawnFromSpawnSpot
SetupWeaponEntity ( ) ;
SpawnFromSpawnSpot ( ) ;
forceRespawn = true ;
wantSpectate = true ;
assert ( spectating ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
SetupWeaponEntity ( ) ;
SpawnFromSpawnSpot ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// trigger playtesting item gives, if we didn't get here from a previous level
// the devmap key will be set on the first devmap, but cleared on any level
// transitions
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) & & gameLocal . serverInfo . FindKey ( " devmap " ) )
{
2012-11-26 18:58:24 +00:00
// fire a trigger with the name "devmap"
2012-11-28 15:47:07 +00:00
idEntity * ent = gameLocal . FindEntity ( " devmap " ) ;
if ( ent )
{
2012-11-26 18:58:24 +00:00
ent - > ActivateTargets ( this ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( hud )
{
if ( weapon_soulcube > 0 & & ( inventory . weapons & ( 1 < < weapon_soulcube ) ) )
{
2012-11-26 18:58:24 +00:00
int max_souls = inventory . MaxAmmoForAmmoClass ( this , " ammo_souls " ) ;
2012-11-28 15:47:07 +00:00
if ( inventory . GetInventoryAmmoForType ( idWeapon : : GetAmmoNumForName ( " ammo_souls " ) ) > = max_souls )
{
2012-11-26 18:58:24 +00:00
hud - > SetShowSoulCubeOnLoad ( true ) ;
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( GetPDA ( ) )
{
2012-11-26 18:58:24 +00:00
// Add any emails from the inventory
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < inventory . emails . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
GetPDA ( ) - > AddEmail ( inventory . emails [ i ] ) ;
}
GetPDA ( ) - > SetSecurity ( idLocalization : : GetString ( " #str_00066 " ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) )
{
2012-11-26 18:58:24 +00:00
hiddenWeapon = true ;
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
}
idealWeapon = weapon_fists ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hiddenWeapon = false ;
}
UpdateHudWeapon ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
tipUp = false ;
objectiveUp = false ;
2012-11-28 15:47:07 +00:00
if ( inventory . levelTriggers . Num ( ) )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_Player_LevelTrigger , 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . pdaOpened = false ;
inventory . selPDA = 0 ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
int startingHealth = gameLocal . world - > spawnArgs . GetInt ( " startingHealth " , health ) ;
2012-11-28 15:47:07 +00:00
if ( health > startingHealth )
{
2012-11-26 18:58:24 +00:00
health = startingHealth ;
}
2012-11-28 15:47:07 +00:00
if ( g_skill . GetInteger ( ) < 2 )
{
if ( health < 25 )
{
2012-11-26 18:58:24 +00:00
health = 25 ;
}
2012-11-28 15:47:07 +00:00
if ( g_useDynamicProtection . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
new_g_damageScale = 1.0f ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
new_g_damageScale = 1.0f ;
g_armorProtection . SetFloat ( ( g_skill . GetInteger ( ) < 2 ) ? 0.4f : 0.2f ) ;
2012-11-28 15:47:07 +00:00
if ( g_skill . GetInteger ( ) = = 3 )
{
2012-11-26 18:58:24 +00:00
nextHealthTake = gameLocal . time + g_healthTakeTime . GetInteger ( ) * 1000 ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//Setup the weapon toggle lists
2012-11-28 15:47:07 +00:00
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
kv = spawnArgs . MatchPrefix ( " weapontoggle " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
2012-11-26 18:58:24 +00:00
WeaponToggle_t newToggle ;
2012-11-28 15:47:07 +00:00
strcpy ( newToggle . name , kv - > GetKey ( ) . c_str ( ) ) ;
2012-11-26 18:58:24 +00:00
idStr toggleData = kv - > GetValue ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idLexer src ;
idToken token ;
2012-11-28 15:47:07 +00:00
src . LoadMemory ( toggleData , toggleData . Length ( ) , " toggleData " ) ;
while ( 1 )
{
if ( ! src . ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
int index = atoi ( token . c_str ( ) ) ;
newToggle . toggleList . Append ( index ) ;
2012-11-26 18:58:24 +00:00
//Skip the ,
2012-11-28 15:47:07 +00:00
src . ReadToken ( & token ) ;
2012-11-26 18:58:24 +00:00
}
newToggle . lastUsed = 0 ;
2012-11-28 15:47:07 +00:00
weaponToggles . Set ( newToggle . name , newToggle ) ;
2012-11-26 18:58:24 +00:00
kv = spawnArgs . MatchPrefix ( " weapontoggle " , kv ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_skill . GetInteger ( ) > = 3 | | cvarSystem - > GetCVarBool ( " fs_buildresources " ) )
{
if ( ! WeaponAvailable ( " weapon_bloodstone_passive " ) )
{
GiveInventoryItem ( " weapon_bloodstone_passive " ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ! WeaponAvailable ( " weapon_bloodstone_active1 " ) )
{
GiveInventoryItem ( " weapon_bloodstone_active1 " ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ! WeaponAvailable ( " weapon_bloodstone_active2 " ) )
{
GiveInventoryItem ( " weapon_bloodstone_active2 " ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ! WeaponAvailable ( " weapon_bloodstone_active3 " ) )
{
GiveInventoryItem ( " weapon_bloodstone_active3 " ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bloomEnabled = false ;
bloomSpeed = 1 ;
bloomIntensity = - 0.01f ;
2012-11-28 15:47:07 +00:00
if ( g_demoMode . GetBool ( ) & & weapon . GetEntity ( ) & & weapon . GetEntity ( ) - > AmmoInClip ( ) = = 0 )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > ForceAmmoInClip ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = =
idPlayer : : ~ idPlayer ( )
Release any resources used by the player .
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idPlayer : : ~ idPlayer ( )
{
2012-11-26 18:58:24 +00:00
delete weapon . GetEntity ( ) ;
weapon = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete flashlight . GetEntity ( ) ;
flashlight = NULL ;
2012-11-28 15:47:07 +00:00
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > ProcessEvent ( & EV_Remove ) ;
}
// have to do this here, idMultiplayerGame::DisconnectClient() is too late
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & gameLocal . mpGame . IsGametypeFlagBased ( ) )
{
2012-11-26 18:58:24 +00:00
ReturnFlag ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete hudManager ;
hudManager = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete pdaMenu ;
pdaMenu = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete mpMessages ;
mpMessages = NULL ;
}
/*
= = = = = = = = = = =
idPlayer : : Save
= = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteUsercmd ( usercmd ) ;
playerView . Save ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( noclip ) ;
savefile - > WriteBool ( godmode ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't save spawnAnglesSet, since we'll have to reset them after loading the savegame
savefile - > WriteAngles ( spawnAngles ) ;
savefile - > WriteAngles ( viewAngles ) ;
savefile - > WriteAngles ( cmdAngles ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( buttonMask ) ;
savefile - > WriteInt ( oldButtons ) ;
savefile - > WriteInt ( oldImpulseSequence ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( lastHitTime ) ;
savefile - > WriteInt ( lastSndHitTime ) ;
savefile - > WriteInt ( lastSavingThrowTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// idBoolFields don't need to be saved, just re-linked in Restore
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteObject ( primaryObjective ) ;
inventory . Save ( savefile ) ;
weapon . Save ( savefile ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < NUM_QUICK_SLOTS ; + + i )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( quickSlot [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( weapon_soulcube ) ;
savefile - > WriteInt ( weapon_pda ) ;
savefile - > WriteInt ( weapon_fists ) ;
savefile - > WriteInt ( weapon_flashlight ) ;
savefile - > WriteInt ( weapon_chainsaw ) ;
savefile - > WriteInt ( weapon_bloodstone ) ;
savefile - > WriteInt ( weapon_bloodstone_active1 ) ;
savefile - > WriteInt ( weapon_bloodstone_active2 ) ;
savefile - > WriteInt ( weapon_bloodstone_active3 ) ;
savefile - > WriteBool ( harvest_lock ) ;
savefile - > WriteInt ( hudPowerup ) ;
savefile - > WriteInt ( lastHudPowerup ) ;
savefile - > WriteInt ( hudPowerupDuration ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( heartRate ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteFloat ( heartInfo . GetStartTime ( ) ) ;
savefile - > WriteFloat ( heartInfo . GetDuration ( ) ) ;
savefile - > WriteFloat ( heartInfo . GetStartValue ( ) ) ;
savefile - > WriteFloat ( heartInfo . GetEndValue ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( lastHeartAdjust ) ;
savefile - > WriteInt ( lastHeartBeat ) ;
savefile - > WriteInt ( lastDmgTime ) ;
savefile - > WriteInt ( deathClearContentsTime ) ;
savefile - > WriteBool ( doingDeathSkin ) ;
savefile - > WriteInt ( lastArmorPulse ) ;
savefile - > WriteFloat ( stamina ) ;
savefile - > WriteFloat ( healthPool ) ;
savefile - > WriteInt ( nextHealthPulse ) ;
savefile - > WriteBool ( healthPulse ) ;
savefile - > WriteInt ( nextHealthTake ) ;
savefile - > WriteBool ( healthTake ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( hiddenWeapon ) ;
soulCubeProjectile . Save ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( spectator ) ;
savefile - > WriteBool ( forceScoreBoard ) ;
savefile - > WriteBool ( forceRespawn ) ;
savefile - > WriteBool ( spectating ) ;
savefile - > WriteInt ( lastSpectateTeleport ) ;
savefile - > WriteBool ( lastHitToggle ) ;
savefile - > WriteBool ( wantSpectate ) ;
savefile - > WriteBool ( weaponGone ) ;
savefile - > WriteBool ( useInitialSpawns ) ;
savefile - > WriteInt ( tourneyRank ) ;
savefile - > WriteInt ( tourneyLine ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
teleportEntity . Save ( savefile ) ;
savefile - > WriteInt ( teleportKiller ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( minRespawnTime ) ;
savefile - > WriteInt ( maxRespawnTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteVec3 ( firstPersonViewOrigin ) ;
savefile - > WriteMat3 ( firstPersonViewAxis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't bother saving dragEntity since it's a dev tool
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteJoint ( hipJoint ) ;
savefile - > WriteJoint ( chestJoint ) ;
savefile - > WriteJoint ( headJoint ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteStaticObject ( physicsObj ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( aasLocation . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < aasLocation . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( aasLocation [ i ] . areaNum ) ;
savefile - > WriteVec3 ( aasLocation [ i ] . pos ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( bobFoot ) ;
savefile - > WriteFloat ( bobFrac ) ;
savefile - > WriteFloat ( bobfracsin ) ;
savefile - > WriteInt ( bobCycle ) ;
savefile - > WriteFloat ( xyspeed ) ;
savefile - > WriteInt ( stepUpTime ) ;
savefile - > WriteFloat ( stepUpDelta ) ;
savefile - > WriteFloat ( idealLegsYaw ) ;
savefile - > WriteFloat ( legsYaw ) ;
savefile - > WriteBool ( legsForward ) ;
savefile - > WriteFloat ( oldViewYaw ) ;
savefile - > WriteAngles ( viewBobAngles ) ;
savefile - > WriteVec3 ( viewBob ) ;
savefile - > WriteInt ( landChange ) ;
savefile - > WriteInt ( landTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( currentWeapon ) ;
savefile - > WriteInt ( idealWeapon . Get ( ) ) ;
savefile - > WriteInt ( previousWeapon ) ;
savefile - > WriteInt ( weaponSwitchTime ) ;
savefile - > WriteBool ( weaponEnabled ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( skinIndex ) ;
savefile - > WriteSkin ( skin ) ;
savefile - > WriteSkin ( powerUpSkin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( numProjectilesFired ) ;
savefile - > WriteInt ( numProjectileHits ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( airless ) ;
savefile - > WriteInt ( airMsec ) ;
savefile - > WriteInt ( lastAirDamage ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( gibDeath ) ;
savefile - > WriteBool ( gibsLaunched ) ;
savefile - > WriteVec3 ( gibsDir ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteFloat ( zoomFov . GetStartTime ( ) ) ;
savefile - > WriteFloat ( zoomFov . GetDuration ( ) ) ;
savefile - > WriteFloat ( zoomFov . GetStartValue ( ) ) ;
savefile - > WriteFloat ( zoomFov . GetEndValue ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteFloat ( centerView . GetStartTime ( ) ) ;
savefile - > WriteFloat ( centerView . GetDuration ( ) ) ;
savefile - > WriteFloat ( centerView . GetStartValue ( ) ) ;
savefile - > WriteFloat ( centerView . GetEndValue ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( fxFov ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteFloat ( influenceFov ) ;
savefile - > WriteInt ( influenceActive ) ;
savefile - > WriteFloat ( influenceRadius ) ;
savefile - > WriteObject ( influenceEntity ) ;
savefile - > WriteMaterial ( influenceMaterial ) ;
savefile - > WriteSkin ( influenceSkin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteObject ( privateCameraView ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < NUM_LOGGED_VIEW_ANGLES ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteAngles ( loggedViewAngles [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < NUM_LOGGED_ACCELS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( loggedAccel [ i ] . time ) ;
savefile - > WriteVec3 ( loggedAccel [ i ] . dir ) ;
}
savefile - > WriteInt ( currentLoggedAccel ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteObject ( focusGUIent ) ;
// can't save focusUI
savefile - > WriteObject ( focusCharacter ) ;
savefile - > WriteInt ( talkCursor ) ;
savefile - > WriteInt ( focusTime ) ;
savefile - > WriteObject ( focusVehicle ) ;
savefile - > WriteUserInterface ( cursor , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( oldMouseX ) ;
savefile - > WriteInt ( oldMouseY ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( tipUp ) ;
savefile - > WriteBool ( objectiveUp ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( lastDamageDef ) ;
savefile - > WriteVec3 ( lastDamageDir ) ;
savefile - > WriteInt ( lastDamageLocation ) ;
savefile - > WriteInt ( smoothedFrame ) ;
savefile - > WriteBool ( smoothedOriginUpdated ) ;
savefile - > WriteVec3 ( smoothedOrigin ) ;
savefile - > WriteAngles ( smoothedAngles ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( respawning ) ;
savefile - > WriteBool ( leader ) ;
savefile - > WriteInt ( lastSpectateChange ) ;
savefile - > WriteInt ( lastTeleFX ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteFloat ( pm_stamina . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// TODO_SPARTY hook this up with new hud
//if ( hud ) {
// hud->SetStateString( "message", idLocalization::GetString( "#str_02916" ) );
// hud->HandleNamedEvent( "Message" );
//}
2012-11-28 15:47:07 +00:00
savefile - > WriteInt ( weaponToggles . Num ( ) ) ;
for ( i = 0 ; i < weaponToggles . Num ( ) ; i + + )
{
WeaponToggle_t * weaponToggle = weaponToggles . GetIndex ( i ) ;
savefile - > WriteString ( weaponToggle - > name ) ;
savefile - > WriteInt ( weaponToggle - > toggleList . Num ( ) ) ;
for ( int j = 0 ; j < weaponToggle - > toggleList . Num ( ) ; j + + )
{
savefile - > WriteInt ( weaponToggle - > toggleList [ j ] ) ;
2012-11-26 18:58:24 +00:00
}
}
savefile - > WriteObject ( mountedObject ) ;
enviroSuitLight . Save ( savefile ) ;
savefile - > WriteBool ( healthRecharge ) ;
savefile - > WriteInt ( lastHealthRechargeTime ) ;
savefile - > WriteInt ( rechargeSpeed ) ;
savefile - > WriteFloat ( new_g_damageScale ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( bloomEnabled ) ;
savefile - > WriteFloat ( bloomSpeed ) ;
savefile - > WriteFloat ( bloomIntensity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteObject ( flashlight . GetEntity ( ) ) ;
savefile - > WriteInt ( flashlightBattery ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
achievementManager . Save ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( playedTimeSecs ) ;
savefile - > WriteInt ( playedTimeResidual ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_PLAYER_PDA ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( pdaHasBeenRead [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_PLAYER_VIDEO ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( videoHasBeenViewed [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_PLAYER_AUDIO ; i + + )
{
for ( int j = 0 ; j < MAX_PLAYER_AUDIO_ENTRIES ; j + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( audioHasBeenHeard [ i ] [ j ] ) ;
}
}
}
/*
= = = = = = = = = = =
idPlayer : : Restore
= = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
float set ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadUsercmd ( usercmd ) ;
playerView . Restore ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( noclip ) ;
savefile - > ReadBool ( godmode ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadAngles ( spawnAngles ) ;
savefile - > ReadAngles ( viewAngles ) ;
savefile - > ReadAngles ( cmdAngles ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( usercmd . angles , 0 , sizeof ( usercmd . angles ) ) ;
SetViewAngles ( viewAngles ) ;
spawnAnglesSet = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( buttonMask ) ;
savefile - > ReadInt ( oldButtons ) ;
savefile - > ReadInt ( oldImpulseSequence ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
usercmd . impulseSequence = 0 ;
oldImpulseSequence = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( lastHitTime ) ;
savefile - > ReadInt ( lastSndHitTime ) ;
savefile - > ReadInt ( lastSavingThrowTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Re-link idBoolFields to the scriptObject, values will be restored in scriptObject's restore
LinkScriptVariables ( ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( primaryObjective ) ) ;
2012-11-26 18:58:24 +00:00
inventory . Restore ( savefile ) ;
weapon . Restore ( savefile ) ;
2012-11-28 15:47:07 +00:00
if ( hudManager ! = NULL )
{
2012-11-26 18:58:24 +00:00
hudManager - > Initialize ( " hud " , common - > SW ( ) ) ;
hudManager - > ActivateMenu ( true ) ;
hud = hudManager - > GetHud ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( pdaMenu ! = NULL )
{
2012-11-26 18:58:24 +00:00
pdaMenu - > Initialize ( " pda " , common - > SW ( ) ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < inventory . emails . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
GetPDA ( ) - > AddEmail ( inventory . emails [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < NUM_QUICK_SLOTS ; + + i )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( quickSlot [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( weapon_soulcube ) ;
savefile - > ReadInt ( weapon_pda ) ;
savefile - > ReadInt ( weapon_fists ) ;
savefile - > ReadInt ( weapon_flashlight ) ;
savefile - > ReadInt ( weapon_chainsaw ) ;
savefile - > ReadInt ( weapon_bloodstone ) ;
savefile - > ReadInt ( weapon_bloodstone_active1 ) ;
savefile - > ReadInt ( weapon_bloodstone_active2 ) ;
savefile - > ReadInt ( weapon_bloodstone_active3 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( harvest_lock ) ;
savefile - > ReadInt ( hudPowerup ) ;
savefile - > ReadInt ( lastHudPowerup ) ;
savefile - > ReadInt ( hudPowerupDuration ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( heartRate ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadFloat ( set ) ;
heartInfo . SetStartTime ( set ) ;
savefile - > ReadFloat ( set ) ;
heartInfo . SetDuration ( set ) ;
savefile - > ReadFloat ( set ) ;
heartInfo . SetStartValue ( set ) ;
savefile - > ReadFloat ( set ) ;
heartInfo . SetEndValue ( set ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( lastHeartAdjust ) ;
savefile - > ReadInt ( lastHeartBeat ) ;
savefile - > ReadInt ( lastDmgTime ) ;
savefile - > ReadInt ( deathClearContentsTime ) ;
savefile - > ReadBool ( doingDeathSkin ) ;
savefile - > ReadInt ( lastArmorPulse ) ;
savefile - > ReadFloat ( stamina ) ;
savefile - > ReadFloat ( healthPool ) ;
savefile - > ReadInt ( nextHealthPulse ) ;
savefile - > ReadBool ( healthPulse ) ;
savefile - > ReadInt ( nextHealthTake ) ;
savefile - > ReadBool ( healthTake ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( hiddenWeapon ) ;
soulCubeProjectile . Restore ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( spectator ) ;
savefile - > ReadBool ( forceScoreBoard ) ;
savefile - > ReadBool ( forceRespawn ) ;
savefile - > ReadBool ( spectating ) ;
savefile - > ReadInt ( lastSpectateTeleport ) ;
savefile - > ReadBool ( lastHitToggle ) ;
savefile - > ReadBool ( wantSpectate ) ;
savefile - > ReadBool ( weaponGone ) ;
savefile - > ReadBool ( useInitialSpawns ) ;
savefile - > ReadInt ( tourneyRank ) ;
savefile - > ReadInt ( tourneyLine ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
teleportEntity . Restore ( savefile ) ;
savefile - > ReadInt ( teleportKiller ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( minRespawnTime ) ;
savefile - > ReadInt ( maxRespawnTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadVec3 ( firstPersonViewOrigin ) ;
savefile - > ReadMat3 ( firstPersonViewAxis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't bother saving dragEntity since it's a dev tool
dragEntity . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadJoint ( hipJoint ) ;
savefile - > ReadJoint ( chestJoint ) ;
savefile - > ReadJoint ( headJoint ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadStaticObject ( physicsObj ) ;
RestorePhysics ( & physicsObj ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( num ) ;
aasLocation . SetGranularity ( 1 ) ;
aasLocation . SetNum ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( aasLocation [ i ] . areaNum ) ;
savefile - > ReadVec3 ( aasLocation [ i ] . pos ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( bobFoot ) ;
savefile - > ReadFloat ( bobFrac ) ;
savefile - > ReadFloat ( bobfracsin ) ;
savefile - > ReadInt ( bobCycle ) ;
savefile - > ReadFloat ( xyspeed ) ;
savefile - > ReadInt ( stepUpTime ) ;
savefile - > ReadFloat ( stepUpDelta ) ;
savefile - > ReadFloat ( idealLegsYaw ) ;
savefile - > ReadFloat ( legsYaw ) ;
savefile - > ReadBool ( legsForward ) ;
savefile - > ReadFloat ( oldViewYaw ) ;
savefile - > ReadAngles ( viewBobAngles ) ;
savefile - > ReadVec3 ( viewBob ) ;
savefile - > ReadInt ( landChange ) ;
savefile - > ReadInt ( landTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( currentWeapon ) ;
int savedIdealWeapon = - 1 ;
savefile - > ReadInt ( savedIdealWeapon ) ;
idealWeapon . Set ( savedIdealWeapon ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( previousWeapon ) ;
savefile - > ReadInt ( weaponSwitchTime ) ;
savefile - > ReadBool ( weaponEnabled ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( skinIndex ) ;
savefile - > ReadSkin ( skin ) ;
savefile - > ReadSkin ( powerUpSkin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( numProjectilesFired ) ;
savefile - > ReadInt ( numProjectileHits ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( airless ) ;
savefile - > ReadInt ( airMsec ) ;
savefile - > ReadInt ( lastAirDamage ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( gibDeath ) ;
savefile - > ReadBool ( gibsLaunched ) ;
savefile - > ReadVec3 ( gibsDir ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadFloat ( set ) ;
zoomFov . SetStartTime ( set ) ;
savefile - > ReadFloat ( set ) ;
zoomFov . SetDuration ( set ) ;
savefile - > ReadFloat ( set ) ;
zoomFov . SetStartValue ( set ) ;
savefile - > ReadFloat ( set ) ;
zoomFov . SetEndValue ( set ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadFloat ( set ) ;
centerView . SetStartTime ( set ) ;
savefile - > ReadFloat ( set ) ;
centerView . SetDuration ( set ) ;
savefile - > ReadFloat ( set ) ;
centerView . SetStartValue ( set ) ;
savefile - > ReadFloat ( set ) ;
centerView . SetEndValue ( set ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( fxFov ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadFloat ( influenceFov ) ;
savefile - > ReadInt ( influenceActive ) ;
savefile - > ReadFloat ( influenceRadius ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( influenceEntity ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadMaterial ( influenceMaterial ) ;
savefile - > ReadSkin ( influenceSkin ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( privateCameraView ) ) ;
for ( i = 0 ; i < NUM_LOGGED_VIEW_ANGLES ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadAngles ( loggedViewAngles [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < NUM_LOGGED_ACCELS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( loggedAccel [ i ] . time ) ;
savefile - > ReadVec3 ( loggedAccel [ i ] . dir ) ;
}
savefile - > ReadInt ( currentLoggedAccel ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( focusGUIent ) ) ;
2012-11-26 18:58:24 +00:00
// can't save focusUI
focusUI = NULL ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( focusCharacter ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( talkCursor ) ;
savefile - > ReadInt ( focusTime ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( focusVehicle ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadUserInterface ( cursor ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( oldMouseX ) ;
savefile - > ReadInt ( oldMouseY ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( tipUp ) ;
savefile - > ReadBool ( objectiveUp ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( lastDamageDef ) ;
savefile - > ReadVec3 ( lastDamageDir ) ;
savefile - > ReadInt ( lastDamageLocation ) ;
savefile - > ReadInt ( smoothedFrame ) ;
savefile - > ReadBool ( smoothedOriginUpdated ) ;
savefile - > ReadVec3 ( smoothedOrigin ) ;
savefile - > ReadAngles ( smoothedAngles ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( respawning ) ;
savefile - > ReadBool ( leader ) ;
savefile - > ReadInt ( lastSpectateChange ) ;
savefile - > ReadInt ( lastTeleFX ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the pm_ cvars
2012-11-28 15:47:07 +00:00
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
kv = spawnArgs . MatchPrefix ( " pm_ " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
2012-11-26 18:58:24 +00:00
cvarSystem - > SetCVarString ( kv - > GetKey ( ) , kv - > GetValue ( ) ) ;
kv = spawnArgs . MatchPrefix ( " pm_ " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadFloat ( set ) ;
pm_stamina . SetFloat ( set ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// create combat collision hull for exact collision detection
SetCombatModel ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int weaponToggleCount ;
2012-11-28 15:47:07 +00:00
savefile - > ReadInt ( weaponToggleCount ) ;
for ( i = 0 ; i < weaponToggleCount ; i + + )
{
2012-11-26 18:58:24 +00:00
WeaponToggle_t newToggle ;
2012-11-28 15:47:07 +00:00
memset ( & newToggle , 0 , sizeof ( newToggle ) ) ;
2012-11-26 18:58:24 +00:00
idStr name ;
2012-11-28 15:47:07 +00:00
savefile - > ReadString ( name ) ;
strcpy ( newToggle . name , name . c_str ( ) ) ;
2012-11-26 18:58:24 +00:00
int indexCount ;
2012-11-28 15:47:07 +00:00
savefile - > ReadInt ( indexCount ) ;
for ( int j = 0 ; j < indexCount ; j + + )
{
2012-11-26 18:58:24 +00:00
int temp ;
2012-11-28 15:47:07 +00:00
savefile - > ReadInt ( temp ) ;
newToggle . toggleList . Append ( temp ) ;
2012-11-26 18:58:24 +00:00
}
newToggle . lastUsed = 0 ;
2012-11-28 15:47:07 +00:00
weaponToggles . Set ( newToggle . name , newToggle ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( mountedObject ) ) ;
2012-11-26 18:58:24 +00:00
enviroSuitLight . Restore ( savefile ) ;
savefile - > ReadBool ( healthRecharge ) ;
savefile - > ReadInt ( lastHealthRechargeTime ) ;
savefile - > ReadInt ( rechargeSpeed ) ;
savefile - > ReadFloat ( new_g_damageScale ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( bloomEnabled ) ;
savefile - > ReadFloat ( bloomSpeed ) ;
savefile - > ReadFloat ( bloomIntensity ) ;
// flashlight
2012-11-28 15:47:07 +00:00
idWeapon * tempWeapon ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( tempWeapon ) ) ;
2012-11-26 18:58:24 +00:00
tempWeapon - > SetIsPlayerFlashlight ( true ) ;
flashlight = tempWeapon ;
savefile - > ReadInt ( flashlightBattery ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
achievementManager . Restore ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( playedTimeSecs ) ;
savefile - > ReadInt ( playedTimeResidual ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
aimAssist . Init ( this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
laserSightHandle = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// re-init the laser model
memset ( & laserSightRenderEntity , 0 , sizeof ( laserSightRenderEntity ) ) ;
laserSightRenderEntity . hModel = renderModelManager - > FindModel ( " _BEAM " ) ;
laserSightRenderEntity . customShader = declManager - > FindMaterial ( " stereoRenderLaserSight " ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_PLAYER_PDA ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( pdaHasBeenRead [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_PLAYER_VIDEO ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( videoHasBeenViewed [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_PLAYER_AUDIO ; i + + )
{
for ( int j = 0 ; j < MAX_PLAYER_AUDIO_ENTRIES ; j + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( audioHasBeenHeard [ i ] [ j ] ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Update the soul cube HUD indicator
2012-11-28 15:47:07 +00:00
if ( hud )
{
if ( weapon_soulcube > 0 & & ( inventory . weapons & ( 1 < < weapon_soulcube ) ) )
{
2012-11-26 18:58:24 +00:00
int max_souls = inventory . MaxAmmoForAmmoClass ( this , " ammo_souls " ) ;
2012-11-28 15:47:07 +00:00
if ( inventory . GetInventoryAmmoForType ( idWeapon : : GetAmmoNumForName ( " ammo_souls " ) ) > = max_souls )
{
2012-11-26 18:58:24 +00:00
hud - > SetShowSoulCubeOnLoad ( true ) ;
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idPlayer : : PrepareForRestart
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : PrepareForRestart ( )
{
2012-11-26 18:58:24 +00:00
ClearPowerUps ( ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) = = false )
{
2012-11-26 18:58:24 +00:00
ServerSpectate ( true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
forceRespawn = true ;
// Confirm reset hud states
2012-11-28 15:47:07 +00:00
DropFlag ( ) ;
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > SetFlagState ( 0 , 0 ) ;
hud - > SetFlagState ( 1 , 0 ) ;
}
// we will be restarting program, clear the client entities from program-related things first
ShutdownThreads ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the sound world is going to be cleared, don't keep references to emitters
FreeSoundEmitter ( false ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Restart
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Restart ( )
{
2012-11-26 18:58:24 +00:00
idActor : : Restart ( ) ;
// client needs to setup the animation script object again
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
// Make sure the weapon spawnId gets re-linked on the next snapshot.
// Otherwise, its owner might not be set after the map restart, which causes asserts and crashes.
weapon = NULL ;
flashlight = NULL ;
enviroSuitLight = NULL ;
Init ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// choose a random spot and prepare the point of view in case player is left spectating
assert ( spectating ) ;
SpawnFromSpawnSpot ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
useInitialSpawns = true ;
UpdateSkinSetup ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : ServerSpectate
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ServerSpectate ( bool spectate )
{
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( spectating ! = spectate )
{
2012-11-26 18:58:24 +00:00
Spectate ( spectate ) ;
2012-11-28 15:47:07 +00:00
if ( ! spectate )
{
2012-11-26 18:58:24 +00:00
// When coming out of spectate, join the team with the least number of players
2012-11-28 15:47:07 +00:00
if ( gameLocal . mpGame . IsGametypeTeamBased ( ) )
{
2012-11-26 18:58:24 +00:00
int teamCounts [ 2 ] = { 0 , 0 } ;
gameLocal . mpGame . NumActualClients ( false , teamCounts ) ;
teamCounts [ team ] - - ;
2012-11-28 15:47:07 +00:00
if ( teamCounts [ 0 ] < teamCounts [ 1 ] )
{
2012-11-26 18:58:24 +00:00
team = 0 ;
2012-11-28 15:47:07 +00:00
}
else if ( teamCounts [ 1 ] < teamCounts [ 0 ] )
{
2012-11-26 18:58:24 +00:00
team = 1 ;
}
gameLocal . mpGame . SwitchToTeam ( entityNumber , - 1 , team ) ;
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . gameType = = GAME_DM )
{
2012-11-26 18:58:24 +00:00
// make sure the scores are reset so you can't exploit by spectating and entering the game back
// other game types don't matter, as you either can't join back, or it's team scores
gameLocal . mpGame . ClearFrags ( entityNumber ) ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( ! spectate )
{
2012-11-26 18:58:24 +00:00
SpawnFromSpawnSpot ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// drop the flag if player was carrying it
2012-11-28 15:47:07 +00:00
if ( spectate & & common - > IsMultiplayer ( ) & & gameLocal . mpGame . IsGametypeFlagBased ( ) & &
carryingFlag )
2012-11-26 18:58:24 +00:00
{
DropFlag ( ) ;
}
}
/*
= = = = = = = = = = =
idPlayer : : SelectInitialSpawnPoint
Try to find a spawn point marked ' initial ' , otherwise
use normal spawn selection .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SelectInitialSpawnPoint ( idVec3 & origin , idAngles & angles )
{
idEntity * spot ;
2012-11-26 18:58:24 +00:00
idStr skin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spot = gameLocal . SelectInitialSpawnPoint ( this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the player skin from the spawn location
2012-11-28 15:47:07 +00:00
if ( spot - > spawnArgs . GetString ( " skin " , NULL , skin ) )
{
2012-11-26 18:58:24 +00:00
spawnArgs . Set ( " spawn_skin " , skin ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// activate the spawn locations targets
spot - > PostEventMS ( & EV_ActivateTargets , 0 , this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
origin = spot - > GetPhysics ( ) - > GetOrigin ( ) ;
origin [ 2 ] + = 4.0f + CM_BOX_EPSILON ; // move up to make sure the player is at least an epsilon above the floor
angles = spot - > GetPhysics ( ) - > GetAxis ( ) . ToAngles ( ) ;
}
/*
= = = = = = = = = = =
idPlayer : : SpawnFromSpawnSpot
Chooses a spawn location and spawns the player
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SpawnFromSpawnSpot ( )
{
2012-11-26 18:58:24 +00:00
idVec3 spawn_origin ;
idAngles spawn_angles ;
SelectInitialSpawnPoint ( spawn_origin , spawn_angles ) ;
SpawnToPoint ( spawn_origin , spawn_angles ) ;
}
/*
= = = = = = = = = = =
idPlayer : : SpawnToPoint
Called every time a client is placed fresh in the world :
after the first ClientBegin , and after each respawn
Initializes all non - persistant parts of playerState
when called here with spectating set to true , just place yourself and init
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SpawnToPoint ( const idVec3 & spawn_origin , const idAngles & spawn_angles )
{
2012-11-26 18:58:24 +00:00
idVec3 spec_origin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
respawning = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Init ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fl . noknockback = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stop any ragdolls being used
StopRagdoll ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set back the player physics
SetPhysics ( & physicsObj ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetClipModelAxis ( ) ;
physicsObj . EnableClip ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! spectating )
{
2012-11-26 18:58:24 +00:00
SetCombatContents ( true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetLinearVelocity ( vec3_origin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// setup our initial view
2012-11-28 15:47:07 +00:00
if ( ! spectating )
{
2012-11-26 18:58:24 +00:00
SetOrigin ( spawn_origin ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
spec_origin = spawn_origin ;
spec_origin [ 2 ] + = pm_normalheight . GetFloat ( ) ;
spec_origin [ 2 ] + = SPECTATE_RAISE ;
SetOrigin ( spec_origin ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if this is the first spawn of the map, we don't have a usercmd yet,
// so the delta angles won't be correct. This will be fixed on the first think.
viewAngles = ang_zero ;
SetDeltaViewAngles ( ang_zero ) ;
SetViewAngles ( spawn_angles ) ;
spawnAngles = spawn_angles ;
spawnAnglesSet = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
legsForward = true ;
legsYaw = 0.0f ;
idealLegsYaw = 0.0f ;
oldViewYaw = viewAngles . yaw ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
Hide ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Show ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
if ( ! spectating )
{
2012-11-26 18:58:24 +00:00
// we may be called twice in a row in some situations. avoid a double fx and 'fly to the roof'
2012-11-28 15:47:07 +00:00
if ( lastTeleFX < gameLocal . time - 1000 )
{
2012-11-26 18:58:24 +00:00
idEntityFx : : StartFx ( spawnArgs . GetString ( " fx_spawn " ) , & spawn_origin , NULL , this , true ) ;
lastTeleFX = gameLocal . time ;
}
}
AI_TELEPORT = true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
AI_TELEPORT = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// kill anything at the new position
2012-11-28 15:47:07 +00:00
if ( ! spectating )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetClipMask ( MASK_PLAYERSOLID ) ; // the clip mask is usually maintained in Move(), but KillBox requires it
gameLocal . KillBox ( this ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't allow full run speed for a bit
physicsObj . SetKnockBack ( 100 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set our respawn time and buttons so that if we're killed we don't respawn immediately
minRespawnTime = gameLocal . time ;
maxRespawnTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
if ( ! spectating )
{
2012-11-26 18:58:24 +00:00
forceRespawn = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Respawn_Shared ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
privateCameraView = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
BecomeActive ( TH_THINK ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// run a client frame to drop exactly to the floor,
// initialize animations and other things
Think ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
respawning = false ;
lastManOver = false ;
lastManPlayAgain = false ;
isTelefragged = false ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Respawn_Shared
Called on server and client players when they respawn ( including on initial spawn )
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Respawn_Shared ( )
{
2012-11-26 18:58:24 +00:00
respawn_netEvent . Set ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
serverOverridePositionTime = gameLocal . GetServerGameTimeMs ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Remove the hud respawn message.
HideRespawnHudMessage ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FlashlightOff ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : SavePersistantInfo
Saves any inventory and player stats when changing levels .
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SavePersistantInfo ( )
{
idDict & playerInfo = gameLocal . persistentPlayerInfo [ entityNumber ] ;
2012-11-26 18:58:24 +00:00
playerInfo . Clear ( ) ;
inventory . GetPersistantData ( playerInfo ) ;
playerInfo . SetInt ( " health " , health ) ;
playerInfo . SetInt ( " current_weapon " , currentWeapon ) ;
playerInfo . SetInt ( " playedTime " , playedTimeSecs ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
achievementManager . SavePersistentData ( playerInfo ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : RestorePersistantInfo
Restores any inventory and player stats when changing levels .
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RestorePersistantInfo ( )
{
if ( common - > IsMultiplayer ( ) | | g_demoMode . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . persistentPlayerInfo [ entityNumber ] . Clear ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . Copy ( gameLocal . persistentPlayerInfo [ entityNumber ] ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . RestoreInventory ( this , spawnArgs ) ;
health = spawnArgs . GetInt ( " health " , " 100 " ) ;
idealWeapon = spawnArgs . GetInt ( " current_weapon " , " 1 " ) ;
playedTimeSecs = spawnArgs . GetInt ( " playedTime " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
achievementManager . RestorePersistentData ( spawnArgs ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : UpdateSkinSetup
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateSkinSetup ( )
{
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . mpGame . IsGametypeTeamBased ( ) ) /* CTF */
{
2012-11-26 18:58:24 +00:00
skinIndex = team + 1 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Each player will now have their Skin Index Reflect their entity number ( host = 0, client 1 = 1, client 2 = 2 etc )
skinIndex = entityNumber ; // session->GetActingGameStateLobbyBase().GetLobbyUserSkinIndex( gameLocal.lobbyUserIDs[entityNumber] );
}
2012-11-28 15:47:07 +00:00
const char * baseSkinName = gameLocal . mpGame . GetSkinName ( skinIndex ) ;
2012-11-26 18:58:24 +00:00
skin = declManager - > FindSkin ( baseSkinName , false ) ;
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( BERSERK ) )
{
2012-11-26 18:58:24 +00:00
idStr powerSkinName = baseSkinName ;
powerSkinName . Append ( " _berserk " ) ;
powerUpSkin = declManager - > FindSkin ( powerSkinName ) ;
}
2012-11-28 15:47:07 +00:00
else if ( PowerUpActive ( INVULNERABILITY ) )
{
2012-11-26 18:58:24 +00:00
idStr powerSkinName = baseSkinName ;
powerSkinName . Append ( " _invuln " ) ;
powerUpSkin = declManager - > FindSkin ( powerSkinName ) ;
}
2012-11-28 15:47:07 +00:00
else if ( PowerUpActive ( INVISIBILITY ) )
{
const char * invisibleSkin = " " ;
2012-11-26 18:58:24 +00:00
spawnArgs . GetString ( " skin_invisibility " , " " , & invisibleSkin ) ;
powerUpSkin = declManager - > FindSkin ( invisibleSkin ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateHudStats
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateHudStats ( idMenuHandler_HUD * _hudManager )
{
if ( _hudManager & & _hudManager - > GetHud ( ) )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idMenuScreen_HUD * hud = _hudManager - > GetHud ( ) ;
2012-11-26 18:58:24 +00:00
hud - > UpdateHealthArmor ( this ) ;
hud - > UpdateStamina ( this ) ;
hud - > UpdateWeaponInfo ( this ) ;
2012-11-28 15:47:07 +00:00
if ( inventory . weaponPulse )
{
2012-11-26 18:58:24 +00:00
UpdateHudWeapon ( ) ;
inventory . weaponPulse = false ;
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . mpGame . IsGametypeFlagBased ( ) )
2012-11-26 18:58:24 +00:00
{
hud - > SetFlagState ( 0 , gameLocal . mpGame . GetFlagStatus ( 0 ) ) ;
hud - > SetFlagState ( 1 , gameLocal . mpGame . GetFlagStatus ( 1 ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hud - > SetTeamScore ( 0 , gameLocal . mpGame . GetFlagPoints ( 0 ) ) ;
hud - > SetTeamScore ( 1 , gameLocal . mpGame . GetFlagPoints ( 1 ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hud - > SetTeam ( team ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateHudWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateHudWeapon ( bool flashWeapon )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idMenuScreen_HUD * curDisplay = hud ;
idPlayer * p = this ;
if ( gameLocal . GetLocalClientNum ( ) > = 0 & & gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] & & gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] - > IsType ( idPlayer : : Type ) )
{
p = static_cast < idPlayer * > ( gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] ) ;
if ( p - > spectating & & p - > spectator = = entityNumber )
{
2012-11-26 18:58:24 +00:00
assert ( p - > hud ) ;
curDisplay = p - > hud ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! curDisplay )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
curDisplay - > UpdateWeaponStates ( p , flashWeapon ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateHudWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateChattingHud ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idMenuScreen_HUD * curDisplay = hud ;
idPlayer * p = this ;
if ( gameLocal . GetLocalClientNum ( ) > = 0 & & gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] & & gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] - > IsType ( idPlayer : : Type ) )
{
p = static_cast < idPlayer * > ( gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] ) ;
if ( p - > spectating & & p - > spectator = = entityNumber )
{
2012-11-26 18:58:24 +00:00
assert ( p - > hud ) ;
curDisplay = p - > hud ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! curDisplay )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
curDisplay - > UpdateChattingHud ( p ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idMenuScreen_Scoreboard : : UpdateSpectating
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateSpectatingText ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idSWF * spectatorMessages = mpMessages ;
idPlayer * p = this ;
if ( gameLocal . GetLocalClientNum ( ) > = 0 & & gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] & & gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] - > IsType ( idPlayer : : Type ) )
{
p = static_cast < idPlayer * > ( gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] ) ;
if ( p & & p - > spectating )
{
2012-11-26 18:58:24 +00:00
spectatorMessages = p - > mpMessages ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! spectatorMessages | | ! spectatorMessages - > IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idPlayer * viewPlayer = static_cast < idPlayer * > ( gameLocal . entities [ p - > spectator ] ) ;
if ( viewPlayer = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStr spectatetext [ 2 ] ;
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . mpGame . IsScoreboardActive ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . mpGame . GetSpectateText ( p , spectatetext , false ) ;
}
2012-11-28 15:47:07 +00:00
idSWFScriptObject & root = spectatorMessages - > GetRootObject ( ) ;
idSWFTextInstance * txtVal = root . GetNestedText ( " txtSpectating " ) ;
if ( txtVal ! = NULL )
{
2012-11-26 18:58:24 +00:00
txtVal - > tooltip = true ;
txtVal - > SetText ( spectatetext [ 0 ] ) ;
txtVal - > SetStrokeInfo ( true , 0.75f , 1.75f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
txtVal = root . GetNestedText ( " txtFollow " ) ;
2012-11-28 15:47:07 +00:00
if ( txtVal ! = NULL )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( spectatetext [ 1 ] ) ;
txtVal - > SetStrokeInfo ( true , 0.75f , 1.75f ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateMpMessages
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : AddChatMessage ( int index , int alpha , const idStr & message )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( mpMessages = = NULL | | ! mpMessages - > IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idSWFScriptObject * mpChat = mpMessages - > GetRootObject ( ) . GetNestedObj ( " _left " , " mpChat " ) ;
idSWFSpriteInstance * info = mpChat - > GetNestedSprite ( va ( " info%i " , index ) ) ;
idSWFTextInstance * txtVal = mpChat - > GetNestedText ( va ( " info%i " , index ) , " txtVal " ) ;
if ( info )
{
2012-11-26 18:58:24 +00:00
info - > SetVisible ( true ) ;
2012-11-28 15:47:07 +00:00
if ( alpha > = 4 )
{
2012-11-26 18:58:24 +00:00
info - > SetAlpha ( 1.0f ) ;
2012-11-28 15:47:07 +00:00
}
else if ( alpha = = 3 )
{
2012-11-26 18:58:24 +00:00
info - > SetAlpha ( 0.875f ) ;
2012-11-28 15:47:07 +00:00
}
else if ( alpha = = 2 )
{
2012-11-26 18:58:24 +00:00
info - > SetAlpha ( 0.75f ) ;
2012-11-28 15:47:07 +00:00
}
else if ( alpha = = 1 )
{
2012-11-26 18:58:24 +00:00
info - > SetAlpha ( 0.625f ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
info - > SetAlpha ( 0.5f ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( txtVal )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetIgnoreColor ( false ) ;
txtVal - > SetText ( message ) ;
txtVal - > SetStrokeInfo ( true , 0.9f , 1.75f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateMpMessages
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ClearChatMessage ( int index )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( mpMessages = = NULL | | ! mpMessages - > IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idSWFScriptObject * mpChat = mpMessages - > GetRootObject ( ) . GetNestedObj ( " _left " , " mpChat " ) ;
idSWFSpriteInstance * info = mpChat - > GetNestedSprite ( va ( " info%i " , index ) ) ;
idSWFTextInstance * txtVal = mpChat - > GetNestedText ( va ( " info%i " , index ) , " txtVal " ) ;
if ( info )
{
2012-11-26 18:58:24 +00:00
info - > SetVisible ( false ) ;
}
2012-11-28 15:47:07 +00:00
if ( txtVal )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( " " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idPlayer : : DrawHUD
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : DrawHUD ( idMenuHandler_HUD * _hudManager )
{
2012-11-26 18:58:24 +00:00
SCOPED_PROFILE_EVENT ( " idPlayer::DrawHUD " ) ;
2012-11-28 15:47:07 +00:00
if ( ! weapon . GetEntity ( ) | | influenceActive ! = INFLUENCE_NONE | | privateCameraView | | gameLocal . GetCamera ( ) | | ! g_showHud . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
UpdateChattingHud ( ) ;
UpdateSpectatingText ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Always draw the local client's messages so that chat works correctly while spectating another player.
2012-11-28 15:47:07 +00:00
idPlayer * localPlayer = static_cast < idPlayer * > ( gameLocal . entities [ gameLocal . GetLocalClientNum ( ) ] ) ;
if ( localPlayer ! = NULL & & localPlayer - > mpMessages ! = NULL )
{
2012-11-26 18:58:24 +00:00
localPlayer - > mpMessages - > Render ( renderSystem , Sys_Milliseconds ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateHudStats ( _hudManager ) ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
return ;
2012-11-28 15:47:07 +00:00
}
if ( _hudManager )
{
2012-11-26 18:58:24 +00:00
_hudManager - > Update ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > UpdateGUI ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// weapon targeting crosshair
2012-11-28 15:47:07 +00:00
if ( ! GuiActive ( ) )
{
2012-11-26 18:58:24 +00:00
// don't show the 2D crosshair in stereo rendering, use the
// laser sight model instead
2012-11-28 15:47:07 +00:00
if ( _hudManager & & _hudManager - > GetHud ( ) )
{
idMenuScreen_HUD * hud = _hudManager - > GetHud ( ) ;
if ( weapon . GetEntity ( ) - > ShowCrosshair ( ) & & ! IsGameStereoRendered ( ) )
{
if ( weapon . GetEntity ( ) - > GetGrabberState ( ) = = 1 | | weapon . GetEntity ( ) - > GetGrabberState ( ) = = 2 )
{
2012-11-26 18:58:24 +00:00
hud - > SetCursorState ( this , CURSOR_GRABBER , 1 ) ;
hud - > SetCursorState ( this , CURSOR_IN_COMBAT , 0 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hud - > SetCursorState ( this , CURSOR_GRABBER , 0 ) ;
hud - > SetCursorState ( this , CURSOR_IN_COMBAT , 1 ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hud - > SetCursorState ( this , CURSOR_NONE , 1 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hud - > UpdateCursorState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
}
else if ( _hudManager & & _hudManager - > GetHud ( ) )
{
idMenuScreen_HUD * hud = _hudManager - > GetHud ( ) ;
2012-11-26 18:58:24 +00:00
hud - > SetCursorState ( this , CURSOR_NONE , 1 ) ;
hud - > UpdateCursorState ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : EnterCinematic
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : EnterCinematic ( )
{
if ( PowerUpActive ( HELLTIME ) )
{
2012-11-26 18:58:24 +00:00
StopHelltime ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Hide ( ) ;
StopSound ( SND_CHANNEL_PDA_AUDIO , false ) ;
StopSound ( SND_CHANNEL_PDA_VIDEO , false ) ;
2012-11-28 15:47:07 +00:00
if ( hudManager )
{
2012-11-26 18:58:24 +00:00
hudManager - > SetRadioMessage ( false ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
physicsObj . SetLinearVelocity ( vec3_origin ) ;
SetState ( " EnterCinematic " ) ;
UpdateScript ( ) ;
2012-11-28 15:47:07 +00:00
if ( weaponEnabled & & weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > EnterCinematic ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > EnterCinematic ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AI_FORWARD = false ;
AI_BACKWARD = false ;
AI_STRAFE_LEFT = false ;
AI_STRAFE_RIGHT = false ;
AI_RUN = false ;
AI_ATTACK_HELD = false ;
AI_WEAPON_FIRED = false ;
AI_JUMP = false ;
AI_CROUCH = false ;
AI_ONGROUND = true ;
AI_ONLADDER = false ;
AI_DEAD = ( health < = 0 ) ;
AI_RUN = false ;
AI_PAIN = false ;
AI_HARDLANDING = false ;
AI_SOFTLANDING = false ;
AI_RELOAD = false ;
AI_TELEPORT = false ;
AI_TURN_LEFT = false ;
AI_TURN_RIGHT = false ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : ExitCinematic
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ExitCinematic ( )
{
2012-11-26 18:58:24 +00:00
Show ( ) ;
2012-11-28 15:47:07 +00:00
if ( weaponEnabled & & weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > ExitCinematic ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > ExitCinematic ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// long cinematics would have surpassed the healthTakeTime, causing the player to take damage
// immediately after the cinematic ends. Instead we start the healthTake cooldown again once
// the cinematic ends.
2012-11-28 15:47:07 +00:00
if ( g_skill . GetInteger ( ) = = 3 )
{
2012-11-26 18:58:24 +00:00
nextHealthTake = gameLocal . time + g_healthTakeTime . GetInteger ( ) * 1000 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetState ( " ExitCinematic " ) ;
UpdateScript ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idPlayer : : UpdateConditions
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateConditions ( )
{
2012-11-26 18:58:24 +00:00
idVec3 velocity ;
float fallspeed ;
float forwardspeed ;
float sidespeed ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// minus the push velocity to avoid playing the walking animation and sounds when riding a mover
velocity = physicsObj . GetLinearVelocity ( ) - physicsObj . GetPushedLinearVelocity ( ) ;
fallspeed = velocity * physicsObj . GetGravityNormal ( ) ;
2012-11-28 15:47:07 +00:00
if ( influenceActive )
{
2012-11-26 18:58:24 +00:00
AI_FORWARD = false ;
AI_BACKWARD = false ;
AI_STRAFE_LEFT = false ;
AI_STRAFE_RIGHT = false ;
2012-11-28 15:47:07 +00:00
}
else if ( gameLocal . time - lastDmgTime < 500 )
{
2012-11-26 18:58:24 +00:00
forwardspeed = velocity * viewAxis [ 0 ] ;
sidespeed = velocity * viewAxis [ 1 ] ;
AI_FORWARD = AI_ONGROUND & & ( forwardspeed > 20.01f ) ;
AI_BACKWARD = AI_ONGROUND & & ( forwardspeed < - 20.01f ) ;
AI_STRAFE_LEFT = AI_ONGROUND & & ( sidespeed > 20.01f ) ;
AI_STRAFE_RIGHT = AI_ONGROUND & & ( sidespeed < - 20.01f ) ;
2012-11-28 15:47:07 +00:00
}
else if ( xyspeed > MIN_BOB_SPEED )
{
2012-11-26 18:58:24 +00:00
AI_FORWARD = AI_ONGROUND & & ( usercmd . forwardmove > 0 ) ;
AI_BACKWARD = AI_ONGROUND & & ( usercmd . forwardmove < 0 ) ;
AI_STRAFE_LEFT = AI_ONGROUND & & ( usercmd . rightmove < 0 ) ;
AI_STRAFE_RIGHT = AI_ONGROUND & & ( usercmd . rightmove > 0 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
AI_FORWARD = false ;
AI_BACKWARD = false ;
AI_STRAFE_LEFT = false ;
AI_STRAFE_RIGHT = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AI_RUN = ( usercmd . buttons & BUTTON_RUN ) & & ( ( ! pm_stamina . GetFloat ( ) ) | | ( stamina > pm_staminathreshold . GetFloat ( ) ) ) ;
AI_DEAD = ( health < = 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = =
WeaponFireFeedback
Called when a weapon fires , generates head twitches , etc
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : WeaponFireFeedback ( const idDict * weaponDef )
{
2012-11-26 18:58:24 +00:00
// force a blink
blink_time = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// play the fire animation
AI_WEAPON_FIRED = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update view feedback
playerView . WeaponFireFeedback ( weaponDef ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// shake controller
float highMagnitude = weaponDef - > GetFloat ( " controllerShakeHighMag " ) ;
int highDuration = weaponDef - > GetInt ( " controllerShakeHighTime " ) ;
float lowMagnitude = weaponDef - > GetFloat ( " controllerShakeLowMag " ) ;
int lowDuration = weaponDef - > GetInt ( " controllerShakeLowTime " ) ;
//const char *name = weaponDef->GetString( "inv_name" );
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
SetControllerShake ( highMagnitude , highDuration , lowMagnitude , lowDuration ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : StopFiring
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : StopFiring ( )
{
2012-11-26 18:58:24 +00:00
AI_ATTACK_HELD = false ;
AI_WEAPON_FIRED = false ;
AI_RELOAD = false ;
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > EndAttack ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : FireWeapon
= = = = = = = = = = = = = = =
*/
idCVar g_infiniteAmmo ( " g_infiniteAmmo " , " 0 " , CVAR_GAME | CVAR_BOOL , " infinite ammo " ) ;
extern idCVar ui_autoSwitch ;
2012-11-28 15:47:07 +00:00
void idPlayer : : FireWeapon ( )
{
2012-11-26 18:58:24 +00:00
idMat3 axis ;
idVec3 muzzle ;
2012-11-28 15:47:07 +00:00
if ( privateCameraView )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( g_editEntityMode . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
GetViewPos ( muzzle , axis ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . editEntities - > SelectEntity ( muzzle , axis [ 0 ] , this ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! hiddenWeapon & & weapon . GetEntity ( ) - > IsReady ( ) )
{
if ( g_infiniteAmmo . GetBool ( ) | | weapon . GetEntity ( ) - > AmmoInClip ( ) | | weapon . GetEntity ( ) - > AmmoAvailable ( ) )
{
2012-11-26 18:58:24 +00:00
AI_ATTACK_HELD = true ;
weapon . GetEntity ( ) - > BeginAttack ( ) ;
2012-11-28 15:47:07 +00:00
if ( ( weapon_soulcube > = 0 ) & & ( currentWeapon = = weapon_soulcube ) )
{
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > UpdateSoulCube ( false ) ;
}
SelectWeapon ( previousWeapon , false ) ;
}
2012-11-28 15:47:07 +00:00
if ( ( weapon_bloodstone > = 0 ) & & ( currentWeapon = = weapon_bloodstone ) & & inventory . weapons & ( 1 < < weapon_bloodstone_active1 ) & & weapon . GetEntity ( ) - > GetStatus ( ) = = WP_READY )
{
2012-11-26 18:58:24 +00:00
// tell it to switch to the previous weapon. Only do this once to prevent
// weapon toggling messing up the previous weapon
2012-11-28 15:47:07 +00:00
if ( idealWeapon = = weapon_bloodstone )
{
if ( previousWeapon = = weapon_bloodstone | | previousWeapon = = - 1 )
{
2012-11-26 18:58:24 +00:00
NextBestWeapon ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
//Since this is a toggle weapon just select itself and it will toggle to the last weapon
SelectWeapon ( weapon_bloodstone , false ) ;
}
}
}
2012-11-28 15:47:07 +00:00
}
else
{
idLobbyBase & lobby = session - > GetActingGameStateLobbyBase ( ) ;
lobbyUserID_t & lobbyUserID = gameLocal . lobbyUserIDs [ entityNumber ] ;
2012-11-26 18:58:24 +00:00
bool autoSwitch = lobby . GetLobbyUserWeaponAutoSwitch ( lobbyUserID ) ;
2012-11-28 15:47:07 +00:00
if ( ! autoSwitch )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update our ammo clip in our inventory
2012-11-28 15:47:07 +00:00
if ( ( currentWeapon > = 0 ) & & ( currentWeapon < MAX_WEAPONS ) )
{
2012-11-26 18:58:24 +00:00
inventory . SetClipAmmoForWeapon ( currentWeapon , weapon . GetEntity ( ) - > AmmoInClip ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
NextBestWeapon ( ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( tipUp )
{
2012-11-26 18:58:24 +00:00
HideTip ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( objectiveUp )
{
2012-11-26 18:58:24 +00:00
HideObjective ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : CacheWeapons
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : CacheWeapons ( )
{
2012-11-26 18:58:24 +00:00
idStr weap ;
int w ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we have any weapons
2012-11-28 15:47:07 +00:00
if ( ! inventory . weapons )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
for ( w = 0 ; w < MAX_WEAPONS ; w + + )
{
if ( inventory . weapons & ( 1 < < w ) )
{
2012-11-26 18:58:24 +00:00
weap = spawnArgs . GetString ( va ( " def_weapon%d " , w ) ) ;
2012-11-28 15:47:07 +00:00
if ( weap ! = " " )
{
2012-11-26 18:58:24 +00:00
idWeapon : : CacheWeapon ( weap ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
inventory . weapons & = ~ ( 1 < < w ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : SetQuickSlot
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetQuickSlot ( int index , int val )
{
if ( index > = NUM_QUICK_SLOTS | | index < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
quickSlot [ index ] = val ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GetQuickSlot
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPlayer : : GetQuickSlot ( int index )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( index > = NUM_QUICK_SLOTS | | index < 0 )
{
2012-11-26 18:58:24 +00:00
return - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return quickSlot [ index ] ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Give
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : Give ( const char * statname , const char * value , unsigned int giveFlags )
{
2012-11-26 18:58:24 +00:00
int amount ;
2012-11-28 15:47:07 +00:00
if ( AI_DEAD )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( statname , " health " ) )
{
if ( health > = inventory . maxHealth )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
amount = atoi ( value ) ;
2012-11-28 15:47:07 +00:00
if ( amount )
{
2012-11-26 18:58:24 +00:00
health + = amount ;
2012-11-28 15:47:07 +00:00
if ( health > inventory . maxHealth )
{
2012-11-26 18:58:24 +00:00
health = inventory . maxHealth ;
}
healthPulse = true ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " stamina " ) )
{
if ( stamina > = 100 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
stamina + = atof ( value ) ;
2012-11-28 15:47:07 +00:00
if ( stamina > 100 )
{
2012-11-26 18:58:24 +00:00
stamina = 100 ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " heartRate " ) )
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
heartRate + = atoi ( value ) ;
2012-11-28 15:47:07 +00:00
if ( heartRate > MAX_HEARTRATE )
{
2012-11-26 18:58:24 +00:00
heartRate = MAX_HEARTRATE ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " air " ) )
{
if ( airMsec > = pm_airMsec . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
airMsec + = pm_airMsec . GetInteger ( ) * atoi ( value ) / 100 ;
2012-11-28 15:47:07 +00:00
if ( airMsec > pm_airMsec . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
airMsec = pm_airMsec . GetInteger ( ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " enviroTime " ) )
{
if ( ( giveFlags & ITEM_GIVE_UPDATE_STATE ) & & PowerUpActive ( ENVIROTIME ) )
{
inventory . powerupEndTime [ ENVIROTIME ] + = ( atof ( value ) * 1000 ) ;
}
else
{
GivePowerUp ( ENVIROTIME , atoi ( value ) * 1000 , giveFlags ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
bool ret = inventory . Give ( this , spawnArgs , statname , value , & idealWeapon , true , giveFlags ) ;
return ret ;
}
return true ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveHealthPool
adds health to the player health pool
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GiveHealthPool ( float amt )
{
if ( AI_DEAD )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( health > 0 )
{
2012-11-26 18:58:24 +00:00
healthPool + = amt ;
2012-11-28 15:47:07 +00:00
if ( healthPool > inventory . maxHealth - health )
{
2012-11-26 18:58:24 +00:00
healthPool = inventory . maxHealth - health ;
}
nextHealthPulse = gameLocal . time ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveItem
Returns false if the item shouldn ' t be picked up
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : GiveItem ( idItem * item , unsigned int giveFlags )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
const idKeyValue * arg ;
2012-11-26 18:58:24 +00:00
idDict attr ;
bool gave ;
int numPickup ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & spectating )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( idStr : : FindText ( item - > GetName ( ) , " weapon_flashlight_new " ) > - 1 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( idStr : : FindText ( item - > GetName ( ) , " weapon_flashlight " ) > - 1 )
{
2012-11-26 18:58:24 +00:00
// don't allow flashlight weapon unless classic mode is enabled
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
item - > GetAttributes ( attr ) ;
gave = false ;
numPickup = inventory . pickupItemNames . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < attr . GetNumKeyVals ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
arg = attr . GetKeyVal ( i ) ;
2012-11-28 15:47:07 +00:00
if ( Give ( arg - > GetKey ( ) , arg - > GetValue ( ) , giveFlags ) )
{
2012-11-26 18:58:24 +00:00
gave = true ;
}
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
2012-11-26 18:58:24 +00:00
arg = item - > spawnArgs . MatchPrefix ( " inv_weapon " , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( arg )
{
2012-11-26 18:58:24 +00:00
// We need to update the weapon hud manually, but not
// the armor/ammo/health because they are updated every
// frame no matter what
UpdateHudWeapon ( false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// display the pickup feedback on the hud
2012-11-28 15:47:07 +00:00
if ( gave & & ( numPickup = = inventory . pickupItemNames . Num ( ) ) )
{
2012-11-26 18:58:24 +00:00
inventory . AddPickupName ( item - > spawnArgs . GetString ( " inv_name " ) , this ) ; //_D3XP
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return gave ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : PowerUpModifier
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idPlayer : : PowerUpModifier ( int type )
{
2012-11-26 18:58:24 +00:00
float mod = 1.0f ;
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( BERSERK ) )
{
switch ( type )
{
case SPEED :
{
2012-11-26 18:58:24 +00:00
mod * = 1.7f ;
break ;
}
2012-11-28 15:47:07 +00:00
case PROJECTILE_DAMAGE :
{
2012-11-26 18:58:24 +00:00
mod * = 2.0f ;
break ;
}
2012-11-28 15:47:07 +00:00
case MELEE_DAMAGE :
{
2012-11-26 18:58:24 +00:00
mod * = 30.0f ;
break ;
}
2012-11-28 15:47:07 +00:00
case MELEE_DISTANCE :
{
2012-11-26 18:58:24 +00:00
mod * = 2.0f ;
break ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & ! common - > IsClient ( ) )
{
if ( PowerUpActive ( MEGAHEALTH ) )
{
if ( healthPool < = 0 )
{
2012-11-26 18:58:24 +00:00
GiveHealthPool ( 100 ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
healthPool = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
/*if( PowerUpActive( HASTE ) ) {
switch ( type ) {
case SPEED : {
mod = 1.7f ;
break ;
}
}
} */
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return mod ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : PowerUpActive
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : PowerUpActive ( int powerup ) const
{
2012-11-26 18:58:24 +00:00
return ( inventory . powerups & ( 1 < < powerup ) ) ! = 0 ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GivePowerUp
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : GivePowerUp ( int powerup , int time , unsigned int giveFlags )
{
const char * sound ;
if ( powerup > = 0 & & powerup < MAX_POWERUPS )
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
if ( common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
msg . WriteShort ( powerup ) ;
msg . WriteShort ( time ) ;
ServerSendEvent ( EVENT_POWERUP , & msg , false ) ;
}
2012-11-28 15:47:07 +00:00
if ( powerup ! = MEGAHEALTH )
{
2012-11-26 18:58:24 +00:00
inventory . GivePowerUp ( this , powerup , time ) ;
}
}
2012-11-28 15:47:07 +00:00
switch ( powerup )
{
case BERSERK :
{
if ( giveFlags & ITEM_GIVE_FROM_WEAPON )
{
2012-11-26 18:58:24 +00:00
// Berserk is granted by the bloodstone in ROE, but we don't want any of the
// standard behavior (sound fx, switch to fists) when you get it this way.
2012-11-28 15:47:07 +00:00
}
else
{
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
2012-11-26 18:58:24 +00:00
inventory . AddPickupName ( " #str_00100627 " , this ) ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " snd_berserk_third " , " " , & sound ) & & sound [ 0 ] ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_DEMONIC , 0 , false , NULL ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
if ( ! common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
idealWeapon = weapon_fists ;
}
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case INVISIBILITY :
{
if ( common - > IsMultiplayer ( ) & & ( giveFlags & ITEM_GIVE_FEEDBACK ) )
{
inventory . AddPickupName ( " #str_00100628 " , this ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
// remove any decals from the model
2012-11-28 15:47:07 +00:00
if ( modelDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > RemoveDecals ( modelDefHandle ) ;
}
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > UpdateSkin ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > UpdateSkin ( ) ;
}
}
2012-11-28 15:47:07 +00:00
/* if ( spawnArgs.GetString( "snd_invisibility", "", &sound ) ) {
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_ANY , 0 , false , NULL ) ;
} */
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
case ADRENALINE :
{
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
inventory . AddPickupName ( " #str_00100799 " , this ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
stamina = 100.0f ;
}
break ;
2012-11-28 15:47:07 +00:00
}
case MEGAHEALTH :
{
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
if ( common - > IsMultiplayer ( ) )
{
inventory . AddPickupName ( " #str_00100629 " , this ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " snd_megahealth " , " " , & sound ) )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
health = 200 ;
}
break ;
2012-11-28 15:47:07 +00:00
}
case HELLTIME :
{
if ( spawnArgs . GetString ( " snd_helltime_start " , " " , & sound ) )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_StartSoundShader , 0 , sound , SND_CHANNEL_ANY ) ;
}
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " snd_helltime_loop " , " " , & sound ) )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_StartSoundShader , 0 , sound , SND_CHANNEL_DEMONIC ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case ENVIROSUIT :
{
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
2012-11-26 18:58:24 +00:00
// Turn on the envirosuit sound
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > SetEnviroSuit ( true ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
// Put the helmet and lights on the player
idDict args ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Light
2012-11-28 15:47:07 +00:00
const idDict * lightDef = gameLocal . FindEntityDefDict ( " envirosuit_light " , false ) ;
if ( lightDef )
{
idEntity * temp ;
2012-11-26 18:58:24 +00:00
gameLocal . SpawnEntityDef ( * lightDef , & temp , false ) ;
2012-11-28 15:47:07 +00:00
idLight * eLight = static_cast < idLight * > ( temp ) ;
2012-11-26 18:58:24 +00:00
eLight - > GetPhysics ( ) - > SetOrigin ( firstPersonViewOrigin ) ;
eLight - > UpdateVisuals ( ) ;
eLight - > Present ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
enviroSuitLight = eLight ;
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case ENVIROTIME :
{
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
hudPowerup = ENVIROTIME ;
// The HUD display bar is fixed at 60 seconds
hudPowerupDuration = 60000 ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case INVULNERABILITY :
{
if ( common - > IsMultiplayer ( ) & & ( giveFlags & ITEM_GIVE_FEEDBACK ) )
{
inventory . AddPickupName ( " #str_00100630 " , this ) ;
2012-11-26 18:58:24 +00:00
}
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
2012-11-26 18:58:24 +00:00
UpdateSkinSetup ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Player given power up %i \n which is out of range " , powerup ) ;
}
return false ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : ClearPowerup
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ClearPowerup ( int i )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
msg . WriteShort ( i ) ;
msg . WriteShort ( 0 ) ;
ServerSendEvent ( EVENT_POWERUP , & msg , false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
powerUpSkin = NULL ;
inventory . powerups & = ~ ( 1 < < i ) ;
inventory . powerupEndTime [ i ] = 0 ;
2012-11-28 15:47:07 +00:00
switch ( i )
{
case BERSERK :
{
if ( common - > IsMultiplayer ( ) )
{
StopSound ( SND_CHANNEL_DEMONIC , false ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
StopHealthRecharge ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case INVISIBILITY :
{
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > UpdateSkin ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > UpdateSkin ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case HELLTIME :
{
2012-11-26 18:58:24 +00:00
GetAchievementManager ( ) . ResetHellTimeKills ( ) ;
StopSound ( SND_CHANNEL_DEMONIC , false ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case ENVIROSUIT :
{
2012-11-26 18:58:24 +00:00
hudPowerup = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Turn off the envirosuit sound
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > SetEnviroSuit ( false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Take off the helmet and lights
2012-11-28 15:47:07 +00:00
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > PostEventMS ( & EV_Remove , 0 ) ;
}
enviroSuitLight = NULL ;
break ;
}
2012-11-28 15:47:07 +00:00
case INVULNERABILITY :
{
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
StopSound ( SND_CHANNEL_DEMONIC , false ) ;
}
}
/*case HASTE: {
if ( common - > IsMultiplayer ( ) ) {
StopSound ( SND_CHANNEL_DEMONIC , false ) ;
}
} */
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : UpdatePowerUps
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdatePowerUps ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsClient ( ) )
{
for ( i = 0 ; i < MAX_POWERUPS ; i + + )
{
if ( ( inventory . powerups & ( 1 < < i ) ) & & inventory . powerupEndTime [ i ] > gameLocal . time )
{
switch ( i )
{
case ENVIROSUIT :
{
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
idAngles lightAng = firstPersonViewAxis . ToAngles ( ) ;
idVec3 lightOrg = firstPersonViewOrigin ;
2012-11-28 15:47:07 +00:00
const idDict * lightDef = gameLocal . FindEntityDefDict ( " envirosuit_light " , false ) ;
2012-11-26 18:58:24 +00:00
idVec3 enviroOffset = lightDef - > GetVector ( " enviro_offset " ) ;
idVec3 enviroAngleOffset = lightDef - > GetVector ( " enviro_angle_offset " ) ;
2012-11-28 15:47:07 +00:00
lightOrg + = ( enviroOffset . x * firstPersonViewAxis [ 0 ] ) ;
lightOrg + = ( enviroOffset . y * firstPersonViewAxis [ 1 ] ) ;
lightOrg + = ( enviroOffset . z * firstPersonViewAxis [ 2 ] ) ;
2012-11-26 18:58:24 +00:00
lightAng . pitch + = enviroAngleOffset . x ;
lightAng . yaw + = enviroAngleOffset . y ;
lightAng . roll + = enviroAngleOffset . z ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetOrigin ( lightOrg ) ;
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetAxis ( lightAng . ToMat3 ( ) ) ;
enviroSuitLight . GetEntity ( ) - > UpdateVisuals ( ) ;
enviroSuitLight . GetEntity ( ) - > Present ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
break ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( i ) & & inventory . powerupEndTime [ i ] < = gameLocal . time )
{
2012-11-26 18:58:24 +00:00
ClearPowerup ( i ) ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( health > 0 )
{
if ( powerUpSkin )
{
2012-11-26 18:58:24 +00:00
renderEntity . customSkin = powerUpSkin ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderEntity . customSkin = skin ;
}
}
2012-11-28 15:47:07 +00:00
if ( healthPool & & gameLocal . time > nextHealthPulse & & ! AI_DEAD & & health > 0 )
{
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ; // healthPool never be set on client
int amt = ( healthPool > 5.0f ) ? 5 : healthPool ;
health + = amt ;
2012-11-28 15:47:07 +00:00
if ( health > inventory . maxHealth )
{
2012-11-26 18:58:24 +00:00
health = inventory . maxHealth ;
healthPool = 0 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
healthPool - = amt ;
}
2012-11-28 15:47:07 +00:00
if ( healthPool < 1.0f )
{
2012-11-26 18:58:24 +00:00
healthPool = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
nextHealthPulse = gameLocal . time + HEALTHPULSE_TIME ;
healthPulse = true ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . inCinematic & & influenceActive = = 0 & & g_skill . GetInteger ( ) = = 3 & & gameLocal . time > nextHealthTake & & ! AI_DEAD & & health > g_healthTakeLimit . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ; // healthPool never be set on client
2012-11-28 15:47:07 +00:00
if ( ! PowerUpActive ( INVULNERABILITY ) )
{
health - = g_healthTakeAmt . GetInteger ( ) ;
if ( health < g_healthTakeLimit . GetInteger ( ) )
{
health = g_healthTakeLimit . GetInteger ( ) ;
}
2012-11-26 18:58:24 +00:00
}
nextHealthTake = gameLocal . time + g_healthTakeTime . GetInteger ( ) * 1000 ;
healthTake = true ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : ClearPowerUps
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ClearPowerUps ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_POWERUPS ; i + + )
{
if ( PowerUpActive ( i ) )
{
2012-11-26 18:58:24 +00:00
ClearPowerup ( i ) ;
}
}
inventory . ClearPowerUps ( ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > PostEventMS ( & EV_Remove , 0 ) ;
}
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveInventoryItem
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : GiveInventoryItem ( idDict * item , unsigned int giveFlags )
{
if ( common - > IsMultiplayer ( ) & & spectating )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( giveFlags & ITEM_GIVE_UPDATE_STATE )
{
inventory . items . Append ( new ( TAG_ENTITY ) idDict ( * item ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
const char * itemName = item - > GetString ( " inv_name " ) ;
if ( giveFlags & ITEM_GIVE_FEEDBACK )
{
if ( idStr : : Cmpn ( itemName , STRTABLE_ID , STRTABLE_ID_LENGTH ) = = 0 )
{
2012-11-26 18:58:24 +00:00
inventory . pickupItemNames . Append ( idLocalization : : GetString ( itemName ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
inventory . pickupItemNames . Append ( itemName ) ;
}
2012-11-28 15:47:07 +00:00
const char * icon = item - > GetString ( " inv_icon " ) ;
if ( hud ! = NULL )
{
2012-11-26 18:58:24 +00:00
hud - > ShowNewItem ( itemName , icon ) ;
}
}
// D3XP added to support powercells
2012-11-28 15:47:07 +00:00
if ( ( giveFlags & ITEM_GIVE_UPDATE_STATE ) & & item - > GetInt ( " inv_powercell " ) & & focusUI )
{
2012-11-26 18:58:24 +00:00
//Reset the powercell count
int powerCellCount = 0 ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < inventory . items . Num ( ) ; j + + )
{
idDict * item = inventory . items [ j ] ;
if ( item - > GetInt ( " inv_powercell " ) )
{
2012-11-26 18:58:24 +00:00
powerCellCount + + ;
}
}
focusUI - > SetStateInt ( " powercell_count " , powerCellCount ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : GiveInventoryItem
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : GiveInventoryItem ( const char * name )
{
2012-11-26 18:58:24 +00:00
idDict args ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
args . Set ( " classname " , name ) ;
args . Set ( " owner " , this - > name . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
gameLocal . SpawnEntityDef ( args ) ;
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveObjective
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GiveObjective ( const char * title , const char * text , const idMaterial * screenshot )
{
idObjectiveInfo & info = inventory . objectiveNames . Alloc ( ) ;
2012-11-26 18:58:24 +00:00
info . title = title ;
info . text = text ;
info . screenshot = screenshot ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
StartSound ( " snd_objectiveup " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > SetupObjective ( title , text , screenshot ) ;
hud - > ShowObjective ( false ) ;
objectiveUp = true ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : CompleteObjective
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : CompleteObjective ( const char * title )
{
2012-11-26 18:58:24 +00:00
int c = inventory . objectiveNames . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < c ; i + + )
{
if ( idStr : : Icmp ( inventory . objectiveNames [ i ] . title , title ) = = 0 )
{
2012-11-26 18:58:24 +00:00
inventory . objectiveNames . RemoveIndex ( i ) ;
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
StartSound ( " snd_objectiveup " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > SetupObjectiveComplete ( title ) ;
hud - > ShowObjective ( true ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveVideo
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GiveVideo ( const idDeclVideo * video , const char * itemName )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( video = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int oldNumVideos = inventory . videos . Num ( ) ;
inventory . videos . AddUnique ( video ) ;
2012-11-28 15:47:07 +00:00
if ( oldNumVideos < inventory . videos . Num ( ) )
{
2012-11-26 18:58:24 +00:00
GetAchievementManager ( ) . EventCompletesAchievement ( ACHIEVEMENT_WATCH_ALL_VIDEOS ) ;
}
2012-11-28 15:47:07 +00:00
if ( itemName ! = NULL & & itemName [ 0 ] ! = 0 )
{
2012-11-26 18:58:24 +00:00
inventory . pickupItemNames . Append ( itemName ) ;
}
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > DownloadVideo ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveSecurity
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GiveSecurity ( const char * security )
{
2012-11-26 18:58:24 +00:00
GetPDA ( ) - > SetSecurity ( security ) ;
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > UpdatedSecurity ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveEmail
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GiveEmail ( const idDeclEmail * email )
{
if ( email = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . emails . AddUnique ( email ) ;
GetPDA ( ) - > AddEmail ( email ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// TODO_SPARTY: hook up new email notification in new hud
//if ( hud ) {
// hud->HandleNamedEvent( "emailPickup" );
//}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GivePDA
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GivePDA ( const idDeclPDA * pda , const char * securityItem )
{
if ( common - > IsMultiplayer ( ) & & spectating )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( securityItem ! = NULL & & securityItem [ 0 ] ! = 0 )
{
2012-11-26 18:58:24 +00:00
inventory . pdaSecurity . AddUnique ( securityItem ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Just to make sure they want the default player spawn defined pda.
// Some what of a hack, so i dont have to change any map scripts that initially give
// the player "personal" pda.
2012-11-28 15:47:07 +00:00
if ( pda = = NULL | | idStr : : Icmp ( pda - > GetName ( ) , " personal " ) = = 0 )
{
pda = static_cast < const idDeclPDA * > ( declManager - > FindType ( DECL_PDA , spawnArgs . GetString ( " pda_name " , " personal " ) ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( pda = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int oldNumPDAs = inventory . pdas . Num ( ) ;
inventory . pdas . AddUnique ( pda ) ;
int newNumPDAs = inventory . pdas . Num ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set the stat for # of PDAs...
// Only increment the PDA stat if we've added a new one....
2012-11-28 15:47:07 +00:00
if ( oldNumPDAs < newNumPDAs )
{
switch ( GetExpansionType ( ) )
{
case GAME_BASE :
GetAchievementManager ( ) . EventCompletesAchievement ( ACHIEVEMENT_PDAS_BASE ) ;
break ;
case GAME_D3XP :
GetAchievementManager ( ) . EventCompletesAchievement ( ACHIEVEMENT_PDAS_ROE ) ;
break ;
case GAME_D3LE :
GetAchievementManager ( ) . EventCompletesAchievement ( ACHIEVEMENT_PDAS_LE ) ;
break ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Copy any videos over
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < pda - > GetNumVideos ( ) ; i + + )
{
const idDeclVideo * video = pda - > GetVideoByIndex ( i ) ;
if ( video ! = NULL )
{
2012-11-26 18:58:24 +00:00
inventory . videos . AddUnique ( video ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// This is kind of a hack, but it works nicely
// We don't want to display the 'you got a new pda' message during a map load
2012-11-28 15:47:07 +00:00
if ( gameLocal . GetFrameNum ( ) > 10 )
{
const char * sec = pda - > GetSecurity ( ) ;
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > DownloadPDA ( pda , ( sec ! = NULL & & sec [ 0 ] ! = 0 ) ? true : false ) ;
}
2012-11-28 15:47:07 +00:00
if ( inventory . pdas . Num ( ) = = 1 )
{
2012-11-26 18:58:24 +00:00
GetPDA ( ) - > RemoveAddedEmailsAndVideos ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! objectiveSystemOpen )
{
2012-11-26 18:58:24 +00:00
TogglePDA ( ) ;
}
//ShowTip( spawnArgs.GetString( "text_infoTitle" ), spawnArgs.GetString( "text_firstPDA" ), true );
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : FindInventoryItem
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDict * idPlayer : : FindInventoryItem ( const char * name )
{
for ( int i = 0 ; i < inventory . items . Num ( ) ; i + + )
{
const char * iname = inventory . items [ i ] - > GetString ( " inv_name " ) ;
2012-12-11 22:48:55 +00:00
if ( iname ! = NULL & & * iname ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
if ( idStr : : Icmp ( name , iname ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return inventory . items [ i ] ;
}
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : FindInventoryItem
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDict * idPlayer : : FindInventoryItem ( int index )
{
if ( index < = inventory . items . Num ( ) )
{
2012-11-26 18:58:24 +00:00
return inventory . items [ index ] ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GetNumInventoryItems
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPlayer : : GetNumInventoryItems ( )
{
2012-11-26 18:58:24 +00:00
return inventory . items . Num ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : RemoveInventoryItem
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RemoveInventoryItem ( const char * name )
{
2012-11-26 18:58:24 +00:00
//Hack for localization
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( name , " Pwr Cell " ) )
{
2012-11-26 18:58:24 +00:00
name = idLocalization : : GetString ( " #str_00101056 " ) ;
}
2012-11-28 15:47:07 +00:00
idDict * item = FindInventoryItem ( name ) ;
if ( item )
{
2012-11-26 18:58:24 +00:00
RemoveInventoryItem ( item ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : RemoveInventoryItem
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RemoveInventoryItem ( idDict * item )
{
2012-11-26 18:58:24 +00:00
inventory . items . Remove ( item ) ;
2012-11-28 15:47:07 +00:00
if ( item - > GetInt ( " inv_powercell " ) & & focusUI )
{
2012-11-26 18:58:24 +00:00
//Reset the powercell count
int powerCellCount = 0 ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < inventory . items . Num ( ) ; j + + )
{
idDict * item = inventory . items [ j ] ;
if ( item - > GetInt ( " inv_powercell " ) )
{
2012-11-26 18:58:24 +00:00
powerCellCount + + ;
}
}
focusUI - > SetStateInt ( " powercell_count " , powerCellCount ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete item ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GiveItem
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GiveItem ( const char * itemname )
{
2012-11-26 18:58:24 +00:00
idDict args ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
args . Set ( " classname " , itemname ) ;
args . Set ( " owner " , name . c_str ( ) ) ;
gameLocal . SpawnEntityDef ( args ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : SlotForWeapon
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPlayer : : SlotForWeapon ( const char * weaponName )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
const char * weap = spawnArgs . GetString ( va ( " def_weapon%d " , i ) ) ;
if ( ! idStr : : Cmp ( weap , weaponName ) )
{
2012-11-26 18:58:24 +00:00
return i ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// not found
return - 1 ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Reload
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Reload ( )
{
if ( spectating | | gameLocal . inCinematic | | influenceActive )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) & & ! IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) & & weapon . GetEntity ( ) - > IsLinked ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > Reload ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : NextBestWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : NextBestWeapon ( )
{
const char * weap ;
2012-11-26 18:58:24 +00:00
int w = MAX_WEAPONS ;
2012-11-28 15:47:07 +00:00
if ( ! weaponEnabled )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
while ( w > 0 )
{
2012-11-26 18:58:24 +00:00
w - - ;
2012-11-28 15:47:07 +00:00
if ( w = = weapon_flashlight )
{
2012-11-26 18:58:24 +00:00
continue ;
}
weap = spawnArgs . GetString ( va ( " def_weapon%d " , w ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! weap [ 0 ] | | ( ( inventory . weapons & ( 1 < < w ) ) = = 0 ) | | ( ! inventory . HasAmmo ( weap , true , this ) ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! spawnArgs . GetBool ( va ( " weapon%d_best " , w ) ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
//Some weapons will report having ammo but the clip is empty and
2012-11-26 18:58:24 +00:00
//will not have enough to fill the clip (i.e. Double Barrel Shotgun with 1 round left)
//We need to skip these weapons because they cannot be used
2012-11-28 15:47:07 +00:00
if ( inventory . HasEmptyClipCannotRefill ( weap , this ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
break ;
}
idealWeapon = w ;
weaponSwitchTime = gameLocal . time + WEAPON_SWITCH_DELAY ;
UpdateHudWeapon ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : NextWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : NextWeapon ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! weaponEnabled | | spectating | | hiddenWeapon | | gameLocal . inCinematic | | gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) | | health < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we have any weapons
2012-11-28 15:47:07 +00:00
if ( ! inventory . weapons )
{
2012-11-26 18:58:24 +00:00
return ;
}
int w = idealWeapon . Get ( ) ;
2012-11-28 15:47:07 +00:00
while ( 1 )
{
2012-11-26 18:58:24 +00:00
w + + ;
2012-11-28 15:47:07 +00:00
if ( w > = MAX_WEAPONS )
{
2012-11-26 18:58:24 +00:00
w = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( w = = idealWeapon )
{
2012-11-26 18:58:24 +00:00
w = weapon_fists ;
break ;
}
2012-11-28 15:47:07 +00:00
if ( ( inventory . weapons & ( 1 < < w ) ) = = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
const char * weap = spawnArgs . GetString ( va ( " def_weapon%d " , w ) ) ;
if ( ! spawnArgs . GetBool ( va ( " weapon%d_cycle " , w ) ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! weap [ 0 ] )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( inventory . HasAmmo ( weap , true , this ) | | w = = weapon_bloodstone )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ( w ! = currentWeapon ) & & ( w ! = idealWeapon ) )
{
2012-11-26 18:58:24 +00:00
idealWeapon = w ;
weaponSwitchTime = gameLocal . time + WEAPON_SWITCH_DELAY ;
UpdateHudWeapon ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : PrevWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : PrevWeapon ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! weaponEnabled | | spectating | | hiddenWeapon | | gameLocal . inCinematic | | gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) | | health < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we have any weapons
2012-11-28 15:47:07 +00:00
if ( ! inventory . weapons )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int w = idealWeapon . Get ( ) ;
2012-11-28 15:47:07 +00:00
while ( 1 )
{
2012-11-26 18:58:24 +00:00
w - - ;
2012-11-28 15:47:07 +00:00
if ( w < 0 )
{
2012-11-26 18:58:24 +00:00
w = MAX_WEAPONS - 1 ;
}
2012-11-28 15:47:07 +00:00
if ( w = = idealWeapon )
{
2012-11-26 18:58:24 +00:00
w = weapon_fists ;
break ;
}
2012-11-28 15:47:07 +00:00
if ( ( inventory . weapons & ( 1 < < w ) ) = = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
const char * weap = spawnArgs . GetString ( va ( " def_weapon%d " , w ) ) ;
if ( ! spawnArgs . GetBool ( va ( " weapon%d_cycle " , w ) ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! weap [ 0 ] )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( inventory . HasAmmo ( weap , true , this ) | | w = = weapon_bloodstone )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ( w ! = currentWeapon ) & & ( w ! = idealWeapon ) )
{
2012-11-26 18:58:24 +00:00
idealWeapon = w ;
weaponSwitchTime = gameLocal . time + WEAPON_SWITCH_DELAY ;
UpdateHudWeapon ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : SelectWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SelectWeapon ( int num , bool force )
{
const char * weap ;
if ( ! weaponEnabled | | spectating | | gameLocal . inCinematic | | health < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ( num < 0 ) | | ( num > = MAX_WEAPONS ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( num = = weapon_flashlight )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ( num ! = weapon_pda ) & & gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) )
{
2012-11-26 18:58:24 +00:00
num = weapon_fists ;
hiddenWeapon ^ = 1 ;
2012-11-28 15:47:07 +00:00
if ( hiddenWeapon & & weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > RaiseWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
//Is the weapon a toggle weapon
WeaponToggle_t * weaponToggle ;
2012-11-28 15:47:07 +00:00
if ( weaponToggles . Get ( va ( " weapontoggle%d " , num ) , & weaponToggle ) )
{
2012-11-26 18:58:24 +00:00
int weaponToggleIndex = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//Find the current Weapon in the list
int currentIndex = - 1 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < weaponToggle - > toggleList . Num ( ) ; i + + )
{
if ( weaponToggle - > toggleList [ i ] = = idealWeapon )
{
2012-11-26 18:58:24 +00:00
currentIndex = i ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( currentIndex = = - 1 )
{
2012-11-26 18:58:24 +00:00
//Didn't find the current weapon so select the first item
weaponToggleIndex = weaponToggle - > lastUsed ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
//Roll to the next available item in the list
weaponToggleIndex = currentIndex ;
weaponToggleIndex + + ;
2012-11-28 15:47:07 +00:00
if ( weaponToggleIndex > = weaponToggle - > toggleList . Num ( ) )
{
2012-11-26 18:58:24 +00:00
weaponToggleIndex = 0 ;
}
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < weaponToggle - > toggleList . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
int weapNum = weaponToggle - > toggleList [ weaponToggleIndex ] ;
//Is it available
2012-11-28 15:47:07 +00:00
if ( inventory . weapons & ( 1 < < weapNum ) )
{
2012-11-26 18:58:24 +00:00
//Do we have ammo for it
2012-11-28 15:47:07 +00:00
if ( inventory . HasAmmo ( spawnArgs . GetString ( va ( " def_weapon%d " , weapNum ) ) , true , this ) | | spawnArgs . GetBool ( va ( " weapon%d_allowempty " , weapNum ) ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weaponToggleIndex + + ;
2012-11-28 15:47:07 +00:00
if ( weaponToggleIndex > = weaponToggle - > toggleList . Num ( ) )
{
2012-11-26 18:58:24 +00:00
weaponToggleIndex = 0 ;
}
}
weaponToggle - > lastUsed = weaponToggleIndex ;
num = weaponToggle - > toggleList [ weaponToggleIndex ] ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weap = spawnArgs . GetString ( va ( " def_weapon%d " , num ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! weap [ 0 ] )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " Invalid weapon \n " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( force | | ( inventory . weapons & ( 1 < < num ) ) )
{
if ( ! inventory . HasAmmo ( weap , true , this ) & & ! spawnArgs . GetBool ( va ( " weapon%d_allowempty " , num ) ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ( previousWeapon > = 0 ) & & ( idealWeapon = = num ) & & ( spawnArgs . GetBool ( va ( " weapon%d_toggle " , num ) ) ) )
{
2012-11-26 18:58:24 +00:00
weap = spawnArgs . GetString ( va ( " def_weapon%d " , previousWeapon ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! inventory . HasAmmo ( weap , true , this ) & & ! spawnArgs . GetBool ( va ( " weapon%d_allowempty " , previousWeapon ) ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
idealWeapon = previousWeapon ;
2012-11-28 15:47:07 +00:00
}
else if ( ( weapon_pda > = 0 ) & & ( num = = weapon_pda ) & & ( inventory . pdas . Num ( ) = = 0 ) )
{
2012-11-26 18:58:24 +00:00
ShowTip ( spawnArgs . GetString ( " text_infoTitle " ) , spawnArgs . GetString ( " text_noPDA " ) , true ) ;
return ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idealWeapon = num ;
}
UpdateHudWeapon ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : DropWeapon
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : DropWeapon ( bool died )
{
2012-11-26 18:58:24 +00:00
idVec3 forward , up ;
int inclip , ammoavailable ;
2012-11-28 15:47:07 +00:00
if ( died = = false )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( spectating | | weaponGone | | weapon . GetEntity ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ( ! died & & ! weapon . GetEntity ( ) - > IsReady ( ) ) | | weapon . GetEntity ( ) - > IsReloading ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
// ammoavailable is how many shots we can fire
// inclip is which amount is in clip right now
ammoavailable = weapon . GetEntity ( ) - > AmmoAvailable ( ) ;
inclip = weapon . GetEntity ( ) - > AmmoInClip ( ) ;
// don't drop a grenade if we have none left
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( idWeapon : : GetAmmoNameForNum ( weapon . GetEntity ( ) - > GetAmmoType ( ) ) , " ammo_grenades " ) & & ( ammoavailable - inclip < = 0 ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ammoavailable + = inclip ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// expect an ammo setup that makes sense before doing any dropping
// ammoavailable is -1 for infinite ammo, and weapons like chainsaw
// a bad ammo config usually indicates a bad weapon state, so we should not drop
// used to be an assertion check, but it still happens in edge cases
2012-11-28 15:47:07 +00:00
if ( ( ammoavailable ! = - 1 ) & & ( ammoavailable < 0 ) )
{
2012-11-26 18:58:24 +00:00
common - > DPrintf ( " idPlayer::DropWeapon: bad ammo setup \n " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
idEntity * item = NULL ;
if ( died )
{
2012-11-26 18:58:24 +00:00
// ain't gonna throw you no weapon if I'm dead
item = weapon . GetEntity ( ) - > DropItem ( vec3_origin , 0 , WEAPON_DROP_TIME , died ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
viewAngles . ToVectors ( & forward , NULL , & up ) ;
item = weapon . GetEntity ( ) - > DropItem ( 250.0f * forward + 150.0f * up , 500 , WEAPON_DROP_TIME , died ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! item )
{
2012-11-26 18:58:24 +00:00
return ;
}
// set the appropriate ammo in the dropped object
2012-11-28 15:47:07 +00:00
const idKeyValue * keyval = item - > spawnArgs . MatchPrefix ( " inv_ammo_ " ) ;
if ( keyval )
{
2012-11-26 18:58:24 +00:00
item - > spawnArgs . SetInt ( keyval - > GetKey ( ) , ammoavailable ) ;
idStr inclipKey = keyval - > GetKey ( ) ;
inclipKey . Insert ( " inclip_ " , 4 ) ;
2012-11-28 15:47:07 +00:00
inclipKey . Insert ( va ( " %.2d " , currentWeapon ) , 11 ) ;
2012-11-26 18:58:24 +00:00
item - > spawnArgs . SetInt ( inclipKey , inclip ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! died )
{
2012-11-26 18:58:24 +00:00
// remove from our local inventory completely
inventory . Drop ( spawnArgs , item - > spawnArgs . GetString ( " inv_weapon " ) , - 1 ) ;
weapon . GetEntity ( ) - > ResetAmmoClip ( ) ;
NextWeapon ( ) ;
weapon . GetEntity ( ) - > WeaponStolen ( ) ;
weaponGone = true ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : StealWeapon
steal the target player ' s current weapon
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : StealWeapon ( idPlayer * player )
{
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure there's something to steal
2012-11-28 15:47:07 +00:00
idWeapon * player_weapon = static_cast < idWeapon * > ( player - > weapon . GetEntity ( ) ) ;
if ( ! player_weapon | | ! player_weapon - > CanDrop ( ) | | weaponGone )
{
2012-11-26 18:58:24 +00:00
return ;
}
// steal - we need to effectively force the other player to abandon his weapon
int newweap = player - > currentWeapon ;
2012-11-28 15:47:07 +00:00
if ( newweap = = - 1 )
{
2012-11-26 18:58:24 +00:00
return ;
}
// might be just dropped - check inventory
2012-11-28 15:47:07 +00:00
if ( ! ( player - > inventory . weapons & ( 1 < < newweap ) ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const char * weapon_classname = spawnArgs . GetString ( va ( " def_weapon%d " , newweap ) ) ;
2012-11-26 18:58:24 +00:00
assert ( weapon_classname ) ;
int ammoavailable = player - > weapon . GetEntity ( ) - > AmmoAvailable ( ) ;
int inclip = player - > weapon . GetEntity ( ) - > AmmoInClip ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ammoavailable + = inclip ;
2012-11-28 15:47:07 +00:00
if ( ( ammoavailable ! = - 1 ) & & ( ammoavailable < 0 ) )
{
2012-11-26 18:58:24 +00:00
// see DropWeapon
common - > DPrintf ( " idPlayer::StealWeapon: bad ammo setup \n " ) ;
// we still steal the weapon, so let's use the default ammo levels
inclip = - 1 ;
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * decl = gameLocal . FindEntityDef ( weapon_classname ) ;
2012-11-26 18:58:24 +00:00
assert ( decl ) ;
2012-11-28 15:47:07 +00:00
const idKeyValue * keypair = decl - > dict . MatchPrefix ( " inv_ammo_ " ) ;
2012-11-26 18:58:24 +00:00
assert ( keypair ) ;
ammoavailable = atoi ( keypair - > GetValue ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
player - > weapon . GetEntity ( ) - > WeaponStolen ( ) ;
player - > inventory . Drop ( player - > spawnArgs , NULL , newweap ) ;
player - > SelectWeapon ( weapon_fists , false ) ;
// in case the robbed player is firing rounds with a continuous fire weapon like the chaingun/plasma etc.
// this will ensure the firing actually stops
player - > weaponGone = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// give weapon, setup the ammo count
Give ( " weapon " , weapon_classname , ITEM_GIVE_FEEDBACK | ITEM_GIVE_UPDATE_STATE ) ;
ammo_t ammo_i = player - > inventory . AmmoIndexForWeaponClass ( weapon_classname , NULL ) ;
idealWeapon = newweap ;
const int currentAmmo = inventory . GetInventoryAmmoForType ( ammo_i ) ;
inventory . SetInventoryAmmoForType ( ammo_i , currentAmmo + ammoavailable ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : ActiveGui
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idUserInterface * idPlayer : : ActiveGui ( )
{
if ( objectiveSystemOpen )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return focusUI ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Weapon_Combat
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Weapon_Combat ( )
{
if ( influenceActive | | ! weaponEnabled | | gameLocal . inCinematic | | privateCameraView )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > RaiseWeapon ( ) ;
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) - > IsReloading ( ) )
{
if ( ! AI_RELOAD )
{
2012-11-26 18:58:24 +00:00
AI_RELOAD = true ;
SetState ( " ReloadWeapon " ) ;
UpdateScript ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
AI_RELOAD = false ;
}
2012-11-28 15:47:07 +00:00
if ( idealWeapon = = weapon_soulcube & & soulCubeProjectile . GetEntity ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
idealWeapon = currentWeapon ;
}
2012-11-28 15:47:07 +00:00
if ( idealWeapon ! = currentWeapon & & idealWeapon . Get ( ) < MAX_WEAPONS )
{
if ( weaponCatchup )
{
2012-11-26 18:58:24 +00:00
assert ( common - > IsClient ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
currentWeapon = idealWeapon . Get ( ) ;
weaponGone = false ;
animPrefix = spawnArgs . GetString ( va ( " def_weapon%d " , currentWeapon ) ) ;
weapon . GetEntity ( ) - > GetWeaponDef ( animPrefix , inventory . GetClipAmmoForWeapon ( currentWeapon ) ) ;
animPrefix . Strip ( " weapon_ " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > NetCatchup ( ) ;
2012-11-28 15:47:07 +00:00
const function_t * newstate = GetScriptFunction ( " NetCatchup " ) ;
if ( newstate )
{
2012-11-26 18:58:24 +00:00
SetState ( newstate ) ;
UpdateScript ( ) ;
}
2012-11-28 15:47:07 +00:00
weaponCatchup = false ;
}
else
{
if ( weapon . GetEntity ( ) - > IsReady ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > PutAway ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) - > IsHolstered ( ) )
{
2012-11-26 18:58:24 +00:00
assert ( idealWeapon . Get ( ) > = 0 ) ;
assert ( idealWeapon . Get ( ) < MAX_WEAPONS ) ;
2012-11-28 15:47:07 +00:00
if ( currentWeapon ! = weapon_pda & & ! spawnArgs . GetBool ( va ( " weapon%d_toggle " , currentWeapon ) ) )
{
2012-11-26 18:58:24 +00:00
previousWeapon = currentWeapon ;
}
currentWeapon = idealWeapon . Get ( ) ;
weaponGone = false ;
animPrefix = spawnArgs . GetString ( va ( " def_weapon%d " , currentWeapon ) ) ;
weapon . GetEntity ( ) - > GetWeaponDef ( animPrefix , inventory . GetClipAmmoForWeapon ( currentWeapon ) ) ;
animPrefix . Strip ( " weapon_ " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > Raise ( ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
weaponGone = false ; // if you drop and re-get weap, you may miss the = false above
if ( weapon . GetEntity ( ) - > IsHolstered ( ) )
{
if ( ! weapon . GetEntity ( ) - > AmmoAvailable ( ) )
{
2012-11-26 18:58:24 +00:00
// weapons can switch automatically if they have no more ammo
NextBestWeapon ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > Raise ( ) ;
state = GetScriptFunction ( " RaiseWeapon " ) ;
2012-11-28 15:47:07 +00:00
if ( state )
{
2012-11-26 18:58:24 +00:00
SetState ( state ) ;
}
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for attack
AI_WEAPON_FIRED = false ;
2012-11-28 15:47:07 +00:00
if ( ! influenceActive )
{
if ( ( usercmd . buttons & BUTTON_ATTACK ) & & ! weaponGone )
{
2012-11-26 18:58:24 +00:00
FireWeapon ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( oldButtons & BUTTON_ATTACK )
{
2012-11-26 18:58:24 +00:00
AI_ATTACK_HELD = false ;
weapon . GetEntity ( ) - > EndAttack ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update our ammo clip in our inventory
2012-11-28 15:47:07 +00:00
if ( ( currentWeapon > = 0 ) & & ( currentWeapon < MAX_WEAPONS ) )
{
2012-11-26 18:58:24 +00:00
inventory . SetClipAmmoForWeapon ( currentWeapon , weapon . GetEntity ( ) - > AmmoInClip ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Weapon_NPC
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Weapon_NPC ( )
{
if ( idealWeapon ! = currentWeapon )
{
2012-11-26 18:58:24 +00:00
Weapon_Combat ( ) ;
}
StopFiring ( ) ;
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
2012-11-28 15:47:07 +00:00
bool wasDown = ( oldButtons & ( BUTTON_ATTACK | BUTTON_USE ) ) ! = 0 ;
bool isDown = ( usercmd . buttons & ( BUTTON_ATTACK | BUTTON_USE ) ) ! = 0 ;
if ( isDown & & ! wasDown )
{
2012-11-26 18:58:24 +00:00
buttonMask | = BUTTON_ATTACK ;
focusCharacter - > TalkTo ( this ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : LowerWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : LowerWeapon ( )
{
if ( weapon . GetEntity ( ) & & ! weapon . GetEntity ( ) - > IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : RaiseWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RaiseWeapon ( )
{
if ( weapon . GetEntity ( ) & & weapon . GetEntity ( ) - > IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > RaiseWeapon ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : WeaponLoweringCallback
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : WeaponLoweringCallback ( )
{
2012-11-26 18:58:24 +00:00
SetState ( " LowerWeapon " ) ;
UpdateScript ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : WeaponRisingCallback
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : WeaponRisingCallback ( )
{
2012-11-26 18:58:24 +00:00
SetState ( " RaiseWeapon " ) ;
UpdateScript ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Weapon_GUI
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Weapon_GUI ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! objectiveSystemOpen )
{
if ( idealWeapon ! = currentWeapon )
{
2012-11-26 18:58:24 +00:00
Weapon_Combat ( ) ;
}
StopFiring ( ) ;
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// disable click prediction for the GUIs. handy to check the state sync does the right thing
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) & & ! net_clientPredictGUI . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
bool wasDown = ( oldButtons & ( BUTTON_ATTACK | BUTTON_USE ) ) ! = 0 ;
bool isDown = ( usercmd . buttons & ( BUTTON_ATTACK | BUTTON_USE ) ) ! = 0 ;
if ( isDown ! = wasDown )
{
const char * command = NULL ;
idUserInterface * ui = ActiveGui ( ) ;
if ( ui )
{
2012-11-26 18:58:24 +00:00
bool updateVisuals = false ;
sysEvent_t ev = sys - > GenerateMouseButtonEvent ( 1 , isDown ) ;
command = ui - > HandleEvent ( & ev , gameLocal . time , & updateVisuals ) ;
2012-11-28 15:47:07 +00:00
if ( updateVisuals & & focusGUIent & & ui = = focusUI )
{
2012-11-26 18:58:24 +00:00
focusGUIent - > UpdateVisuals ( ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
// we predict enough, but don't want to execute commands
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// HACK - Check to see who is activating the frag chamber. Im sorry.
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & focusGUIent )
{
if ( strcmp ( focusGUIent - > GetName ( ) , " chamber_gui_console " ) = = 0 & & strcmp ( command , " ; runScript chamber_trigger " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
gameLocal . playerActivateFragChamber = this ;
}
}
2012-11-28 15:47:07 +00:00
if ( focusGUIent )
{
2012-11-26 18:58:24 +00:00
HandleGuiCommands ( focusGUIent , command ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
HandleGuiCommands ( this , command ) ;
}
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateWeapon ( )
{
if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ! spectating ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
// clients need to wait till the weapon and it's world model entity
// are present and synchronized ( weapon.worldModel idEntityPtr to idAnimatedEntity )
2012-11-28 15:47:07 +00:00
if ( ! weapon . GetEntity ( ) - > IsWorldModelReady ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// always make sure the weapon is correctly setup before accessing it
2012-11-28 15:47:07 +00:00
if ( ! weapon . GetEntity ( ) - > IsLinked ( ) )
{
if ( idealWeapon ! = - 1 )
{
2012-11-26 18:58:24 +00:00
animPrefix = spawnArgs . GetString ( va ( " def_weapon%d " , idealWeapon . Get ( ) ) ) ;
int ammoInClip = inventory . GetClipAmmoForWeapon ( idealWeapon . Get ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & respawning )
{
2012-11-26 18:58:24 +00:00
// Do not load ammo into the clip here on MP respawn, as it will be done
// elsewhere. If we take ammo out here then the player will end up losing
// a clip of ammo for their initial weapon upon respawn.
ammoInClip = 0 ;
}
weapon . GetEntity ( ) - > GetWeaponDef ( animPrefix , ammoInClip ) ;
assert ( weapon . GetEntity ( ) - > IsLinked ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
if ( hiddenWeapon & & tipUp & & usercmd . buttons & BUTTON_ATTACK )
{
2012-11-26 18:58:24 +00:00
HideTip ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_dragEntity . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
StopFiring ( ) ;
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
dragEntity . Update ( this ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ActiveGui ( ) )
{
2012-11-26 18:58:24 +00:00
// gui handling overrides weapon use
Weapon_GUI ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( focusCharacter & & ( focusCharacter - > health > 0 ) )
{
2012-11-26 18:58:24 +00:00
Weapon_NPC ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Weapon_Combat ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( hiddenWeapon )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update weapon state, particles, dlights, etc
weapon . GetEntity ( ) - > PresentWeapon ( CanShowWeaponViewmodel ( ) ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateFlashLight
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateFlashlight ( )
{
if ( idealWeapon = = weapon_flashlight )
{
2012-11-26 18:58:24 +00:00
// force classic flashlight to go away
NextWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! flashlight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! flashlight . GetEntity ( ) - > GetOwner ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Don't update the flashlight if dead in MP.
// Otherwise you can see a floating flashlight worldmodel near player's skeletons.
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
if ( health < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Flashlight has an infinite battery in multiplayer.
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) )
{
if ( flashlight . GetEntity ( ) - > lightOn )
{
if ( flashlight_batteryDrainTimeMS . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
flashlightBattery - = ( gameLocal . time - gameLocal . previousTime ) ;
2012-11-28 15:47:07 +00:00
if ( flashlightBattery < 0 )
{
2012-11-26 18:58:24 +00:00
FlashlightOff ( ) ;
flashlightBattery = 0 ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( flashlightBattery < flashlight_batteryDrainTimeMS . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
flashlightBattery + = ( gameLocal . time - gameLocal . previousTime ) * Max ( 1 , ( flashlight_batteryDrainTimeMS . GetInteger ( ) / flashlight_batteryChargeTimeMS . GetInteger ( ) ) ) ;
2012-11-28 15:47:07 +00:00
if ( flashlightBattery > flashlight_batteryDrainTimeMS . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
flashlightBattery = flashlight_batteryDrainTimeMS . GetInteger ( ) ;
}
}
}
}
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > UpdateFlashlight ( this ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
// clients need to wait till the weapon and it's world model entity
// are present and synchronized ( weapon.worldModel idEntityPtr to idAnimatedEntity )
2012-11-28 15:47:07 +00:00
if ( ! flashlight . GetEntity ( ) - > IsWorldModelReady ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// always make sure the weapon is correctly setup before accessing it
2012-11-28 15:47:07 +00:00
if ( ! flashlight . GetEntity ( ) - > IsLinked ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > GetWeaponDef ( " weapon_flashlight_new " , 0 ) ;
flashlight . GetEntity ( ) - > SetIsPlayerFlashlight ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// adjust position / orientation of flashlight
2012-11-28 15:47:07 +00:00
idAnimatedEntity * worldModel = flashlight . GetEntity ( ) - > GetWorldModel ( ) ;
2012-11-26 18:58:24 +00:00
worldModel - > BindToJoint ( this , " Chest " , true ) ;
// Don't interpolate the flashlight world model in mp, let it bind like normal.
worldModel - > SetUseClientInterpolation ( false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( flashlight . GetEntity ( ) - > IsLinked ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// this positions the third person flashlight model! (as seen in the mirror)
2012-11-28 15:47:07 +00:00
idAnimatedEntity * worldModel = flashlight . GetEntity ( ) - > GetWorldModel ( ) ;
2012-11-26 18:58:24 +00:00
static const idVec3 fl_pos = idVec3 ( 3.0f , 9.0f , 2.0f ) ;
worldModel - > GetPhysics ( ) - > SetOrigin ( fl_pos ) ;
static float fl_pitch = 0.0f ;
static float fl_yaw = 0.0f ;
static float fl_roll = 0.0f ;
static idAngles ang = ang_zero ;
ang . Set ( fl_pitch , fl_yaw , fl_roll ) ;
worldModel - > GetPhysics ( ) - > SetAxis ( ang . ToMat3 ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) - > lightOn )
{
if ( ( flashlightBattery < flashlight_batteryChargeTimeMS . GetInteger ( ) / 2 ) & & ( gameLocal . random . RandomFloat ( ) < flashlight_batteryFlickerPercent . GetFloat ( ) ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > RemoveMuzzleFlashlight ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > MuzzleFlashLight ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > PresentWeapon ( true ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) | | gameLocal . inCinematic | | spectating | | fl . hidden )
{
2012-11-26 18:58:24 +00:00
worldModel - > Hide ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
worldModel - > Show ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : FlashlightOn
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : FlashlightOn ( )
{
if ( ! flashlight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( flashlightBattery < idMath : : Ftoi ( flashlight_minActivatePercent . GetFloat ( ) * flashlight_batteryDrainTimeMS . GetFloat ( ) ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . inCinematic )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) - > lightOn )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
flashlight - > FlashlightOn ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : FlashlightOff
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : FlashlightOff ( )
{
if ( ! flashlight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! flashlight . GetEntity ( ) - > lightOn )
{
2012-11-26 18:58:24 +00:00
return ;
}
flashlight - > FlashlightOff ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : SpectateFreeFly
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SpectateFreeFly ( bool force )
{
idPlayer * player ;
2012-11-26 18:58:24 +00:00
idVec3 newOrig ;
idVec3 spawn_origin ;
idAngles spawn_angles ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
player = gameLocal . GetClientByNum ( spectator ) ;
2012-11-28 15:47:07 +00:00
if ( force | | gameLocal . time > lastSpectateChange )
{
2012-11-26 18:58:24 +00:00
spectator = entityNumber ;
2012-11-28 15:47:07 +00:00
if ( player ! = NULL & & player ! = this & & ! player - > spectating & & ! player - > IsInTeleport ( ) )
{
2012-11-26 18:58:24 +00:00
newOrig = player - > GetPhysics ( ) - > GetOrigin ( ) ;
2012-11-28 15:47:07 +00:00
if ( player - > physicsObj . IsCrouching ( ) )
{
2012-11-26 18:58:24 +00:00
newOrig [ 2 ] + = pm_crouchviewheight . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
newOrig [ 2 ] + = pm_normalviewheight . GetFloat ( ) ;
}
newOrig [ 2 ] + = SPECTATE_RAISE ;
idBounds b = idBounds ( vec3_origin ) . Expand ( pm_spectatebbox . GetFloat ( ) * 0.5f ) ;
idVec3 start = player - > GetPhysics ( ) - > GetOrigin ( ) ;
start [ 2 ] + = pm_spectatebbox . GetFloat ( ) * 0.5f ;
trace_t t ;
// assuming spectate bbox is inside stand or crouch box
gameLocal . clip . TraceBounds ( t , start , newOrig , b , MASK_PLAYERSOLID , player ) ;
newOrig . Lerp ( start , newOrig , t . fraction ) ;
SetOrigin ( newOrig ) ;
idAngles angle = player - > viewAngles ;
angle [ 2 ] = 0 ;
SetViewAngles ( angle ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
SelectInitialSpawnPoint ( spawn_origin , spawn_angles ) ;
spawn_origin [ 2 ] + = pm_normalviewheight . GetFloat ( ) ;
spawn_origin [ 2 ] + = SPECTATE_RAISE ;
SetOrigin ( spawn_origin ) ;
SetViewAngles ( spawn_angles ) ;
// This may happen during GAMESTATE_STARTUP in mp, so we must set the spawnAngles too.
spawnAngles = spawn_angles ;
2012-11-28 15:47:07 +00:00
if ( force = = false )
{
2012-11-26 18:58:24 +00:00
// only do this if they hit the cycle button.
2012-11-28 15:47:07 +00:00
if ( common - > IsServer ( ) )
{
if ( player ! = NULL )
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
msg . WriteFloat ( GetPhysics ( ) - > GetOrigin ( ) [ 0 ] ) ;
msg . WriteFloat ( GetPhysics ( ) - > GetOrigin ( ) [ 1 ] ) ;
msg . WriteFloat ( GetPhysics ( ) - > GetOrigin ( ) [ 2 ] ) ;
msg . WriteFloat ( viewAngles [ 0 ] ) ;
msg . WriteFloat ( viewAngles [ 1 ] ) ;
msg . WriteFloat ( viewAngles [ 2 ] ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ServerSendEvent ( idPlayer : : EVENT_FORCE_ORIGIN , & msg , false ) ;
}
}
}
}
lastSpectateChange = gameLocal . time + 500 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
idPlayer : : SpectateCycle
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SpectateCycle ( )
{
idPlayer * player ;
if ( gameLocal . time > lastSpectateChange )
{
2012-11-26 18:58:24 +00:00
int latchedSpectator = spectator ;
spectator = gameLocal . GetNextClientNum ( spectator ) ;
player = gameLocal . GetClientByNum ( spectator ) ;
assert ( player ) ; // never call here when the current spectator is wrong
// ignore other spectators
2012-11-28 15:47:07 +00:00
while ( latchedSpectator ! = spectator & & player - > spectating )
{
2012-11-26 18:58:24 +00:00
spectator = gameLocal . GetNextClientNum ( spectator ) ;
player = gameLocal . GetClientByNum ( spectator ) ;
}
lastSpectateChange = gameLocal . time + 500 ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdateSpectating
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateSpectating ( )
{
2012-11-26 18:58:24 +00:00
assert ( spectating ) ;
assert ( ! common - > IsClient ( ) ) ;
assert ( IsHidden ( ) ) ;
2012-11-28 15:47:07 +00:00
idPlayer * player ;
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
player = gameLocal . GetClientByNum ( spectator ) ;
2012-11-28 15:47:07 +00:00
if ( ! player | | ( player - > spectating & & player ! = this ) )
{
2012-11-26 18:58:24 +00:00
SpectateFreeFly ( true ) ;
2012-11-28 15:47:07 +00:00
}
else if ( usercmd . buttons & BUTTON_JUMP )
{
2012-11-26 18:58:24 +00:00
SpectateFreeFly ( false ) ;
2012-11-28 15:47:07 +00:00
}
else if ( usercmd . buttons & BUTTON_USE )
{
2012-11-26 18:58:24 +00:00
SpectateCycle ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( usercmd . buttons & BUTTON_ATTACK )
{
2012-11-26 18:58:24 +00:00
wantSpectate = false ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : HandleSingleGuiCommand
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : HandleSingleGuiCommand ( idEntity * entityGui , idLexer * src )
{
2012-11-26 18:58:24 +00:00
idToken token ;
2012-11-28 15:47:07 +00:00
if ( ! src - > ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( token = = " ; " )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " addhealth " ) = = 0 )
{
if ( entityGui & & health < 100 )
{
2012-11-26 18:58:24 +00:00
int _health = entityGui - > spawnArgs . GetInt ( " gui_parm1 " ) ;
int amt = ( _health > = HEALTH_PER_DOSE ) ? HEALTH_PER_DOSE : _health ;
_health - = amt ;
entityGui - > spawnArgs . SetInt ( " gui_parm1 " , _health ) ;
2012-11-28 15:47:07 +00:00
if ( entityGui - > GetRenderEntity ( ) & & entityGui - > GetRenderEntity ( ) - > gui [ 0 ] )
{
2012-11-26 18:58:24 +00:00
entityGui - > GetRenderEntity ( ) - > gui [ 0 ] - > SetStateInt ( " gui_parm1 " , _health ) ;
}
health + = amt ;
2012-11-28 15:47:07 +00:00
if ( health > 100 )
{
2012-11-26 18:58:24 +00:00
health = 100 ;
}
}
return true ;
}
src - > UnreadToken ( & token ) ;
return false ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : PlayAudioLog
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : PlayAudioLog ( const idSoundShader * shader )
{
2012-11-26 18:58:24 +00:00
EndVideoDisk ( ) ;
2012-11-28 15:47:07 +00:00
if ( name . Length ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
int ms ;
StartSoundShader ( shader , SND_CHANNEL_PDA_AUDIO , 0 , false , & ms ) ;
CancelEvents ( & EV_Player_StopAudioLog ) ;
PostEventMS ( & EV_Player_StopAudioLog , ms + 150 ) ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : EndAudioLog
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : EndAudioLog ( )
{
2012-11-26 18:58:24 +00:00
StopSound ( SND_CHANNEL_PDA_AUDIO , false ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : PlayVideoDisk
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : PlayVideoDisk ( const idDeclVideo * decl )
{
2012-11-26 18:58:24 +00:00
EndAudioLog ( ) ;
pdaVideoMat = decl - > GetRoq ( ) ;
2012-11-28 15:47:07 +00:00
if ( pdaVideoMat )
{
2012-11-26 18:58:24 +00:00
int c = pdaVideoMat - > GetNumStages ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < c ; i + + )
{
const shaderStage_t * stage = pdaVideoMat - > GetStage ( i ) ;
if ( stage ! = NULL & & stage - > texture . cinematic )
{
2012-11-26 18:58:24 +00:00
stage - > texture . cinematic - > ResetTime ( Sys_Milliseconds ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( decl - > GetWave ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( decl - > GetWave ( ) , SND_CHANNEL_PDA_VIDEO , 0 , false , NULL ) ;
}
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : EndVideoDisk
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : EndVideoDisk ( )
{
2012-11-26 18:58:24 +00:00
pdaVideoMat = NULL ;
StopSound ( SND_CHANNEL_PDA_VIDEO , false ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : Collide
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : Collide ( const trace_t & collision , const idVec3 & velocity )
{
idEntity * other ;
if ( common - > IsClient ( ) & & spectating = = false )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
other = gameLocal . entities [ collision . c . entityNum ] ;
2012-11-28 15:47:07 +00:00
if ( other )
{
2012-11-26 18:58:24 +00:00
other - > Signal ( SIG_TOUCH ) ;
2012-11-28 15:47:07 +00:00
if ( ! spectating )
{
if ( other - > RespondsTo ( EV_Touch ) )
{
2012-11-26 18:58:24 +00:00
other - > ProcessEvent ( & EV_Touch , this , & collision ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( other - > RespondsTo ( EV_SpectatorTouch ) )
{
2012-11-26 18:58:24 +00:00
other - > ProcessEvent ( & EV_SpectatorTouch , this , & collision ) ;
}
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : UpdateLocation
2012-11-28 15:47:07 +00:00
Searches nearby locations
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateLocation ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > UpdateLocation ( this ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : ClearFocus
Clears the focus cursor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ClearFocus ( )
{
2012-11-26 18:58:24 +00:00
focusCharacter = NULL ;
focusGUIent = NULL ;
focusUI = NULL ;
focusVehicle = NULL ;
talkCursor = 0 ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : UpdateFocus
Searches nearby entities for interactive guis , possibly making one of them
the focus and sending it a mouse move event
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateFocus ( )
{
idClipModel * clipModelList [ MAX_GENTITIES ] ;
idClipModel * clip ;
2012-11-26 18:58:24 +00:00
int listedClipModels ;
2012-11-28 15:47:07 +00:00
idEntity * oldFocus ;
idEntity * ent ;
idUserInterface * oldUI ;
idAI * oldChar ;
2012-11-26 18:58:24 +00:00
int oldTalkCursor ;
2012-11-28 15:47:07 +00:00
idAFEntity_Vehicle * oldVehicle ;
2012-11-26 18:58:24 +00:00
int i , j ;
idVec3 start , end ;
bool allowFocus ;
2012-11-28 15:47:07 +00:00
const char * command ;
2012-11-26 18:58:24 +00:00
trace_t trace ;
guiPoint_t pt ;
2012-11-28 15:47:07 +00:00
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
sysEvent_t ev ;
2012-11-28 15:47:07 +00:00
idUserInterface * ui ;
if ( gameLocal . inCinematic )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// only update the focus character when attack button isn't pressed so players
// can still chainsaw NPC's
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) | | ( ! focusCharacter & & ( usercmd . buttons & BUTTON_ATTACK ) ) )
{
2012-11-26 18:58:24 +00:00
allowFocus = false ;
}
2012-11-28 15:47:07 +00:00
else
{
allowFocus = true ;
}
2012-11-26 18:58:24 +00:00
oldFocus = focusGUIent ;
oldUI = focusUI ;
oldChar = focusCharacter ;
oldTalkCursor = talkCursor ;
oldVehicle = focusVehicle ;
2012-11-28 15:47:07 +00:00
if ( focusTime < = gameLocal . time )
{
2012-11-26 18:58:24 +00:00
ClearFocus ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't let spectators interact with GUIs
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
start = GetEyePosition ( ) ;
end = start + firstPersonViewAxis [ 0 ] * 80.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// player identification -> names to the hud
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
idVec3 end = start + viewAngles . ToForward ( ) * 768.0f ;
gameLocal . clip . TracePoint ( trace , start , end , MASK_SHOT_BOUNDINGBOX , this ) ;
int iclient = - 1 ;
2012-11-28 15:47:07 +00:00
if ( ( trace . fraction < 1.0f ) & & ( trace . c . entityNum < MAX_CLIENTS ) )
{
2012-11-26 18:58:24 +00:00
iclient = trace . c . entityNum ;
}
2012-11-28 15:47:07 +00:00
if ( MPAim ! = iclient )
{
2012-11-26 18:58:24 +00:00
lastMPAim = MPAim ;
MPAim = iclient ;
lastMPAimTime = gameLocal . realClientTime ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idBounds bounds ( start ) ;
bounds . AddPoint ( end ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
listedClipModels = gameLocal . clip . ClipModelsTouchingBounds ( bounds , - 1 , clipModelList , MAX_GENTITIES ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// no pretense at sorting here, just assume that there will only be one active
// gui within range along the trace
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < listedClipModels ; i + + )
{
2012-11-26 18:58:24 +00:00
clip = clipModelList [ i ] ;
ent = clip - > GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ent - > IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( allowFocus )
{
if ( ent - > IsType ( idAFAttachment : : Type ) )
{
idEntity * body = static_cast < idAFAttachment * > ( ent ) - > GetBody ( ) ;
if ( body ! = NULL & & body - > IsType ( idAI : : Type ) & & ( static_cast < idAI * > ( body ) - > GetTalkState ( ) > = TALK_OK ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . clip . TracePoint ( trace , start , end , MASK_SHOT_RENDERMODEL , this ) ;
2012-11-28 15:47:07 +00:00
if ( ( trace . fraction < 1.0f ) & & ( trace . c . entityNum = = ent - > entityNumber ) )
{
2012-11-26 18:58:24 +00:00
ClearFocus ( ) ;
2012-11-28 15:47:07 +00:00
focusCharacter = static_cast < idAI * > ( body ) ;
2012-11-26 18:58:24 +00:00
talkCursor = 1 ;
focusTime = gameLocal . time + FOCUS_TIME ;
break ;
}
}
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent - > IsType ( idAI : : Type ) )
{
if ( static_cast < idAI * > ( ent ) - > GetTalkState ( ) > = TALK_OK )
{
2012-11-26 18:58:24 +00:00
gameLocal . clip . TracePoint ( trace , start , end , MASK_SHOT_RENDERMODEL , this ) ;
2012-11-28 15:47:07 +00:00
if ( ( trace . fraction < 1.0f ) & & ( trace . c . entityNum = = ent - > entityNumber ) )
{
2012-11-26 18:58:24 +00:00
ClearFocus ( ) ;
2012-11-28 15:47:07 +00:00
focusCharacter = static_cast < idAI * > ( ent ) ;
2012-11-26 18:58:24 +00:00
talkCursor = 1 ;
focusTime = gameLocal . time + FOCUS_TIME ;
break ;
}
}
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent - > IsType ( idAFEntity_Vehicle : : Type ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . clip . TracePoint ( trace , start , end , MASK_SHOT_RENDERMODEL , this ) ;
2012-11-28 15:47:07 +00:00
if ( ( trace . fraction < 1.0f ) & & ( trace . c . entityNum = = ent - > entityNumber ) )
{
2012-11-26 18:58:24 +00:00
ClearFocus ( ) ;
2012-11-28 15:47:07 +00:00
focusVehicle = static_cast < idAFEntity_Vehicle * > ( ent ) ;
2012-11-26 18:58:24 +00:00
focusTime = gameLocal . time + FOCUS_TIME ;
break ;
}
continue ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! ent - > GetRenderEntity ( ) | | ! ent - > GetRenderEntity ( ) - > gui [ 0 ] | | ! ent - > GetRenderEntity ( ) - > gui [ 0 ] - > IsInteractive ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent - > spawnArgs . GetBool ( " inv_item " ) )
{
2012-11-26 18:58:24 +00:00
// don't allow guis on pickup items focus
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pt = gameRenderWorld - > GuiTrace ( ent - > GetModelDefHandle ( ) , start , end ) ;
2012-11-28 15:47:07 +00:00
if ( pt . x ! = - 1 )
{
2012-11-26 18:58:24 +00:00
// we have a hit
2012-11-28 15:47:07 +00:00
renderEntity_t * focusGUIrenderEntity = ent - > GetRenderEntity ( ) ;
if ( ! focusGUIrenderEntity )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( pt . guiId = = 1 )
{
2012-11-26 18:58:24 +00:00
ui = focusGUIrenderEntity - > gui [ 0 ] ;
2012-11-28 15:47:07 +00:00
}
else if ( pt . guiId = = 2 )
{
2012-11-26 18:58:24 +00:00
ui = focusGUIrenderEntity - > gui [ 1 ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
ui = focusGUIrenderEntity - > gui [ 2 ] ;
}
2012-11-28 15:47:07 +00:00
if ( ui = = NULL )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ClearFocus ( ) ;
focusGUIent = ent ;
focusUI = ui ;
2012-11-28 15:47:07 +00:00
if ( oldFocus ! = ent )
{
2012-11-26 18:58:24 +00:00
// new activation
// going to see if we have anything in inventory a gui might be interested in
// need to enumerate inventory items
focusUI - > SetStateInt ( " inv_count " , inventory . items . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < inventory . items . Num ( ) ; j + + )
{
idDict * item = inventory . items [ j ] ;
const char * iname = item - > GetString ( " inv_name " ) ;
const char * iicon = item - > GetString ( " inv_icon " ) ;
const char * itext = item - > GetString ( " inv_text " ) ;
focusUI - > SetStateString ( va ( " inv_name_%i " , j ) , iname ) ;
focusUI - > SetStateString ( va ( " inv_icon_%i " , j ) , iicon ) ;
focusUI - > SetStateString ( va ( " inv_text_%i " , j ) , itext ) ;
kv = item - > MatchPrefix ( " inv_id " , NULL ) ;
if ( kv )
{
2012-11-26 18:58:24 +00:00
focusUI - > SetStateString ( va ( " inv_id_%i " , j ) , kv - > GetValue ( ) ) ;
}
focusUI - > SetStateInt ( iname , 1 ) ;
}
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < inventory . pdaSecurity . Num ( ) ; j + + )
{
const char * p = inventory . pdaSecurity [ j ] ;
if ( p & & * p )
{
2012-11-26 18:58:24 +00:00
focusUI - > SetStateInt ( p , 1 ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int powerCellCount = 0 ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < inventory . items . Num ( ) ; j + + )
{
idDict * item = inventory . items [ j ] ;
if ( item - > GetInt ( " inv_powercell " ) )
{
2012-11-26 18:58:24 +00:00
powerCellCount + + ;
}
}
focusUI - > SetStateInt ( " powercell_count " , powerCellCount ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int staminapercentage = ( int ) ( 100.0f * stamina / pm_stamina . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
focusUI - > SetStateString ( " player_health " , va ( " %i " , health ) ) ;
2012-11-26 18:58:24 +00:00
focusUI - > SetStateString ( " player_stamina " , va ( " %i%% " , staminapercentage ) ) ;
focusUI - > SetStateString ( " player_armor " , va ( " %i%% " , inventory . armor ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = focusGUIent - > spawnArgs . MatchPrefix ( " gui_parm " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
2012-11-26 18:58:24 +00:00
focusUI - > SetStateString ( kv - > GetKey ( ) , kv - > GetValue ( ) ) ;
kv = focusGUIent - > spawnArgs . MatchPrefix ( " gui_parm " , kv ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clamp the mouse to the corner
ev = sys - > GenerateMouseMoveEvent ( - 2000 , - 2000 ) ;
command = focusUI - > HandleEvent ( & ev , gameLocal . time ) ;
2012-11-28 15:47:07 +00:00
HandleGuiCommands ( focusGUIent , command ) ;
2012-11-26 18:58:24 +00:00
// move to an absolute position
ev = sys - > GenerateMouseMoveEvent ( pt . x * SCREEN_WIDTH , pt . y * SCREEN_HEIGHT ) ;
command = focusUI - > HandleEvent ( & ev , gameLocal . time ) ;
HandleGuiCommands ( focusGUIent , command ) ;
focusTime = gameLocal . time + FOCUS_GUI_TIME ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( focusGUIent & & focusUI )
{
if ( ! oldFocus | | oldFocus ! = focusGUIent )
{
2012-11-26 18:58:24 +00:00
command = focusUI - > Activate ( true , gameLocal . time ) ;
HandleGuiCommands ( focusGUIent , command ) ;
StartSound ( " snd_guienter " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
// HideTip();
// HideObjective();
}
2012-11-28 15:47:07 +00:00
}
else if ( oldFocus & & oldUI )
{
2012-11-26 18:58:24 +00:00
command = oldUI - > Activate ( false , gameLocal . time ) ;
HandleGuiCommands ( oldFocus , command ) ;
StartSound ( " snd_guiexit " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > SetCursorState ( this , CURSOR_TALK , talkCursor ) ;
}
2012-11-28 15:47:07 +00:00
if ( oldChar ! = focusCharacter & & hud )
{
if ( focusCharacter )
{
2012-11-26 18:58:24 +00:00
hud - > SetCursorText ( " #str_02036 " , focusCharacter - > spawnArgs . GetString ( " npc_name " , " Joe " ) ) ;
hud - > UpdateCursorState ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hud - > SetCursorText ( " " , " " ) ;
hud - > UpdateCursorState ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : CrashLand
Check for hard landings that generate sound events
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : CrashLand ( const idVec3 & oldOrigin , const idVec3 & oldVelocity )
{
2012-11-26 18:58:24 +00:00
idVec3 origin , velocity ;
idVec3 gravityVector , gravityNormal ;
float delta ;
float hardDelta , fatalDelta , softDelta ;
float dist ;
float vel , acc ;
float t ;
float a , b , c , den ;
waterLevel_t waterLevel ;
bool noDamage ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AI_SOFTLANDING = false ;
AI_HARDLANDING = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the player is not on the ground
2012-11-28 15:47:07 +00:00
if ( ! physicsObj . HasGroundContacts ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gravityNormal = physicsObj . GetGravityNormal ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the player wasn't going down
2012-11-28 15:47:07 +00:00
if ( ( oldVelocity * - gravityNormal ) > = 0.0f )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
waterLevel = physicsObj . GetWaterLevel ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// never take falling damage if completely underwater
2012-11-28 15:47:07 +00:00
if ( waterLevel = = WATERLEVEL_HEAD )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// no falling damage if touching a nodamage surface
noDamage = false ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < physicsObj . GetNumContacts ( ) ; i + + )
{
const contactInfo_t & contact = physicsObj . GetContact ( i ) ;
if ( contact . material - > GetSurfaceFlags ( ) & SURF_NODAMAGE )
{
2012-11-26 18:58:24 +00:00
noDamage = true ;
StartSound ( " snd_land_hard " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
origin = GetPhysics ( ) - > GetOrigin ( ) ;
gravityVector = physicsObj . GetGravity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calculate the exact velocity on landing
dist = ( origin - oldOrigin ) * - gravityNormal ;
vel = oldVelocity * - gravityNormal ;
acc = - gravityVector . Length ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
a = acc / 2.0f ;
b = vel ;
c = - dist ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
den = b * b - 4.0f * a * c ;
2012-11-28 15:47:07 +00:00
if ( den < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
t = ( - b - idMath : : Sqrt ( den ) ) / ( 2.0f * a ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delta = vel + t * acc ;
delta = delta * delta * 0.0001 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reduce falling damage if there is standing water
2012-11-28 15:47:07 +00:00
if ( waterLevel = = WATERLEVEL_WAIST )
{
2012-11-26 18:58:24 +00:00
delta * = 0.25f ;
}
2012-11-28 15:47:07 +00:00
if ( waterLevel = = WATERLEVEL_FEET )
{
2012-11-26 18:58:24 +00:00
delta * = 0.5f ;
}
2012-11-28 15:47:07 +00:00
if ( delta < 1.0f )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// allow falling a bit further for multiplayer
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
fatalDelta = 75.0f ;
hardDelta = 50.0f ;
softDelta = 45.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
fatalDelta = 65.0f ;
hardDelta = 45.0f ;
softDelta = 30.0f ;
}
2012-11-28 15:47:07 +00:00
if ( delta > fatalDelta )
{
2012-11-26 18:58:24 +00:00
AI_HARDLANDING = true ;
landChange = - 32 ;
landTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
if ( ! noDamage )
{
2012-11-26 18:58:24 +00:00
pain_debounce_time = gameLocal . time + pain_delay + 1 ; // ignore pain since we'll play our landing anim
Damage ( NULL , NULL , idVec3 ( 0 , 0 , - 1 ) , " damage_fatalfall " , 1.0f , 0 ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( delta > hardDelta )
{
2012-11-26 18:58:24 +00:00
AI_HARDLANDING = true ;
landChange = - 24 ;
landTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
if ( ! noDamage )
{
2012-11-26 18:58:24 +00:00
pain_debounce_time = gameLocal . time + pain_delay + 1 ; // ignore pain since we'll play our landing anim
Damage ( NULL , NULL , idVec3 ( 0 , 0 , - 1 ) , " damage_hardfall " , 1.0f , 0 ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( delta > softDelta )
{
2012-11-26 18:58:24 +00:00
AI_HARDLANDING = true ;
landChange = - 16 ;
landTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
if ( ! noDamage )
{
2012-11-26 18:58:24 +00:00
pain_debounce_time = gameLocal . time + pain_delay + 1 ; // ignore pain since we'll play our landing anim
Damage ( NULL , NULL , idVec3 ( 0 , 0 , - 1 ) , " damage_softfall " , 1.0f , 0 ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( delta > 7 )
{
2012-11-26 18:58:24 +00:00
AI_SOFTLANDING = true ;
landChange = - 8 ;
landTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
}
else if ( delta > 3 )
{
2012-11-26 18:58:24 +00:00
// just walk on
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : BobCycle
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : BobCycle ( const idVec3 & pushVelocity )
{
2012-11-26 18:58:24 +00:00
float bobmove ;
int old , deltaTime ;
idVec3 vel , gravityDir , velocity ;
idMat3 viewaxis ;
float bob ;
float delta ;
float speed ;
float f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// calculate speed and cycle to be used for
// all cyclic walking effects
//
velocity = physicsObj . GetLinearVelocity ( ) - pushVelocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gravityDir = physicsObj . GetGravityNormal ( ) ;
vel = velocity - ( velocity * gravityDir ) * gravityDir ;
xyspeed = vel . LengthFast ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// do not evaluate the bob for other clients
// when doing a spectate follow, don't do any weapon bobbing
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) & & ! IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
viewBobAngles . Zero ( ) ;
viewBob . Zero ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! physicsObj . HasGroundContacts ( ) | | influenceActive = = INFLUENCE_LEVEL2 | | ( common - > IsMultiplayer ( ) & & spectating ) )
{
2012-11-26 18:58:24 +00:00
// airborne
bobCycle = 0 ;
bobFoot = 0 ;
bobfracsin = 0 ;
2012-11-28 15:47:07 +00:00
}
else if ( ( ! usercmd . forwardmove & & ! usercmd . rightmove ) | | ( xyspeed < = MIN_BOB_SPEED ) )
{
2012-11-26 18:58:24 +00:00
// start at beginning of cycle again
bobCycle = 0 ;
bobFoot = 0 ;
bobfracsin = 0 ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( physicsObj . IsCrouching ( ) )
{
2012-11-26 18:58:24 +00:00
bobmove = pm_crouchbob . GetFloat ( ) ;
// ducked characters never play footsteps
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// vary the bobbing based on the speed of the player
bobmove = pm_walkbob . GetFloat ( ) * ( 1.0f - bobFrac ) + pm_runbob . GetFloat ( ) * bobFrac ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for footstep / splash sounds
old = bobCycle ;
2012-11-28 15:47:07 +00:00
bobCycle = ( int ) ( old + bobmove * ( gameLocal . time - gameLocal . previousTime ) ) & 255 ;
2012-11-26 18:58:24 +00:00
bobFoot = ( bobCycle & 128 ) > > 7 ;
bobfracsin = idMath : : Fabs ( sin ( ( bobCycle & 127 ) / 127.0 * idMath : : PI ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calculate angles for view bobbing
viewBobAngles . Zero ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
viewaxis = viewAngles . ToMat3 ( ) * physicsObj . GetGravityAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add angles based on velocity
delta = velocity * viewaxis [ 0 ] ;
viewBobAngles . pitch + = delta * pm_runpitch . GetFloat ( ) ;
delta = velocity * viewaxis [ 1 ] ;
viewBobAngles . roll - = delta * pm_runroll . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add angles based on bob
// make sure the bob is visible even at low speeds
speed = xyspeed > 200 ? xyspeed : 200 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delta = bobfracsin * pm_bobpitch . GetFloat ( ) * speed ;
2012-11-28 15:47:07 +00:00
if ( physicsObj . IsCrouching ( ) )
{
2012-11-26 18:58:24 +00:00
delta * = 3 ; // crouching
}
viewBobAngles . pitch + = delta ;
delta = bobfracsin * pm_bobroll . GetFloat ( ) * speed ;
2012-11-28 15:47:07 +00:00
if ( physicsObj . IsCrouching ( ) )
{
2012-11-26 18:58:24 +00:00
delta * = 3 ; // crouching accentuates roll
}
2012-11-28 15:47:07 +00:00
if ( bobFoot & 1 )
{
2012-11-26 18:58:24 +00:00
delta = - delta ;
}
viewBobAngles . roll + = delta ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calculate position for view bobbing
viewBob . Zero ( ) ;
2012-11-28 15:47:07 +00:00
if ( physicsObj . HasSteppedUp ( ) )
{
2012-11-26 18:58:24 +00:00
// check for stepping up before a previous step is completed
deltaTime = gameLocal . time - stepUpTime ;
2012-11-28 15:47:07 +00:00
if ( deltaTime < STEPUP_TIME )
{
2012-11-26 18:58:24 +00:00
stepUpDelta = stepUpDelta * ( STEPUP_TIME - deltaTime ) / STEPUP_TIME + physicsObj . GetStepUp ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stepUpDelta = physicsObj . GetStepUp ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( stepUpDelta > 2.0f * pm_stepsize . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
stepUpDelta = 2.0f * pm_stepsize . GetFloat ( ) ;
}
stepUpTime = gameLocal . time ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 gravity = physicsObj . GetGravityNormal ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the player stepped up recently
deltaTime = gameLocal . time - stepUpTime ;
2012-11-28 15:47:07 +00:00
if ( deltaTime < STEPUP_TIME )
{
2012-11-26 18:58:24 +00:00
viewBob + = gravity * ( stepUpDelta * ( STEPUP_TIME - deltaTime ) / STEPUP_TIME ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add bob height after any movement smoothing
bob = bobfracsin * xyspeed * pm_bobup . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
if ( bob > 6 )
{
2012-11-26 18:58:24 +00:00
bob = 6 ;
}
viewBob [ 2 ] + = bob ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add fall height
delta = gameLocal . time - landTime ;
2012-11-28 15:47:07 +00:00
if ( delta < LAND_DEFLECT_TIME )
{
2012-11-26 18:58:24 +00:00
f = delta / LAND_DEFLECT_TIME ;
viewBob - = gravity * ( landChange * f ) ;
2012-11-28 15:47:07 +00:00
}
else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME )
{
2012-11-26 18:58:24 +00:00
delta - = LAND_DEFLECT_TIME ;
f = 1.0 - ( delta / LAND_RETURN_TIME ) ;
viewBob - = gravity * ( landChange * f ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : UpdateDeltaViewAngles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateDeltaViewAngles ( const idAngles & angles )
{
2012-11-26 18:58:24 +00:00
// set the delta angle
idAngles delta ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 3 ; i + + )
{
2012-11-26 18:58:24 +00:00
delta [ i ] = angles [ i ] - SHORT2ANGLE ( usercmd . angles [ i ] ) ;
}
SetDeltaViewAngles ( delta ) ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : SetViewAngles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetViewAngles ( const idAngles & angles )
{
2012-11-26 18:58:24 +00:00
UpdateDeltaViewAngles ( angles ) ;
viewAngles = angles ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : UpdateViewAngles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateViewAngles ( )
{
2012-11-26 18:58:24 +00:00
int i ;
idAngles delta ;
2012-11-28 15:47:07 +00:00
if ( ! noclip & & ( gameLocal . inCinematic | | privateCameraView | | gameLocal . GetCamera ( ) | | influenceActive = = INFLUENCE_LEVEL2 | | objectiveSystemOpen ) )
{
2012-11-26 18:58:24 +00:00
// no view changes at all, but we still want to update the deltas or else when
// we get out of this mode, our view will snap to a kind of random angle
UpdateDeltaViewAngles ( viewAngles ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if dead
2012-11-28 15:47:07 +00:00
if ( health < = 0 )
{
if ( pm_thirdPersonDeath . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
viewAngles . roll = 0.0f ;
viewAngles . pitch = 30.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
viewAngles . roll = 40.0f ;
viewAngles . pitch = - 15.0f ;
}
return ;
}
2012-11-28 15:47:07 +00:00
//
2012-11-26 18:58:24 +00:00
// circularly clamp the angles with deltas
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
2012-11-26 18:58:24 +00:00
cmdAngles [ i ] = SHORT2ANGLE ( usercmd . angles [ i ] ) ;
2012-11-28 15:47:07 +00:00
if ( influenceActive = = INFLUENCE_LEVEL3 )
{
viewAngles [ i ] + = idMath : : ClampFloat ( - 1.0f , 1.0f , idMath : : AngleDelta ( idMath : : AngleNormalize180 ( SHORT2ANGLE ( usercmd . angles [ i ] ) + deltaViewAngles [ i ] ) , viewAngles [ i ] ) ) ;
}
else
{
viewAngles [ i ] = idMath : : AngleNormalize180 ( SHORT2ANGLE ( usercmd . angles [ i ] ) + deltaViewAngles [ i ] ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
if ( ! centerView . IsDone ( gameLocal . time ) )
{
viewAngles . pitch = centerView . GetCurrentValue ( gameLocal . time ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clamp the pitch
2012-11-28 15:47:07 +00:00
if ( noclip )
{
if ( viewAngles . pitch > 89.0f )
{
2012-11-26 18:58:24 +00:00
// don't let the player look down more than 89 degrees while noclipping
viewAngles . pitch = 89.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( viewAngles . pitch < - 89.0f )
{
2012-11-26 18:58:24 +00:00
// don't let the player look up more than 89 degrees while noclipping
viewAngles . pitch = - 89.0f ;
}
2012-11-28 15:47:07 +00:00
}
else if ( mountedObject )
{
2012-11-26 18:58:24 +00:00
int yaw_min , yaw_max , varc ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mountedObject - > GetAngleRestrictions ( yaw_min , yaw_max , varc ) ;
2012-11-28 15:47:07 +00:00
if ( yaw_min < yaw_max )
{
2012-11-26 18:58:24 +00:00
viewAngles . yaw = idMath : : ClampFloat ( yaw_min , yaw_max , viewAngles . yaw ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( viewAngles . yaw < 0 )
{
2012-11-26 18:58:24 +00:00
viewAngles . yaw = idMath : : ClampFloat ( - 180.f , yaw_max , viewAngles . yaw ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
viewAngles . yaw = idMath : : ClampFloat ( yaw_min , 180.f , viewAngles . yaw ) ;
}
}
viewAngles . pitch = idMath : : ClampFloat ( - varc , varc , viewAngles . pitch ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// don't let the player look up or down more than 90 degrees normally
const float restrict = 1.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
viewAngles . pitch = std : : min ( viewAngles . pitch , pm_maxviewpitch . GetFloat ( ) * restrict ) ;
viewAngles . pitch = std : : max ( viewAngles . pitch , pm_minviewpitch . GetFloat ( ) * restrict ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateDeltaViewAngles ( viewAngles ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// orient the model towards the direction we're looking
SetAngles ( idAngles ( 0 , viewAngles . yaw , 0 ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save in the log for analyzing weapon angle offsets
2012-11-28 15:47:07 +00:00
loggedViewAngles [ gameLocal . framenum & ( NUM_LOGGED_VIEW_ANGLES - 1 ) ] = viewAngles ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = =
idPlayer : : AdjustHeartRate
Player heartrate works as follows
DEF_HEARTRATE is resting heartrate
Taking damage when health is above 75 adjusts heart rate by 1 beat per second
Taking damage when health is below 75 adjusts heart rate by 5 beats per second
Maximum heartrate from damage is MAX_HEARTRATE
Firing a weapon adds 1 beat per second up to a maximum of COMBAT_HEARTRATE
Being at less than 25 % stamina adds 5 beats per second up to ZEROSTAMINA_HEARTRATE
All heartrates are target rates . . the heart rate will start falling as soon as there have been no adjustments for 5 seconds
Once it starts falling it always tries to get to DEF_HEARTRATE
2012-11-28 15:47:07 +00:00
The exception to the above rule is upon death at which point the rate is set to DYING_HEARTRATE and starts falling
2012-11-26 18:58:24 +00:00
immediately to zero
2012-11-28 15:47:07 +00:00
Heart rate volumes go from zero ( - 40 db for DEF_HEARTRATE to 5 db for MAX_HEARTRATE ) the volume is
2012-11-26 18:58:24 +00:00
scaled linearly based on the actual rate
Exception to the above rule is once the player is dead , the dying heart rate starts at either the current volume if
it is audible or - 10 db and scales to 8 db on the last few beats
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : AdjustHeartRate ( int target , float timeInSecs , float delay , bool force )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( heartInfo . GetEndValue ( ) = = target )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( AI_DEAD & & ! force )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
lastHeartAdjust = gameLocal . time ;
2012-11-26 18:58:24 +00:00
heartInfo . Init ( gameLocal . time + delay * 1000 , timeInSecs * 1000 , heartRate , target ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : GetBaseHeartRate
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPlayer : : GetBaseHeartRate ( )
{
int base = idMath : : Ftoi ( ( BASE_HEARTRATE + LOWHEALTH_HEARTRATE_ADJ ) - ( ( float ) health / 100.0f ) * LOWHEALTH_HEARTRATE_ADJ ) ;
2012-11-26 18:58:24 +00:00
int rate = idMath : : Ftoi ( base + ( ZEROSTAMINA_HEARTRATE - base ) * ( 1.0f - stamina / pm_stamina . GetFloat ( ) ) ) ;
int diff = ( lastDmgTime ) ? gameLocal . time - lastDmgTime : 99999 ;
rate + = ( diff < 5000 ) ? ( diff < 2500 ) ? ( diff < 1000 ) ? 15 : 10 : 5 : 0 ;
return rate ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : SetCurrentHeartRate
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetCurrentHeartRate ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
int base = idMath : : Ftoi ( ( BASE_HEARTRATE + LOWHEALTH_HEARTRATE_ADJ ) - ( ( float ) health / 100.0f ) * LOWHEALTH_HEARTRATE_ADJ ) ;
if ( PowerUpActive ( ADRENALINE ) )
{
2012-11-26 18:58:24 +00:00
heartRate = 135 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
heartRate = idMath : : Ftoi ( heartInfo . GetCurrentValue ( gameLocal . time ) ) ;
int currentRate = GetBaseHeartRate ( ) ;
2012-11-28 15:47:07 +00:00
if ( health > = 0 & & gameLocal . time > lastHeartAdjust + 2500 )
{
2012-11-26 18:58:24 +00:00
AdjustHeartRate ( currentRate , 2.5f , 0.0f , false ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int bps = idMath : : Ftoi ( 60.0f / heartRate * 1000.0f ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . time - lastHeartBeat > bps )
{
2012-11-26 18:58:24 +00:00
int dmgVol = DMG_VOLUME ;
int deathVol = DEATH_VOLUME ;
int zeroVol = ZERO_VOLUME ;
float pct = 0.0 ;
2012-11-28 15:47:07 +00:00
if ( heartRate > BASE_HEARTRATE & & health > 0 )
{
pct = ( float ) ( heartRate - base ) / ( MAX_HEARTRATE - base ) ;
pct * = ( ( float ) dmgVol - ( float ) zeroVol ) ;
}
else if ( health < = 0 )
{
pct = ( float ) ( heartRate - DYING_HEARTRATE ) / ( BASE_HEARTRATE - DYING_HEARTRATE ) ;
if ( pct > 1.0f )
{
pct = 1.0f ;
}
else if ( pct < 0.0f )
{
2012-11-26 18:58:24 +00:00
pct = 0.0f ;
}
2012-11-28 15:47:07 +00:00
pct * = ( ( float ) deathVol - ( float ) zeroVol ) ;
}
pct + = ( float ) zeroVol ;
if ( pct ! = zeroVol )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_heartbeat " , SND_CHANNEL_HEART , SSF_PRIVATE_SOUND , false , NULL ) ;
// modify just this channel to a custom volume
soundShaderParms_t parms ;
memset ( & parms , 0 , sizeof ( parms ) ) ;
parms . volume = pct ;
refSound . referenceSound - > ModifySound ( SND_CHANNEL_HEART , & parms ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastHeartBeat = gameLocal . time ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : UpdateAir
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateAir ( )
{
if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// see if the player is connected to the info_vacuum
bool newAirless = false ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . vacuumAreaNum ! = - 1 )
{
2012-11-26 18:58:24 +00:00
int num = GetNumPVSAreas ( ) ;
2012-11-28 15:47:07 +00:00
if ( num > 0 )
{
2012-11-26 18:58:24 +00:00
int areaNum ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the player box spans multiple areas, get the area from the origin point instead,
// otherwise a rotating player box may poke into an outside area
2012-11-28 15:47:07 +00:00
if ( num = = 1 )
{
const int * pvsAreas = GetPVSAreas ( ) ;
2012-11-26 18:58:24 +00:00
areaNum = pvsAreas [ 0 ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
areaNum = gameRenderWorld - > PointInArea ( this - > GetPhysics ( ) - > GetOrigin ( ) ) ;
}
newAirless = gameRenderWorld - > AreasAreConnected ( gameLocal . vacuumAreaNum , areaNum , PS_BLOCK_AIR ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( ENVIROTIME ) )
{
2012-11-26 18:58:24 +00:00
newAirless = false ;
}
2012-11-28 15:47:07 +00:00
if ( newAirless )
{
if ( ! airless )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_decompress " , SND_CHANNEL_ANY , SSF_GLOBAL , false , NULL ) ;
StartSound ( " snd_noAir " , SND_CHANNEL_BODY2 , 0 , false , NULL ) ;
}
airMsec - = ( gameLocal . time - gameLocal . previousTime ) ;
2012-11-28 15:47:07 +00:00
if ( airMsec < 0 )
{
2012-11-26 18:58:24 +00:00
airMsec = 0 ;
// check for damage
2012-11-28 15:47:07 +00:00
const idDict * damageDef = gameLocal . FindEntityDefDict ( " damage_noair " , false ) ;
int dmgTiming = 1000 * ( ( damageDef ) ? damageDef - > GetFloat ( " delay " , " 3.0 " ) : 3.0f ) ;
if ( gameLocal . time > lastAirDamage + dmgTiming )
{
2012-11-26 18:58:24 +00:00
Damage ( NULL , NULL , vec3_origin , " damage_noair " , 1.0f , 0 ) ;
lastAirDamage = gameLocal . time ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( airless )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_recompress " , SND_CHANNEL_ANY , SSF_GLOBAL , false , NULL ) ;
StopSound ( SND_CHANNEL_BODY2 , false ) ;
}
airMsec + = ( gameLocal . time - gameLocal . previousTime ) ; // regain twice as fast as lose
2012-11-28 15:47:07 +00:00
if ( airMsec > pm_airMsec . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
airMsec = pm_airMsec . GetInteger ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
airless = newAirless ;
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > UpdateOxygen ( airless , 100 * airMsec / pm_airMsec . GetInteger ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdatePowerupHud ( )
{
if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( lastHudPowerup ! = hudPowerup )
{
if ( hudPowerup = = - 1 )
{
2012-11-26 18:58:24 +00:00
//The powerup hud should be turned off
// TODO_SPARTY: powerups??
//if ( hud ) {
// hud->HandleNamedEvent( "noPowerup" );
//}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
//Turn the pwoerup hud on
// TODO_SPARTY: powerups??
//if ( hud ) {
// hud->HandleNamedEvent( "Powerup" );
//}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastHudPowerup = hudPowerup ;
}
2012-11-28 15:47:07 +00:00
if ( hudPowerup ! = - 1 & & hudPowerup < MAX_POWERUPS )
{
if ( PowerUpActive ( hudPowerup ) )
{
2012-11-26 18:58:24 +00:00
//int remaining = inventory.powerupEndTime[ hudPowerup ] - gameLocal.time;
//int filledbar = idMath::ClampInt( 0, hudPowerupDuration, remaining );
// TODO_SPARTY: powerups??
//if ( hud ) {
// hud->SetStateInt( "player_powerup", 100 * filledbar / hudPowerupDuration );
// hud->SetStateInt( "player_poweruptime", remaining / 1000 );
//}
}
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : GetPDA
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDeclPDA * idPlayer : : GetPDA ( ) const
{
if ( inventory . pdas . Num ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
return inventory . pdas [ 0 ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : GetVideo
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDeclVideo * idPlayer : : GetVideo ( int index )
{
if ( index > = 0 & & index < inventory . videos . Num ( ) )
{
2012-11-26 18:58:24 +00:00
return inventory . videos [ index ] ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : TogglePDA
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : TogglePDA ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( inventory . pdas . Num ( ) = = 0 )
{
2012-11-26 18:58:24 +00:00
ShowTip ( spawnArgs . GetString ( " text_infoTitle " ) , spawnArgs . GetString ( " text_noPDA " ) , true ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( pdaMenu ! = NULL )
{
2012-11-26 18:58:24 +00:00
objectiveSystemOpen = ! objectiveSystemOpen ;
pdaMenu - > ActivateMenu ( objectiveSystemOpen ) ;
2012-11-28 15:47:07 +00:00
if ( objectiveSystemOpen )
{
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > ClearNewPDAInfo ( ) ;
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : Spectate
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Spectate ( bool spectate , bool force )
{
2012-11-26 18:58:24 +00:00
spectating = spectate ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
// join the spectators
ClearPowerUps ( ) ;
spectator = this - > entityNumber ;
Init ( ) ;
StopRagdoll ( ) ;
SetPhysics ( & physicsObj ) ;
physicsObj . DisableClip ( ) ;
FlashlightOff ( ) ;
Hide ( ) ;
Event_DisableWeapon ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Raise me up by a little bit. if i'm the local client.
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
SetSpectateOrigin ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
HideRespawnHudMessage ( ) ;
2012-11-28 15:47:07 +00:00
idLib : : Printf ( " DMP _ GENERAL :> Player %d Spectating \n " , entityNumber ) ;
}
else
{
2012-11-26 18:58:24 +00:00
// put everything back together again
currentWeapon = - 1 ; // to make sure the def will be loaded if necessary
Show ( ) ;
Event_EnableWeapon ( ) ;
2012-11-28 15:47:07 +00:00
idLib : : Printf ( " DMP _ GENERAL :> Player %d Not Spectating \n " , entityNumber ) ;
2012-11-26 18:58:24 +00:00
SetEyeHeight ( pm_normalviewheight . GetFloat ( ) ) ;
}
SetClipModel ( ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : SetClipModel
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetClipModel ( )
{
2012-11-26 18:58:24 +00:00
idBounds bounds ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
bounds = idBounds ( vec3_origin ) . Expand ( pm_spectatebbox . GetFloat ( ) * 0.5f ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
bounds [ 0 ] . Set ( - pm_bboxwidth . GetFloat ( ) * 0.5f , - pm_bboxwidth . GetFloat ( ) * 0.5f , 0 ) ;
bounds [ 1 ] . Set ( pm_bboxwidth . GetFloat ( ) * 0.5f , pm_bboxwidth . GetFloat ( ) * 0.5f , pm_normalheight . GetFloat ( ) ) ;
}
// the origin of the clip model needs to be set before calling SetClipModel
// otherwise our physics object's current origin value gets reset to 0
2012-11-28 15:47:07 +00:00
idClipModel * newClip ;
if ( pm_usecylinder . GetBool ( ) )
{
newClip = new ( TAG_PHYSICS_CLIP_ENTITY ) idClipModel ( idTraceModel ( bounds , 8 ) ) ;
2012-11-26 18:58:24 +00:00
newClip - > Translate ( physicsObj . PlayerGetOrigin ( ) ) ;
physicsObj . SetClipModel ( newClip , 1.0f ) ;
2012-11-28 15:47:07 +00:00
}
else
{
newClip = new ( TAG_PHYSICS_CLIP_ENTITY ) idClipModel ( idTraceModel ( bounds ) ) ;
2012-11-26 18:58:24 +00:00
newClip - > Translate ( physicsObj . PlayerGetOrigin ( ) ) ;
physicsObj . SetClipModel ( newClip , 1.0f ) ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : UseVehicle
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UseVehicle ( )
{
2012-11-26 18:58:24 +00:00
trace_t trace ;
idVec3 start , end ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
if ( GetBindMaster ( ) & & GetBindMaster ( ) - > IsType ( idAFEntity_Vehicle : : Type ) )
{
2012-11-26 18:58:24 +00:00
Show ( ) ;
2012-11-28 15:47:07 +00:00
static_cast < idAFEntity_Vehicle * > ( GetBindMaster ( ) ) - > Use ( this ) ;
}
else
{
2012-11-26 18:58:24 +00:00
start = GetEyePosition ( ) ;
end = start + viewAngles . ToForward ( ) * 80.0f ;
gameLocal . clip . TracePoint ( trace , start , end , MASK_SHOT_RENDERMODEL , this ) ;
2012-11-28 15:47:07 +00:00
if ( trace . fraction < 1.0f )
{
2012-11-26 18:58:24 +00:00
ent = gameLocal . entities [ trace . c . entityNum ] ;
2012-11-28 15:47:07 +00:00
if ( ent & & ent - > IsType ( idAFEntity_Vehicle : : Type ) )
{
2012-11-26 18:58:24 +00:00
Hide ( ) ;
2012-11-28 15:47:07 +00:00
static_cast < idAFEntity_Vehicle * > ( ent ) - > Use ( this ) ;
2012-11-26 18:58:24 +00:00
}
}
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : PerformImpulse
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : PerformImpulse ( int impulse )
{
2012-11-26 18:58:24 +00:00
bool isIntroMap = ( idStr : : FindText ( gameLocal . GetMapFileName ( ) , " mars_city1 " ) > = 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Normal 1 - 0 Keys.
2012-11-28 15:47:07 +00:00
if ( impulse > = IMPULSE_0 & & impulse < = IMPULSE_12 & & ! isIntroMap )
{
2012-11-26 18:58:24 +00:00
SelectWeapon ( impulse , false ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// DPAD Weapon Quick Select
2012-11-28 15:47:07 +00:00
if ( impulse > = IMPULSE_28 & & impulse < = IMPULSE_31 & & ! isIntroMap )
{
2012-11-26 18:58:24 +00:00
SelectWeapon ( impulse , false ) ;
return ;
}
2012-11-28 15:47:07 +00:00
switch ( impulse )
{
case IMPULSE_13 :
{
2012-11-26 18:58:24 +00:00
Reload ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case IMPULSE_14 :
{
if ( ! isIntroMap )
{
2012-11-26 18:58:24 +00:00
NextWeapon ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case IMPULSE_15 :
{
if ( ! isIntroMap )
{
2012-11-26 18:58:24 +00:00
PrevWeapon ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case IMPULSE_16 :
{
if ( flashlight . IsValid ( ) )
{
if ( flashlight . GetEntity ( ) - > lightOn )
{
2012-11-26 18:58:24 +00:00
FlashlightOff ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! spectating & & weaponEnabled & & ! hiddenWeapon & & ! gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) )
{
2012-11-26 18:58:24 +00:00
FlashlightOn ( ) ;
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case IMPULSE_19 :
{
2012-11-26 18:58:24 +00:00
// when we're not in single player, IMPULSE_19 is used for showScores
// otherwise it opens the pda
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
# if !defined(ID_RETAIL) && !defined(ID_RETAIL_INTERNAL)
2012-11-28 15:47:07 +00:00
if ( ! common - > KeyState ( 56 ) ) // don't toggle PDA when LEFT ALT is down
{
2012-11-26 18:58:24 +00:00
# endif
2012-11-28 15:47:07 +00:00
if ( objectiveSystemOpen )
{
2012-11-26 18:58:24 +00:00
TogglePDA ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( weapon_pda > = 0 )
{
2012-11-26 18:58:24 +00:00
SelectWeapon ( weapon_pda , true ) ;
}
# if !defined(ID_RETAIL) && !defined(ID_RETAIL_INTERNAL)
}
# endif
2012-11-28 15:47:07 +00:00
}
else
{
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . mpGame . SetScoreboardActive ( true ) ;
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case IMPULSE_22 :
{
if ( common - > IsClient ( ) | | IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . mpGame . ToggleSpectate ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case IMPULSE_25 :
{
if ( common - > IsServer ( ) & & gameLocal . mpGame . IsGametypeFlagBased ( ) & & ( gameLocal . serverInfo . GetInt ( " si_midnight " ) = = 2 ) )
{
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > PostEventMS ( & EV_Remove , 0 ) ;
enviroSuitLight = NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
const idDict * lightDef = gameLocal . FindEntityDefDict ( " envirosuit_light " , false ) ;
if ( lightDef )
{
idEntity * temp = static_cast < idEntity * > ( enviroSuitLight . GetEntity ( ) ) ;
2012-11-26 18:58:24 +00:00
idAngles lightAng = firstPersonViewAxis . ToAngles ( ) ;
idVec3 lightOrg = firstPersonViewOrigin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 enviroOffset = lightDef - > GetVector ( " enviro_offset " ) ;
idVec3 enviroAngleOffset = lightDef - > GetVector ( " enviro_angle_offset " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . SpawnEntityDef ( * lightDef , & temp , false ) ;
2012-11-28 15:47:07 +00:00
enviroSuitLight = static_cast < idLight * > ( temp ) ;
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > fl . networkSync = true ;
2012-11-28 15:47:07 +00:00
lightOrg + = ( enviroOffset . x * firstPersonViewAxis [ 0 ] ) ;
lightOrg + = ( enviroOffset . y * firstPersonViewAxis [ 1 ] ) ;
lightOrg + = ( enviroOffset . z * firstPersonViewAxis [ 2 ] ) ;
2012-11-26 18:58:24 +00:00
lightAng . pitch + = enviroAngleOffset . x ;
lightAng . yaw + = enviroAngleOffset . y ;
lightAng . roll + = enviroAngleOffset . z ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetOrigin ( lightOrg ) ;
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetAxis ( lightAng . ToMat3 ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > UpdateVisuals ( ) ;
enviroSuitLight . GetEntity ( ) - > Present ( ) ;
}
}
}
break ;
}
2012-11-28 15:47:07 +00:00
//Hack so the chainsaw will work in MP
case IMPULSE_27 :
{
SelectWeapon ( 18 , false ) ;
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = =
idPlayer : : EvaluateControls
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : EvaluateControls ( )
{
2012-11-26 18:58:24 +00:00
// check for respawning
2012-11-28 15:47:07 +00:00
if ( health < = 0 & & ! g_testDeath . GetBool ( ) )
{
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
// in MP, idMultiplayerGame decides spawns
2012-11-28 15:47:07 +00:00
if ( ( gameLocal . time > minRespawnTime ) & & ( usercmd . buttons & BUTTON_ATTACK ) )
{
2012-11-26 18:58:24 +00:00
forceRespawn = true ;
2012-11-28 15:47:07 +00:00
}
else if ( gameLocal . time > maxRespawnTime )
{
2012-11-26 18:58:24 +00:00
forceRespawn = true ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// in single player, we let the session handle restarting the level or loading a game
2012-11-28 15:47:07 +00:00
if ( gameLocal . time > minRespawnTime )
{
2012-11-26 18:58:24 +00:00
gameLocal . sessionCommand = " died " ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( usercmd . impulseSequence ! = oldImpulseSequence )
{
2012-11-26 18:58:24 +00:00
PerformImpulse ( usercmd . impulse ) ;
}
2012-11-28 15:47:07 +00:00
if ( forceScoreBoard )
{
2012-11-26 18:58:24 +00:00
gameLocal . mpGame . SetScoreboardActive ( true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
oldImpulseSequence = usercmd . impulseSequence ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AdjustSpeed ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update the viewangles
UpdateViewAngles ( ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : AdjustSpeed
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : AdjustSpeed ( )
{
2012-11-26 18:58:24 +00:00
float speed ;
float rate ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
speed = pm_spectatespeed . GetFloat ( ) ;
bobFrac = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( noclip )
{
2012-11-26 18:58:24 +00:00
speed = pm_noclipspeed . GetFloat ( ) ;
bobFrac = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( ! physicsObj . OnLadder ( ) & & ( usercmd . buttons & BUTTON_RUN ) & & ( usercmd . forwardmove | | usercmd . rightmove ) & & ! ( usercmd . buttons & BUTTON_CROUCH ) )
{
if ( ! common - > IsMultiplayer ( ) & & ! physicsObj . IsCrouching ( ) & & ! PowerUpActive ( ADRENALINE ) )
{
2012-11-26 18:58:24 +00:00
stamina - = MS2SEC ( gameLocal . time - gameLocal . previousTime ) ;
}
2012-11-28 15:47:07 +00:00
if ( stamina < 0 )
{
2012-11-26 18:58:24 +00:00
stamina = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( ( ! pm_stamina . GetFloat ( ) ) | | ( stamina > pm_staminathreshold . GetFloat ( ) ) )
{
2012-11-26 18:58:24 +00:00
bobFrac = 1.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( pm_staminathreshold . GetFloat ( ) < = 0.0001f )
{
2012-11-26 18:58:24 +00:00
bobFrac = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
bobFrac = stamina / pm_staminathreshold . GetFloat ( ) ;
}
speed = pm_walkspeed . GetFloat ( ) * ( 1.0f - bobFrac ) + pm_runspeed . GetFloat ( ) * bobFrac ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
rate = pm_staminarate . GetFloat ( ) ;
// increase 25% faster when not moving
2012-11-28 15:47:07 +00:00
if ( ( usercmd . forwardmove = = 0 ) & & ( usercmd . rightmove = = 0 ) & & ( ! physicsObj . OnLadder ( ) | | ( ( usercmd . buttons & ( BUTTON_CROUCH | BUTTON_JUMP ) ) = = 0 ) ) )
{
rate * = 1.25f ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stamina + = rate * MS2SEC ( gameLocal . time - gameLocal . previousTime ) ;
2012-11-28 15:47:07 +00:00
if ( stamina > pm_stamina . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
stamina = pm_stamina . GetFloat ( ) ;
}
speed = pm_walkspeed . GetFloat ( ) ;
bobFrac = 0.0f ;
}
2012-11-28 15:47:07 +00:00
speed * = PowerUpModifier ( SPEED ) ;
if ( influenceActive = = INFLUENCE_LEVEL3 )
{
2012-11-26 18:58:24 +00:00
speed * = 0.33f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetSpeed ( speed , pm_crouchspeed . GetFloat ( ) ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : AdjustBodyAngles
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : AdjustBodyAngles ( )
{
2012-11-26 18:58:24 +00:00
idMat3 lookAxis ;
idMat3 legsAxis ;
bool blend ;
float diff ;
float frac ;
float upBlend ;
float forwardBlend ;
float downBlend ;
2012-11-28 15:47:07 +00:00
if ( health < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
blend = true ;
2012-11-28 15:47:07 +00:00
if ( ! physicsObj . HasGroundContacts ( ) )
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = 0.0f ;
legsForward = true ;
2012-11-28 15:47:07 +00:00
}
else if ( usercmd . forwardmove < 0 )
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = idMath : : AngleNormalize180 ( idVec3 ( - usercmd . forwardmove , usercmd . rightmove , 0.0f ) . ToYaw ( ) ) ;
legsForward = false ;
2012-11-28 15:47:07 +00:00
}
else if ( usercmd . forwardmove > 0 )
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = idMath : : AngleNormalize180 ( idVec3 ( usercmd . forwardmove , - usercmd . rightmove , 0.0f ) . ToYaw ( ) ) ;
legsForward = true ;
2012-11-28 15:47:07 +00:00
}
else if ( ( usercmd . rightmove ! = 0 ) & & physicsObj . IsCrouching ( ) )
{
if ( ! legsForward )
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = idMath : : AngleNormalize180 ( idVec3 ( idMath : : Abs ( usercmd . rightmove ) , usercmd . rightmove , 0.0f ) . ToYaw ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = idMath : : AngleNormalize180 ( idVec3 ( idMath : : Abs ( usercmd . rightmove ) , - usercmd . rightmove , 0.0f ) . ToYaw ( ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( usercmd . rightmove ! = 0 )
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = 0.0f ;
legsForward = true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
legsForward = true ;
diff = idMath : : Fabs ( idealLegsYaw - legsYaw ) ;
idealLegsYaw = idealLegsYaw - idMath : : AngleNormalize180 ( viewAngles . yaw - oldViewYaw ) ;
2012-11-28 15:47:07 +00:00
if ( diff < 0.1f )
{
2012-11-26 18:58:24 +00:00
legsYaw = idealLegsYaw ;
blend = false ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! physicsObj . IsCrouching ( ) )
{
2012-11-26 18:58:24 +00:00
legsForward = true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
oldViewYaw = viewAngles . yaw ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AI_TURN_LEFT = false ;
AI_TURN_RIGHT = false ;
2012-11-28 15:47:07 +00:00
if ( idealLegsYaw < - 45.0f )
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = 0 ;
AI_TURN_RIGHT = true ;
blend = true ;
2012-11-28 15:47:07 +00:00
}
else if ( idealLegsYaw > 45.0f )
{
2012-11-26 18:58:24 +00:00
idealLegsYaw = 0 ;
AI_TURN_LEFT = true ;
blend = true ;
}
2012-11-28 15:47:07 +00:00
if ( blend )
{
2012-11-26 18:58:24 +00:00
legsYaw = legsYaw * 0.9f + idealLegsYaw * 0.1f ;
}
legsAxis = idAngles ( 0.0f , legsYaw , 0.0f ) . ToMat3 ( ) ;
animator . SetJointAxis ( hipJoint , JOINTMOD_WORLD , legsAxis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calculate the blending between down, straight, and up
frac = viewAngles . pitch / 90.0f ;
2012-11-28 15:47:07 +00:00
if ( frac > 0.0f )
{
2012-11-26 18:58:24 +00:00
downBlend = frac ;
forwardBlend = 1.0f - frac ;
upBlend = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
downBlend = 0.0f ;
forwardBlend = 1.0f + frac ;
upBlend = - frac ;
}
2012-11-28 15:47:07 +00:00
animator . CurrentAnim ( ANIMCHANNEL_TORSO ) - > SetSyncedAnimWeight ( 0 , downBlend ) ;
2012-11-26 18:58:24 +00:00
animator . CurrentAnim ( ANIMCHANNEL_TORSO ) - > SetSyncedAnimWeight ( 1 , forwardBlend ) ;
animator . CurrentAnim ( ANIMCHANNEL_TORSO ) - > SetSyncedAnimWeight ( 2 , upBlend ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animator . CurrentAnim ( ANIMCHANNEL_LEGS ) - > SetSyncedAnimWeight ( 0 , downBlend ) ;
animator . CurrentAnim ( ANIMCHANNEL_LEGS ) - > SetSyncedAnimWeight ( 1 , forwardBlend ) ;
animator . CurrentAnim ( ANIMCHANNEL_LEGS ) - > SetSyncedAnimWeight ( 2 , upBlend ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : InitAASLocation
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : InitAASLocation ( )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
idVec3 size ;
idBounds bounds ;
2012-11-28 15:47:07 +00:00
idAAS * aas ;
2012-11-26 18:58:24 +00:00
idVec3 origin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetFloorPos ( 64.0f , origin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
num = gameLocal . NumAAS ( ) ;
aasLocation . SetGranularity ( 1 ) ;
2012-11-28 15:47:07 +00:00
aasLocation . SetNum ( num ) ;
for ( i = 0 ; i < aasLocation . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
aasLocation [ i ] . areaNum = 0 ;
aasLocation [ i ] . pos = origin ;
aas = gameLocal . GetAAS ( i ) ;
2012-11-28 15:47:07 +00:00
if ( aas ! = NULL & & aas - > GetSettings ( ) )
{
2012-11-26 18:58:24 +00:00
size = aas - > GetSettings ( ) - > boundingBoxes [ 0 ] [ 1 ] ;
bounds [ 0 ] = - size ;
size . z = 32.0f ;
bounds [ 1 ] = size ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
aasLocation [ i ] . areaNum = aas - > PointReachableAreaNum ( origin , bounds , AREA_REACHABLE_WALK ) ;
}
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : SetAASLocation
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetAASLocation ( )
{
2012-11-26 18:58:24 +00:00
int i ;
int areaNum ;
idVec3 size ;
idBounds bounds ;
2012-11-28 15:47:07 +00:00
idAAS * aas ;
2012-11-26 18:58:24 +00:00
idVec3 origin ;
2012-11-28 15:47:07 +00:00
if ( ! GetFloorPos ( 64.0f , origin ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < aasLocation . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
aas = gameLocal . GetAAS ( i ) ;
2012-11-28 15:47:07 +00:00
if ( ! aas )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
size = aas - > GetSettings ( ) - > boundingBoxes [ 0 ] [ 1 ] ;
bounds [ 0 ] = - size ;
size . z = 32.0f ;
bounds [ 1 ] = size ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
areaNum = aas - > PointReachableAreaNum ( origin , bounds , AREA_REACHABLE_WALK ) ;
2012-11-28 15:47:07 +00:00
if ( areaNum )
{
2012-11-26 18:58:24 +00:00
aasLocation [ i ] . pos = origin ;
aasLocation [ i ] . areaNum = areaNum ;
}
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : GetAASLocation
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GetAASLocation ( idAAS * aas , idVec3 & pos , int & areaNum ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
if ( aas ! = NULL )
{
for ( i = 0 ; i < aasLocation . Num ( ) ; i + + )
{
if ( aas = = gameLocal . GetAAS ( i ) )
{
2012-11-26 18:58:24 +00:00
areaNum = aasLocation [ i ] . areaNum ;
pos = aasLocation [ i ] . pos ;
return ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
areaNum = 0 ;
pos = physicsObj . GetOrigin ( ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : Move_Interpolated
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Move_Interpolated ( float fraction )
{
2012-11-26 18:58:24 +00:00
float newEyeOffset ;
idVec3 oldOrigin ;
idVec3 oldVelocity ;
idVec3 pushVelocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save old origin and velocity for crashlanding
oldOrigin = physicsObj . GetOrigin ( ) ;
oldVelocity = physicsObj . GetLinearVelocity ( ) ;
pushVelocity = physicsObj . GetPushedLinearVelocity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set physics variables
physicsObj . SetMaxStepHeight ( pm_stepsize . GetFloat ( ) ) ;
physicsObj . SetMaxJumpHeight ( pm_jumpheight . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( noclip )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( 0 ) ;
physicsObj . SetMovementType ( PM_NOCLIP ) ;
2012-11-28 15:47:07 +00:00
}
else if ( spectating )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( 0 ) ;
physicsObj . SetMovementType ( PM_SPECTATOR ) ;
2012-11-28 15:47:07 +00:00
}
else if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( CONTENTS_CORPSE | CONTENTS_MONSTERCLIP ) ;
physicsObj . SetMovementType ( PM_DEAD ) ;
2012-11-28 15:47:07 +00:00
}
else if ( gameLocal . inCinematic | | gameLocal . GetCamera ( ) | | privateCameraView | | ( influenceActive = = INFLUENCE_LEVEL2 ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( CONTENTS_BODY ) ;
physicsObj . SetMovementType ( PM_FREEZE ) ;
2012-11-28 15:47:07 +00:00
}
else if ( mountedObject )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( 0 ) ;
physicsObj . SetMovementType ( PM_FREEZE ) ;
2012-11-28 15:47:07 +00:00
}
else
{
physicsObj . SetContents ( CONTENTS_BODY ) ;
2012-11-26 18:58:24 +00:00
physicsObj . SetMovementType ( PM_NORMAL ) ;
}
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetClipMask ( MASK_DEADSOLID ) ;
2012-11-28 15:47:07 +00:00
}
else if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetClipMask ( MASK_DEADSOLID ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
physicsObj . SetClipMask ( MASK_PLAYERSOLID ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetDebugLevel ( g_debugMove . GetBool ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
{
idVec3 org ;
idMat3 axis ;
GetViewPos ( org , axis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetPlayerInput ( usercmd , axis [ 0 ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: physics gets disabled somehow
BecomeActive ( TH_PHYSICS ) ;
InterpolatePhysics ( fraction ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update our last valid AAS location for the AI
SetAASLocation ( ) ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = pm_deadviewheight . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( physicsObj . IsCrouching ( ) )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = pm_crouchviewheight . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( GetBindMaster ( ) & & GetBindMaster ( ) - > IsType ( idAFEntity_Vehicle : : Type ) )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
newEyeOffset = pm_normalviewheight . GetFloat ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( EyeHeight ( ) ! = newEyeOffset )
{
if ( spectating )
{
2012-11-26 18:58:24 +00:00
SetEyeHeight ( newEyeOffset ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// smooth out duck height changes
SetEyeHeight ( EyeHeight ( ) * pm_crouchrate . GetFloat ( ) + newEyeOffset * ( 1.0f - pm_crouchrate . GetFloat ( ) ) ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( AI_JUMP )
{
2012-11-26 18:58:24 +00:00
// bounce the view weapon
2012-11-28 15:47:07 +00:00
loggedAccel_t * acc = & loggedAccel [ currentLoggedAccel & ( NUM_LOGGED_ACCELS - 1 ) ] ;
2012-11-26 18:58:24 +00:00
currentLoggedAccel + + ;
acc - > time = gameLocal . time ;
acc - > dir [ 2 ] = 200 ;
acc - > dir [ 0 ] = acc - > dir [ 1 ] = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( AI_ONLADDER )
{
2012-11-26 18:58:24 +00:00
int old_rung = oldOrigin . z / LADDER_RUNG_DISTANCE ;
int new_rung = physicsObj . GetOrigin ( ) . z / LADDER_RUNG_DISTANCE ;
2012-11-28 15:47:07 +00:00
if ( old_rung ! = new_rung )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_stepladder " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
BobCycle ( pushVelocity ) ;
CrashLand ( oldOrigin , oldVelocity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = =
idPlayer : : Move
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Move ( )
{
2012-11-26 18:58:24 +00:00
float newEyeOffset ;
idVec3 oldOrigin ;
idVec3 oldVelocity ;
idVec3 pushVelocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save old origin and velocity for crashlanding
oldOrigin = physicsObj . GetOrigin ( ) ;
oldVelocity = physicsObj . GetLinearVelocity ( ) ;
pushVelocity = physicsObj . GetPushedLinearVelocity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set physics variables
physicsObj . SetMaxStepHeight ( pm_stepsize . GetFloat ( ) ) ;
physicsObj . SetMaxJumpHeight ( pm_jumpheight . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( noclip )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( 0 ) ;
physicsObj . SetMovementType ( PM_NOCLIP ) ;
2012-11-28 15:47:07 +00:00
}
else if ( spectating )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( 0 ) ;
physicsObj . SetMovementType ( PM_SPECTATOR ) ;
2012-11-28 15:47:07 +00:00
}
else if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( CONTENTS_CORPSE | CONTENTS_MONSTERCLIP ) ;
physicsObj . SetMovementType ( PM_DEAD ) ;
2012-11-28 15:47:07 +00:00
}
else if ( gameLocal . inCinematic | | gameLocal . GetCamera ( ) | | privateCameraView | | ( influenceActive = = INFLUENCE_LEVEL2 ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( CONTENTS_BODY ) ;
physicsObj . SetMovementType ( PM_FREEZE ) ;
2012-11-28 15:47:07 +00:00
}
else if ( mountedObject )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( 0 ) ;
physicsObj . SetMovementType ( PM_FREEZE ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( CONTENTS_BODY ) ;
physicsObj . SetMovementType ( PM_NORMAL ) ;
}
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetClipMask ( MASK_DEADSOLID ) ;
2012-11-28 15:47:07 +00:00
}
else if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetClipMask ( MASK_DEADSOLID ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
physicsObj . SetClipMask ( MASK_PLAYERSOLID ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetDebugLevel ( g_debugMove . GetBool ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
{
idVec3 org ;
idMat3 axis ;
GetViewPos ( org , axis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetPlayerInput ( usercmd , axis [ 0 ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: physics gets disabled somehow
BecomeActive ( TH_PHYSICS ) ;
RunPhysics ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update our last valid AAS location for the AI
SetAASLocation ( ) ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = pm_deadviewheight . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( physicsObj . IsCrouching ( ) )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = pm_crouchviewheight . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( GetBindMaster ( ) & & GetBindMaster ( ) - > IsType ( idAFEntity_Vehicle : : Type ) )
{
2012-11-26 18:58:24 +00:00
newEyeOffset = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
newEyeOffset = pm_normalviewheight . GetFloat ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( EyeHeight ( ) ! = newEyeOffset )
{
if ( spectating )
{
2012-11-26 18:58:24 +00:00
SetEyeHeight ( newEyeOffset ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// smooth out duck height changes
SetEyeHeight ( EyeHeight ( ) * pm_crouchrate . GetFloat ( ) + newEyeOffset * ( 1.0f - pm_crouchrate . GetFloat ( ) ) ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( noclip | | gameLocal . inCinematic | | ( influenceActive = = INFLUENCE_LEVEL2 ) )
{
2012-11-26 18:58:24 +00:00
AI_CROUCH = false ;
AI_ONGROUND = ( influenceActive = = INFLUENCE_LEVEL2 ) ;
AI_ONLADDER = false ;
AI_JUMP = false ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
AI_CROUCH = physicsObj . IsCrouching ( ) ;
AI_ONGROUND = physicsObj . HasGroundContacts ( ) ;
AI_ONLADDER = physicsObj . OnLadder ( ) ;
AI_JUMP = physicsObj . HasJumped ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we're standing on top of a monster and give a push if we are
2012-11-28 15:47:07 +00:00
idEntity * groundEnt = physicsObj . GetGroundEntity ( ) ;
if ( groundEnt ! = NULL & & groundEnt - > IsType ( idAI : : Type ) )
{
2012-11-26 18:58:24 +00:00
idVec3 vel = physicsObj . GetLinearVelocity ( ) ;
2012-11-28 15:47:07 +00:00
if ( vel . ToVec2 ( ) . LengthSqr ( ) < 0.1f )
{
2012-11-26 18:58:24 +00:00
vel . ToVec2 ( ) = physicsObj . GetOrigin ( ) . ToVec2 ( ) - groundEnt - > GetPhysics ( ) - > GetAbsBounds ( ) . GetCenter ( ) . ToVec2 ( ) ;
vel . ToVec2 ( ) . NormalizeFast ( ) ;
vel . ToVec2 ( ) * = pm_walkspeed . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// give em a push in the direction they're going
vel * = 1.1f ;
}
physicsObj . SetLinearVelocity ( vel ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( AI_JUMP )
{
2012-11-26 18:58:24 +00:00
// bounce the view weapon
2012-11-28 15:47:07 +00:00
loggedAccel_t * acc = & loggedAccel [ currentLoggedAccel & ( NUM_LOGGED_ACCELS - 1 ) ] ;
2012-11-26 18:58:24 +00:00
currentLoggedAccel + + ;
acc - > time = gameLocal . time ;
acc - > dir [ 2 ] = 200 ;
acc - > dir [ 0 ] = acc - > dir [ 1 ] = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( AI_ONLADDER )
{
2012-11-26 18:58:24 +00:00
int old_rung = oldOrigin . z / LADDER_RUNG_DISTANCE ;
int new_rung = physicsObj . GetOrigin ( ) . z / LADDER_RUNG_DISTANCE ;
2012-11-28 15:47:07 +00:00
if ( old_rung ! = new_rung )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_stepladder " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
BobCycle ( pushVelocity ) ;
CrashLand ( oldOrigin , oldVelocity ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idPlayer : : AllowClientAuthPhysics
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : AllowClientAuthPhysics ( )
{
2012-11-26 18:58:24 +00:00
// note respawn count > 1: respawn should be called twice - once for initial spawn and once for actual respawn by game mode
// TODO: I don't think doom 3 will need to care about the respawn count.
return ( usercmd . serverGameMilliseconds > serverOverridePositionTime & & commonLocal . GetUCmdMgr ( ) . HasUserCmdForPlayer ( entityNumber ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idPlayer : : RunPhysics_RemoteClientCorrection
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RunPhysics_RemoteClientCorrection ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! AllowClientAuthPhysics ( ) )
{
2012-11-26 18:58:24 +00:00
// We are still overriding client's position
2012-11-28 15:47:07 +00:00
if ( pm_clientAuthoritative_debug . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
//clientGame->renderWorld->DebugPoint( idColor::colorRed, GetOrigin() );
2012-11-28 15:47:07 +00:00
idLib : : Printf ( " [%d]Ignoring client auth: cmd.serverTime: %d overrideTime: %d \n " , entityNumber , usercmd . serverGameMilliseconds , serverOverridePositionTime ) ;
2012-11-26 18:58:24 +00:00
}
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Client is on a pusher... ignore him so he doesn't lag behind
bool becameUnlocked = false ;
2012-11-28 15:47:07 +00:00
if ( physicsObj . ClientPusherLocked ( becameUnlocked ) )
{
2012-11-26 18:58:24 +00:00
// Check and see how far we've diverged.
idVec3 cmdPos ( usercmd . pos [ 0 ] , usercmd . pos [ 1 ] , usercmd . pos [ 2 ] ) ;
idVec3 newOrigin = physicsObj . GetOrigin ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 divergeVec = cmdPos - newOrigin ;
idLib : : Printf ( " Client Divergence: %s Length: %2f \n " , divergeVec . ToString ( 3 ) , divergeVec . Length ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the client Diverges over a certain amount, snap him back
2012-11-28 15:47:07 +00:00
if ( divergeVec . Length ( ) < pm_clientAuthoritative_Divergence . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
if ( becameUnlocked )
{
2012-11-26 18:58:24 +00:00
// Client just got off of a mover, wait before listening to him
serverOverridePositionTime = gameLocal . GetServerGameTimeMs ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Correction
{
idVec3 newOrigin = physicsObj . GetOrigin ( ) ;
idVec3 cmdPos ( usercmd . pos [ 0 ] , usercmd . pos [ 1 ] , usercmd . pos [ 2 ] ) ;
idVec3 desiredPos = cmdPos ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float delta = ( desiredPos - newOrigin ) . Length ( ) ;
// ignore small differences in Z: this can cause player to not have proper ground contacts which messes up
// velocity/acceleration calculation. If this hack doesn't work out, will may need more precision for at least
// the Z component of the client's origin.
2012-11-28 15:47:07 +00:00
if ( idMath : : Fabs ( desiredPos . z - newOrigin . z ) < pm_clientAuthoritative_minDistZ . GetFloat ( ) )
{
if ( pm_clientAuthoritative_debug . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
//idLib::Printf("[%d]Remote client physics: ignore small z delta: %f\n", usercmd.clientGameFrame, ( desiredPos.z - newOrigin.z ) );
}
desiredPos . z = newOrigin . z ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Origin
2012-11-28 15:47:07 +00:00
if ( delta > pm_clientAuthoritative_minDist . GetFloat ( ) )
{
if ( pm_clientAuthoritative_Lerp . GetFloat ( ) > 0.0f )
{
2012-11-26 18:58:24 +00:00
desiredPos . x = idMath : : LerpToWithScale ( newOrigin . x , desiredPos . x , pm_clientAuthoritative_Lerp . GetFloat ( ) ) ;
desiredPos . y = idMath : : LerpToWithScale ( newOrigin . y , desiredPos . y , pm_clientAuthoritative_Lerp . GetFloat ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set corrected position immediately if non deferred
physicsObj . SetOrigin ( desiredPos ) ;
2012-11-28 15:47:07 +00:00
if ( pm_clientAuthoritative_debug . GetBool ( ) & & delta > pm_clientAuthoritative_warnDist . GetFloat ( ) )
{
idLib : : Warning ( " Remote client player physics: delta movement for frame was %f units " , delta ) ;
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugLine ( colorRed , newOrigin , desiredPos ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( pm_clientAuthoritative_debug . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
//idLib::Printf( "[%d]Remote client player physics delta: %.2f. forward: %d pos <%.2f, %.2f, %.2f> \n", usercmd.clientGameFrame, delta, (int)usercmd.forwardmove, desiredPos.x, desiredPos.y, desiredPos.z );
gameRenderWorld - > DebugLine ( colorRed , newOrigin , desiredPos ) ;
//gameRenderWorld->DebugPoint( colorBlue, cmdPos );
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set velocity if significantly different than client.
const float serverSpeedSquared = physicsObj . GetLinearVelocity ( ) . LengthSqr ( ) ;
const float clientSpeedSquared = usercmd . speedSquared ;
2012-11-28 15:47:07 +00:00
2012-12-02 21:37:32 +00:00
if ( fabsf ( serverSpeedSquared - clientSpeedSquared ) > pm_clientAuthoritative_minSpeedSquared . GetFloat ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
idVec3 normalizedVelocity = physicsObj . GetLinearVelocity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const float VELOCITY_EPSILON = 0.001f ;
2012-11-28 15:47:07 +00:00
if ( normalizedVelocity . LengthSqr ( ) > VELOCITY_EPSILON )
{
2012-11-26 18:58:24 +00:00
normalizedVelocity . Normalize ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetLinearVelocity ( normalizedVelocity * idMath : : Sqrt ( clientSpeedSquared ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idPlayer : : GetPhysicsTimeStep
Uses the time from the usercmd in case the server is running at a slower engineHz
than the client .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPlayer : : GetPhysicsTimeStep ( ) const
{
2012-11-26 18:58:24 +00:00
// if the ucDeltaMillisecond value looks wrong, use the game delta milliseconds
// This can happen if the user brings up the pause menu in SP
const int ucDeltaMilliseconds = usercmd . clientGameMilliseconds - oldCmd . clientGameMilliseconds ;
2012-11-28 15:47:07 +00:00
if ( ucDeltaMilliseconds < 1 | | ucDeltaMilliseconds > 20 )
{
2012-11-26 18:58:24 +00:00
return gameLocal . time - gameLocal . previousTime ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return ucDeltaMilliseconds ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : ShowRespawnHudMessage
Called once when the minimum respawn time has passed after a player has died
so that we can display a message to the user .
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ShowRespawnHudMessage ( )
{
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
hud - > ShowRespawnMessage ( true ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Clients show the hud message through a reliable message.
idBitMsg outMsg ;
byte dummyData [ 1 ] ;
outMsg . InitWrite ( dummyData , sizeof ( dummyData ) ) ;
outMsg . BeginWriting ( ) ;
outMsg . WriteByte ( 0 ) ;
session - > GetActingGameStateLobbyBase ( ) . SendReliableToLobbyUser ( gameLocal . lobbyUserIDs [ entityNumber ] , GAME_RELIABLE_MESSAGE_RESPAWN_AVAILABLE , outMsg ) ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : HideRespawnHudMessage
Called once when we should remove the respawn message from the hud ,
for example , when a player does respawn .
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : HideRespawnHudMessage ( )
{
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
hud - > ShowRespawnMessage ( false ) ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : UpdateHud
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateHud ( )
{
idPlayer * aimed ;
if ( ! hud )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int c = inventory . pickupItemNames . Num ( ) ;
2012-11-28 15:47:07 +00:00
if ( c > 0 )
{
if ( hud ! = NULL & & hud - > IsPickupListReady ( ) )
{
if ( inventory . nextItemPickup & & gameLocal . time - inventory . nextItemPickup > 2000 )
{
2012-11-26 18:58:24 +00:00
inventory . nextItemNum = 1 ;
}
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int count = 5 ;
bool showNewPickups = false ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < count ; i + + ) //_D3XP
{
if ( i < c )
{
2012-11-26 18:58:24 +00:00
hud - > UpdatePickupInfo ( i , inventory . pickupItemNames [ 0 ] ) ;
inventory . nextItemNum + + ;
showNewPickups = true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hud - > UpdatePickupInfo ( i , " " ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . nextItemPickup = gameLocal . time + 2500 ;
inventory . pickupItemNames . RemoveIndex ( 0 ) ;
}
2012-11-28 15:47:07 +00:00
if ( showNewPickups )
{
2012-11-26 18:58:24 +00:00
hud - > ShowPickups ( ) ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . realClientTime = = lastMPAimTime )
{
if ( MPAim ! = - 1 & & gameLocal . mpGame . IsGametypeTeamBased ( ) /* CTF */
& & gameLocal . entities [ MPAim ] & & gameLocal . entities [ MPAim ] - > IsType ( idPlayer : : Type )
& & static_cast < idPlayer * > ( gameLocal . entities [ MPAim ] ) - > team = = team )
{
aimed = static_cast < idPlayer * > ( gameLocal . entities [ MPAim ] ) ;
hud - > TriggerHitTarget ( true , session - > GetActingGameStateLobbyBase ( ) . GetLobbyUserName ( gameLocal . lobbyUserIDs [ MPAim ] ) , aimed - > team + 1 ) ;
MPAimHighlight = true ;
MPAimFadeTime = 0 ; // no fade till loosing focus
}
else if ( MPAimHighlight )
{
2012-11-26 18:58:24 +00:00
hud - > TriggerHitTarget ( false , " " ) ;
MPAimFadeTime = gameLocal . realClientTime ;
MPAimHighlight = false ;
}
}
2012-11-28 15:47:07 +00:00
if ( MPAimFadeTime )
{
2012-11-26 18:58:24 +00:00
assert ( ! MPAimHighlight ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . realClientTime - MPAimFadeTime > 2000 )
{
2012-11-26 18:58:24 +00:00
MPAimFadeTime = 0 ;
}
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
hud - > ToggleLagged ( isLagged ) ;
2012-11-28 15:47:07 +00:00
// TODO_SPARTY: what is this projectile stuff for
2012-11-26 18:58:24 +00:00
//hud->SetStateInt( "g_showProjectilePct", g_showProjectilePct.GetInteger() );
//if ( numProjectilesFired ) {
// hud->SetStateString( "projectilepct", va( "Hit %% %.1f", ( (float) numProjectileHits / numProjectilesFired ) * 100 ) );
//} else {
// hud->SetStateString( "projectilepct", "Hit % 0.0" );
//}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : UpdateDeathSkin
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateDeathSkin ( bool state_hitch )
{
if ( ! ( common - > IsMultiplayer ( ) | | g_testDeath . GetBool ( ) ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( health < = 0 )
{
if ( ! doingDeathSkin )
{
2012-11-26 18:58:24 +00:00
deathClearContentsTime = spawnArgs . GetInt ( " deathSkinTime " ) ;
doingDeathSkin = true ;
renderEntity . noShadow = true ;
2012-11-28 15:47:07 +00:00
if ( state_hitch )
{
2012-11-26 18:58:24 +00:00
renderEntity . shaderParms [ SHADERPARM_TIME_OF_DEATH ] = gameLocal . time * 0.001f - 2.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderEntity . shaderParms [ SHADERPARM_TIME_OF_DEATH ] = gameLocal . time * 0.001f ;
}
UpdateVisuals ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// wait a bit before switching off the content
2012-11-28 15:47:07 +00:00
if ( deathClearContentsTime & & gameLocal . time > deathClearContentsTime )
{
2012-11-26 18:58:24 +00:00
SetCombatContents ( false ) ;
deathClearContentsTime = 0 ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderEntity . noShadow = false ;
renderEntity . shaderParms [ SHADERPARM_TIME_OF_DEATH ] = 0.0f ;
UpdateVisuals ( ) ;
doingDeathSkin = false ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : StartFxOnBone
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : StartFxOnBone ( const char * fx , const char * bone )
{
2012-11-26 18:58:24 +00:00
idVec3 offset ;
idMat3 axis ;
jointHandle_t jointHandle = GetAnimator ( ) - > GetJointHandle ( bone ) ;
2012-11-28 15:47:07 +00:00
if ( jointHandle = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " Cannot find bone %s \n " , bone ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( GetAnimator ( ) - > GetJointTransform ( jointHandle , gameLocal . time , offset , axis ) )
{
2012-11-26 18:58:24 +00:00
offset = GetPhysics ( ) - > GetOrigin ( ) + offset * GetPhysics ( ) - > GetAxis ( ) ;
axis = axis * GetPhysics ( ) - > GetAxis ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idEntityFx : : StartFx ( fx , & offset , & axis , this , true ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : HandleGuiEvents
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : HandleGuiEvents ( const sysEvent_t * ev )
{
2012-11-26 18:58:24 +00:00
bool handled = false ;
2012-11-28 15:47:07 +00:00
if ( hudManager ! = NULL & & hudManager - > IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
handled = hudManager - > HandleGuiEvent ( ev ) ;
}
2012-11-28 15:47:07 +00:00
if ( pdaMenu ! = NULL & & pdaMenu - > IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
handled = pdaMenu - > HandleGuiEvent ( ev ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return handled ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : UpdateLaserSight
= = = = = = = = = = = = = =
*/
idCVar g_laserSightWidth ( " g_laserSightWidth " , " 2.0 " , CVAR_FLOAT | CVAR_ARCHIVE , " laser sight beam width " ) ;
idCVar g_laserSightLength ( " g_laserSightLength " , " 250 " , CVAR_FLOAT | CVAR_ARCHIVE , " laser sight beam length " ) ;
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdateLaserSight ( )
{
2012-11-26 18:58:24 +00:00
idVec3 muzzleOrigin ;
idMat3 muzzleAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// In Multiplayer, weapon might not have been spawned yet.
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! IsGameStereoRendered ( ) | |
! weapon . GetEntity ( ) - > ShowCrosshair ( ) | |
AI_DEAD | |
weapon - > IsHidden ( ) | |
! weapon - > GetMuzzlePositionWithHacks ( muzzleOrigin , muzzleAxis ) )
{
2012-11-26 18:58:24 +00:00
// hide it
laserSightRenderEntity . allowSurfaceInViewID = - 1 ;
2012-11-28 15:47:07 +00:00
if ( laserSightHandle = = - 1 )
{
2012-11-26 18:58:24 +00:00
laserSightHandle = gameRenderWorld - > AddEntityDef ( & laserSightRenderEntity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > UpdateEntityDef ( laserSightHandle , & laserSightRenderEntity ) ;
}
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// program the beam model
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// only show in the player's view
2012-11-28 15:47:07 +00:00
laserSightRenderEntity . allowSurfaceInViewID = entityNumber + 1 ;
2012-11-26 18:58:24 +00:00
laserSightRenderEntity . axis . Identity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
laserSightRenderEntity . origin = muzzleOrigin - muzzleAxis [ 0 ] * 2.0f ;
2012-11-28 15:47:07 +00:00
idVec3 & target = * reinterpret_cast < idVec3 * > ( & laserSightRenderEntity . shaderParms [ SHADERPARM_BEAM_END_X ] ) ;
2012-11-26 18:58:24 +00:00
target = muzzleOrigin + muzzleAxis [ 0 ] * g_laserSightLength . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
laserSightRenderEntity . shaderParms [ SHADERPARM_BEAM_WIDTH ] = g_laserSightWidth . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
if ( IsGameStereoRendered ( ) & & laserSightHandle = = - 1 )
{
2012-11-26 18:58:24 +00:00
laserSightHandle = gameRenderWorld - > AddEntityDef ( & laserSightRenderEntity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > UpdateEntityDef ( laserSightHandle , & laserSightRenderEntity ) ;
}
}
/*
= = = = = = = = = = = = = =
idPlayer : : Think
Called every tic for each player
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Think ( )
{
2012-11-26 18:58:24 +00:00
playedTimeResidual + = ( gameLocal . time - gameLocal . previousTime ) ;
playedTimeSecs + = playedTimeResidual / 1000 ;
playedTimeResidual = playedTimeResidual % 1000 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
aimAssist . Update ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdatePlayerIcons ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateSkinSetup ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
buttonMask & = usercmd . buttons ;
usercmd . buttons & = ~ buttonMask ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the ik before we do anything else so the skeleton doesn't get updated twice
walkIK . ClearJointMods ( ) ;
// if this is the very first frame of the map, set the delta view angles
// based on the usercmd angles
2012-11-28 15:47:07 +00:00
if ( ! spawnAnglesSet & & ( gameLocal . GameState ( ) ! = GAMESTATE_STARTUP ) )
{
2012-11-26 18:58:24 +00:00
spawnAnglesSet = true ;
SetViewAngles ( spawnAngles ) ;
oldImpulseSequence = usercmd . impulseSequence ;
}
2012-11-28 15:47:07 +00:00
if ( mountedObject )
{
2012-11-26 18:58:24 +00:00
usercmd . forwardmove = 0 ;
usercmd . rightmove = 0 ;
2012-11-28 15:47:07 +00:00
usercmd . buttons & = ~ ( BUTTON_JUMP | BUTTON_CROUCH ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( objectiveSystemOpen | | gameLocal . inCinematic | | influenceActive )
{
if ( objectiveSystemOpen & & AI_PAIN )
{
2012-11-26 18:58:24 +00:00
TogglePDA ( ) ;
}
usercmd . forwardmove = 0 ;
usercmd . rightmove = 0 ;
2012-11-28 15:47:07 +00:00
usercmd . buttons & = ~ ( BUTTON_JUMP | BUTTON_CROUCH ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// log movement changes for weapon bobbing effects
2012-11-28 15:47:07 +00:00
if ( usercmd . forwardmove ! = oldCmd . forwardmove )
{
loggedAccel_t * acc = & loggedAccel [ currentLoggedAccel & ( NUM_LOGGED_ACCELS - 1 ) ] ;
2012-11-26 18:58:24 +00:00
currentLoggedAccel + + ;
acc - > time = gameLocal . time ;
acc - > dir [ 0 ] = usercmd . forwardmove - oldCmd . forwardmove ;
acc - > dir [ 1 ] = acc - > dir [ 2 ] = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( usercmd . rightmove ! = oldCmd . rightmove )
{
loggedAccel_t * acc = & loggedAccel [ currentLoggedAccel & ( NUM_LOGGED_ACCELS - 1 ) ] ;
2012-11-26 18:58:24 +00:00
currentLoggedAccel + + ;
acc - > time = gameLocal . time ;
acc - > dir [ 1 ] = usercmd . rightmove - oldCmd . rightmove ;
acc - > dir [ 0 ] = acc - > dir [ 2 ] = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// zooming
2012-11-28 15:47:07 +00:00
if ( ( usercmd . buttons ^ oldCmd . buttons ) & BUTTON_ZOOM )
{
if ( ( usercmd . buttons & BUTTON_ZOOM ) & & weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
zoomFov . Init ( gameLocal . time , 200.0f , CalcFov ( false ) , weapon . GetEntity ( ) - > GetZoomFov ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
zoomFov . Init ( gameLocal . time , 200.0f , zoomFov . GetCurrentValue ( gameLocal . time ) , DefaultFov ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we have an active gui, we will unrotate the view angles as
// we turn the mouse movements into gui events
2012-11-28 15:47:07 +00:00
idUserInterface * gui = ActiveGui ( ) ;
if ( gui & & gui ! = focusUI )
{
RouteGuiMouse ( gui ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the push velocity on the weapon before running the physics
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > SetPushVelocity ( physicsObj . GetPushedLinearVelocity ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
EvaluateControls ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! af . IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
AdjustBodyAngles ( ) ;
CopyJointsFromBodyToHead ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
// Local player on the server. Do normal movement.
Move ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Server is processing a client. Run client's commands like normal...
Move ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ...then correct if needed.
RunPhysics_RemoteClientCorrection ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! g_stopTime . GetBool ( ) )
{
if ( ! noclip & & ! spectating & & ( health > 0 ) & & ! IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
TouchTriggers ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// not done on clients for various reasons. don't do it on server and save the sound channel for other things
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
SetCurrentHeartRate ( ) ;
float scale = new_g_damageScale ;
2012-11-28 15:47:07 +00:00
if ( g_useDynamicProtection . GetBool ( ) & & scale < 1.0f & & gameLocal . time - lastDmgTime > 500 )
{
if ( scale < 1.0f )
{
2012-11-26 18:58:24 +00:00
scale + = 0.05f ;
}
2012-11-28 15:47:07 +00:00
if ( scale > 1.0f )
{
2012-11-26 18:58:24 +00:00
scale = 1.0f ;
}
new_g_damageScale = scale ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update GUIs, Items, and character interactions
UpdateFocus ( ) ;
UpdateLocation ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update player script
UpdateScript ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// service animations
2012-11-28 15:47:07 +00:00
if ( ! spectating & & ! af . IsActive ( ) & & ! gameLocal . inCinematic )
{
UpdateConditions ( ) ;
2012-11-26 18:58:24 +00:00
UpdateAnimState ( ) ;
CheckBlink ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear out our pain flag so we can tell if we recieve any damage between now and the next time we think
AI_PAIN = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calculate the exact bobbed view position, which is used to
// position the view weapon, among other things
CalculateFirstPersonView ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// this may use firstPersonView, or a thirdPeroson / camera view
CalculateRenderView ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . UpdateArmor ( ) ;
2012-11-28 15:47:07 +00:00
if ( spectating )
{
2012-11-26 18:58:24 +00:00
UpdateSpectating ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( health > 0 )
{
2012-11-26 18:58:24 +00:00
UpdateWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateFlashlight ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateAir ( ) ;
UpdatePowerupHud ( ) ;
UpdateHud ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdatePowerUps ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateDeathSkin ( false ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
DrawPlayerIcons ( ) ;
2012-11-28 15:47:07 +00:00
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
idAngles lightAng = firstPersonViewAxis . ToAngles ( ) ;
idVec3 lightOrg = firstPersonViewOrigin ;
2012-11-28 15:47:07 +00:00
const idDict * lightDef = gameLocal . FindEntityDefDict ( " envirosuit_light " , false ) ;
2012-11-26 18:58:24 +00:00
idVec3 enviroOffset = lightDef - > GetVector ( " enviro_offset " ) ;
idVec3 enviroAngleOffset = lightDef - > GetVector ( " enviro_angle_offset " ) ;
2012-11-28 15:47:07 +00:00
lightOrg + = ( enviroOffset . x * firstPersonViewAxis [ 0 ] ) ;
lightOrg + = ( enviroOffset . y * firstPersonViewAxis [ 1 ] ) ;
lightOrg + = ( enviroOffset . z * firstPersonViewAxis [ 2 ] ) ;
2012-11-26 18:58:24 +00:00
lightAng . pitch + = enviroAngleOffset . x ;
lightAng . yaw + = enviroAngleOffset . y ;
lightAng . roll + = enviroAngleOffset . z ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetOrigin ( lightOrg ) ;
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetAxis ( lightAng . ToMat3 ( ) ) ;
enviroSuitLight . GetEntity ( ) - > UpdateVisuals ( ) ;
enviroSuitLight . GetEntity ( ) - > Present ( ) ;
}
}
2012-11-28 15:47:07 +00:00
renderEntity_t * headRenderEnt = NULL ;
if ( head . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
headRenderEnt = head . GetEntity ( ) - > GetRenderEntity ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( headRenderEnt )
{
if ( influenceSkin )
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > customSkin = influenceSkin ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > customSkin = NULL ;
}
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) | | g_showPlayerShadow . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
renderEntity . suppressShadowInViewID = 0 ;
2012-11-28 15:47:07 +00:00
if ( headRenderEnt )
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > suppressShadowInViewID = 0 ;
}
2012-11-28 15:47:07 +00:00
}
else
{
renderEntity . suppressShadowInViewID = entityNumber + 1 ;
if ( headRenderEnt )
{
headRenderEnt - > suppressShadowInViewID = entityNumber + 1 ;
2012-11-26 18:58:24 +00:00
}
}
// never cast shadows from our first-person muzzle flashes
renderEntity . suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber ;
2012-11-28 15:47:07 +00:00
if ( headRenderEnt )
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber ;
}
2012-11-28 15:47:07 +00:00
if ( ! g_stopTime . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
UpdateAnimation ( ) ;
2012-11-28 15:47:07 +00:00
Present ( ) ;
2012-11-26 18:58:24 +00:00
UpdateDamageEffects ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
LinkCombat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
playerView . CalculateShake ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! ( thinkFlags & TH_THINK ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " player %d not thinking? \n " , entityNumber ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_showEnemies . GetBool ( ) )
{
idActor * ent ;
2012-11-26 18:58:24 +00:00
int num = 0 ;
2012-11-28 15:47:07 +00:00
for ( ent = enemyList . Next ( ) ; ent ! = NULL ; ent = ent - > enemyNode . Next ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " enemy (%d)'%s' \n " , ent - > entityNumber , ent - > name . c_str ( ) ) ;
gameRenderWorld - > DebugBounds ( colorRed , ent - > GetPhysics ( ) - > GetBounds ( ) . Expand ( 2 ) , ent - > GetPhysics ( ) - > GetOrigin ( ) ) ;
num + + ;
}
gameLocal . Printf ( " %d: enemies \n " , num ) ;
}
2012-11-28 15:47:07 +00:00
inventory . RechargeAmmo ( this ) ;
if ( healthRecharge )
{
2012-11-26 18:58:24 +00:00
int elapsed = gameLocal . time - lastHealthRechargeTime ;
2012-11-28 15:47:07 +00:00
if ( elapsed > = rechargeSpeed )
{
int intervals = ( gameLocal . time - lastHealthRechargeTime ) / rechargeSpeed ;
Give ( " health " , va ( " %d " , intervals ) , ITEM_GIVE_FEEDBACK | ITEM_GIVE_UPDATE_STATE ) ;
lastHealthRechargeTime + = intervals * rechargeSpeed ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// determine if portal sky is in pvs
gameLocal . portalSkyActive = gameLocal . pvs . CheckAreasForPortalSky ( gameLocal . GetPlayerPVS ( ) , GetPhysics ( ) - > GetOrigin ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stereo rendering laser sight that replaces the crosshair
UpdateLaserSight ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Show the respawn hud message if necessary.
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & ( minRespawnTime ! = maxRespawnTime ) )
{
if ( gameLocal . previousTime < minRespawnTime & & minRespawnTime < = gameLocal . time )
{
2012-11-26 18:58:24 +00:00
// Server will show the hud message directly.
ShowRespawnHudMessage ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure voice groups are set to the right team
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & session - > GetState ( ) > = idSession : : INGAME & & entityNumber < MAX_CLIENTS ) // The entityNumber < MAX_CLIENTS seems to quiet the static analyzer
{
2012-11-26 18:58:24 +00:00
// Make sure we're on the right team (at the lobby level)
const int voiceTeam = spectating ? LOBBY_SPECTATE_TEAM_FOR_VOICE_CHAT : team ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//idLib::Printf( "SERVER: Sending voice %i / %i\n", entityNumber, voiceTeam );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Update lobby team
session - > GetActingGameStateLobbyBase ( ) . SetLobbyUserTeam ( gameLocal . lobbyUserIDs [ entityNumber ] , voiceTeam ) ;
// Update voice groups to match in case something changed
session - > SetVoiceGroupsToTeams ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : StartHealthRecharge
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : StartHealthRecharge ( int speed )
{
2012-11-26 18:58:24 +00:00
lastHealthRechargeTime = gameLocal . time ;
healthRecharge = true ;
rechargeSpeed = speed ;
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : StopHealthRecharge
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : StopHealthRecharge ( )
{
2012-11-26 18:58:24 +00:00
healthRecharge = false ;
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : GetCurrentWeapon
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idStr idPlayer : : GetCurrentWeapon ( )
{
const char * weapon ;
if ( currentWeapon > = 0 )
{
2012-11-26 18:58:24 +00:00
weapon = spawnArgs . GetString ( va ( " def_weapon%d " , currentWeapon ) ) ;
return weapon ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return " " ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : CanGive
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : CanGive ( const char * statname , const char * value )
{
if ( AI_DEAD )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( statname , " health " ) )
{
if ( health > = inventory . maxHealth )
{
2012-11-26 18:58:24 +00:00
return false ;
}
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " stamina " ) )
{
if ( stamina > = 100 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " heartRate " ) )
{
2012-11-26 18:58:24 +00:00
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( ! idStr : : Icmp ( statname , " air " ) )
{
if ( airMsec > = pm_airMsec . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return inventory . CanGive ( this , spawnArgs , statname , value ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : StopHelltime
provides a quick non - ramping way of stopping helltime
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : StopHelltime ( bool quick )
{
if ( ! PowerUpActive ( HELLTIME ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// take away the powerups
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( INVULNERABILITY ) )
{
2012-11-26 18:58:24 +00:00
ClearPowerup ( INVULNERABILITY ) ;
}
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( BERSERK ) )
{
2012-11-26 18:58:24 +00:00
ClearPowerup ( BERSERK ) ;
}
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( HELLTIME ) )
{
2012-11-26 18:58:24 +00:00
ClearPowerup ( HELLTIME ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stop the looping sound
StopSound ( SND_CHANNEL_DEMONIC , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset the game vars
2012-11-28 15:47:07 +00:00
if ( quick )
{
2012-11-26 18:58:24 +00:00
gameLocal . QuickSlowmoReset ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : Event_ToggleBloom
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_ToggleBloom ( int on )
{
if ( on )
{
2012-11-26 18:58:24 +00:00
bloomEnabled = true ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
bloomEnabled = false ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : Event_SetBloomParms
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_SetBloomParms ( float speed , float intensity )
{
2012-11-26 18:58:24 +00:00
bloomSpeed = speed ;
bloomIntensity = intensity ;
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : PlayHelltimeStopSound
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : PlayHelltimeStopSound ( )
{
2012-11-26 18:58:24 +00:00
const char * sound ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " snd_helltime_stop " , " " , & sound ) )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_StartSoundShader , 0 , sound , SND_CHANNEL_ANY ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : RouteGuiMouse
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RouteGuiMouse ( idUserInterface * gui )
{
2012-11-26 18:58:24 +00:00
sysEvent_t ev ;
2012-11-28 15:47:07 +00:00
const char * command ;
if ( usercmd . mx ! = oldMouseX | | usercmd . my ! = oldMouseY )
{
2012-11-26 18:58:24 +00:00
ev = sys - > GenerateMouseMoveEvent ( usercmd . mx - oldMouseX , usercmd . my - oldMouseY ) ;
command = gui - > HandleEvent ( & ev , gameLocal . time ) ;
oldMouseX = usercmd . mx ;
oldMouseY = usercmd . my ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : LookAtKiller
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : LookAtKiller ( idEntity * inflictor , idEntity * attacker )
{
2012-11-26 18:58:24 +00:00
idVec3 dir ;
2012-11-28 15:47:07 +00:00
if ( attacker & & attacker ! = this )
{
2012-11-26 18:58:24 +00:00
dir = attacker - > GetPhysics ( ) - > GetOrigin ( ) - GetPhysics ( ) - > GetOrigin ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( inflictor & & inflictor ! = this )
{
2012-11-26 18:58:24 +00:00
dir = inflictor - > GetPhysics ( ) - > GetOrigin ( ) - GetPhysics ( ) - > GetOrigin ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
dir = viewAxis [ 0 ] ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idAngles ang ( 0 , dir . ToYaw ( ) , 0 ) ;
SetViewAngles ( ang ) ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : Kill
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Kill ( bool delayRespawn , bool nodamage )
{
if ( spectating )
{
2012-11-26 18:58:24 +00:00
SpectateFreeFly ( false ) ;
2012-11-28 15:47:07 +00:00
}
else if ( health > 0 )
{
2012-11-26 18:58:24 +00:00
godmode = false ;
2012-11-28 15:47:07 +00:00
if ( nodamage )
{
2012-11-26 18:58:24 +00:00
ServerSpectate ( true ) ;
2012-11-28 15:47:07 +00:00
idLib : : Printf ( " TOURNEY Kill :> Player %d On Deck \n " , entityNumber ) ;
2012-11-26 18:58:24 +00:00
forceRespawn = true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Damage ( this , this , vec3_origin , " damage_suicide " , 1.0f , INVALID_JOINT ) ;
2012-11-28 15:47:07 +00:00
if ( delayRespawn )
{
2012-11-26 18:58:24 +00:00
forceRespawn = false ;
int delay = spawnArgs . GetFloat ( " respawn_delay " ) ;
minRespawnTime = gameLocal . time + SEC2MS ( delay ) ;
maxRespawnTime = minRespawnTime + MAX_RESPAWN_TIME ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Killed
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location )
{
2012-11-26 18:58:24 +00:00
float delay ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stop taking knockback once dead
fl . noknockback = true ;
2012-11-28 15:47:07 +00:00
if ( health < - 999 )
{
2012-11-26 18:58:24 +00:00
health = - 999 ;
}
2012-11-28 15:47:07 +00:00
if ( AI_DEAD )
{
2012-11-26 18:58:24 +00:00
AI_PAIN = true ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
heartInfo . Init ( 0 , 0 , 0 , BASE_HEARTRATE ) ;
AdjustHeartRate ( DEAD_HEARTRATE , 10.0f , 0.0f , true ) ;
2012-11-28 15:47:07 +00:00
if ( ! g_testDeath . GetBool ( ) & & ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
playerView . Fade ( colorBlack , 3000 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AI_DEAD = true ;
SetAnimState ( ANIMCHANNEL_LEGS , " Legs_Death " , 4 ) ;
SetAnimState ( ANIMCHANNEL_TORSO , " Torso_Death " , 4 ) ;
SetWaitState ( " " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animator . ClearAllJoints ( ) ;
2012-11-28 15:47:07 +00:00
if ( StartRagdoll ( ) )
{
2012-11-26 18:58:24 +00:00
pm_modelView . SetInteger ( 0 ) ;
minRespawnTime = gameLocal . time + RAGDOLL_DEATH_TIME ;
maxRespawnTime = minRespawnTime + MAX_RESPAWN_TIME ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// don't allow respawn until the death anim is done
// g_forcerespawn may force spawning at some later time
delay = spawnArgs . GetFloat ( " respawn_delay " ) ;
minRespawnTime = gameLocal . time + SEC2MS ( delay ) ;
maxRespawnTime = minRespawnTime + MAX_RESPAWN_TIME ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetMovementType ( PM_DEAD ) ;
StartSound ( " snd_death " , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
StopSound ( SND_CHANNEL_BODY2 , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fl . takedamage = true ; // can still be gibbed
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get rid of weapon
weapon . GetEntity ( ) - > OwnerDied ( ) ;
// In multiplayer, get rid of the flashlight, or other players
// will see it floating after the player is dead.
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
FlashlightOff ( ) ;
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > OwnerDied ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// drop the weapon as an item
DropWeapon ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// drop the flag if player was carrying it
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & gameLocal . mpGame . IsGametypeFlagBased ( ) & & carryingFlag )
{
2012-11-26 18:58:24 +00:00
DropFlag ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! g_testDeath . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
LookAtKiller ( inflictor , attacker ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) | | g_testDeath . GetBool ( ) )
{
idPlayer * killer = NULL ;
2012-11-26 18:58:24 +00:00
// no gibbing in MP. Event_Gib will early out in MP
2012-11-28 15:47:07 +00:00
if ( attacker - > IsType ( idPlayer : : Type ) )
{
killer = static_cast < idPlayer * > ( attacker ) ;
if ( health < - 20 | | killer - > PowerUpActive ( BERSERK ) )
{
2012-11-26 18:58:24 +00:00
gibDeath = true ;
gibsDir = dir ;
gibsLaunched = false ;
}
}
gameLocal . mpGame . PlayerDeath ( this , killer , isTelefragged ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( CONTENTS_CORPSE | CONTENTS_MONSTERCLIP ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ClearPowerUps ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idPlayer : : GetAIAimTargets
Returns positions for the AI to aim at .
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GetAIAimTargets ( const idVec3 & lastSightPos , idVec3 & headPos , idVec3 & chestPos )
{
2012-11-26 18:58:24 +00:00
idVec3 offset ;
idMat3 axis ;
idVec3 origin ;
origin = lastSightPos - physicsObj . GetOrigin ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetJointWorldTransform ( chestJoint , gameLocal . time , offset , axis ) ;
headPos = offset + origin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetJointWorldTransform ( headJoint , gameLocal . time , offset , axis ) ;
chestPos = offset + origin ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : DamageFeedback
callback function for when another entity received damage from this entity . damage can be adjusted and returned to the caller .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : DamageFeedback ( idEntity * victim , idEntity * inflictor , int & damage )
{
2012-11-26 18:58:24 +00:00
// Since we're predicting projectiles on the client now, we might actually get here
// (used be an assert for clients).
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
damage * = PowerUpModifier ( BERSERK ) ;
2012-11-28 15:47:07 +00:00
if ( damage & & ( victim ! = this ) & & ( victim - > IsType ( idActor : : Type ) | | victim - > IsType ( idDamagable : : Type ) ) )
{
idPlayer * victimPlayer = NULL ;
/* No damage feedback sound for hitting friendlies in CTF */
if ( victim - > IsType ( idPlayer : : Type ) )
{
victimPlayer = static_cast < idPlayer * > ( victim ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . mpGame . IsGametypeFlagBased ( ) & & victimPlayer & & this - > team = = victimPlayer - > team )
{
/* Do nothing ... */
}
else
{
2012-11-26 18:58:24 +00:00
SetLastHitTime ( gameLocal . time ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : CalcDamagePoints
Calculates how many health and armor points will be inflicted , but
doesn ' t actually do anything with them . This is used to tell when an attack
would have killed the player , possibly allowing a " saving throw "
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : CalcDamagePoints ( idEntity * inflictor , idEntity * attacker , const idDict * damageDef ,
const float damageScale , const int location , int * health , int * armor )
{
2012-11-26 18:58:24 +00:00
int damage ;
int armorSave ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
damageDef - > GetInt ( " damage " , " 20 " , damage ) ;
damage = GetDamageForLocation ( damage , location ) ;
2012-11-28 15:47:07 +00:00
idPlayer * player = attacker - > IsType ( idPlayer : : Type ) ? static_cast < idPlayer * > ( attacker ) : NULL ;
if ( ! common - > IsMultiplayer ( ) )
{
if ( inflictor ! = gameLocal . world )
{
switch ( g_skill . GetInteger ( ) )
{
case 0 :
2012-11-26 18:58:24 +00:00
damage * = 0.50f ;
2012-11-28 15:47:07 +00:00
if ( damage < 1 )
{
2012-11-26 18:58:24 +00:00
damage = 1 ;
}
break ;
case 2 :
damage * = 1.70f ;
break ;
case 3 :
damage * = 3.5f ;
break ;
default :
break ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
damage * = damageScale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// always give half damage if hurting self
2012-11-28 15:47:07 +00:00
if ( attacker = = this )
{
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
// only do this in mp so single player plasma and rocket splash is very dangerous in close quarters
damage * = damageDef - > GetFloat ( " selfDamageScale " , " 0.5 " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
damage * = damageDef - > GetFloat ( " selfDamageScale " , " 1 " ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for completely getting out of the damage
2012-11-28 15:47:07 +00:00
if ( ! damageDef - > GetBool ( " noGod " ) )
{
2012-11-26 18:58:24 +00:00
// check for godmode
2012-11-28 15:47:07 +00:00
if ( godmode )
{
2012-11-26 18:58:24 +00:00
damage = 0 ;
}
//Invulnerability is just like god mode
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( INVULNERABILITY ) )
{
2012-11-26 18:58:24 +00:00
damage = 0 ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// inform the attacker that they hit someone
attacker - > DamageFeedback ( this , inflictor , damage ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save some from armor
2012-11-28 15:47:07 +00:00
if ( ! damageDef - > GetBool ( " noArmor " ) )
{
2012-11-26 18:58:24 +00:00
float armor_protection ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
armor_protection = ( common - > IsMultiplayer ( ) ) ? g_armorProtectionMP . GetFloat ( ) : g_armorProtection . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
armorSave = ceil ( damage * armor_protection ) ;
2012-11-28 15:47:07 +00:00
if ( armorSave > = inventory . armor )
{
2012-11-26 18:58:24 +00:00
armorSave = inventory . armor ;
}
2012-11-28 15:47:07 +00:00
if ( ! damage )
{
2012-11-26 18:58:24 +00:00
armorSave = 0 ;
2012-11-28 15:47:07 +00:00
}
else if ( armorSave > = damage )
{
2012-11-26 18:58:24 +00:00
armorSave = damage - 1 ;
damage = 1 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
damage - = armorSave ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
armorSave = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for team damage
2012-11-28 15:47:07 +00:00
if ( gameLocal . mpGame . IsGametypeTeamBased ( ) /* CTF */
& & ! gameLocal . serverInfo . GetBool ( " si_teamDamage " )
& & ! damageDef - > GetBool ( " noTeam " )
& & player
& & player ! = this // you get self damage no matter what
& & player - > team = = team )
{
damage = 0 ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* health = damage ;
* armor = armorSave ;
}
/*
= = = = = = = = = = = =
idPlayer : : ControllerShakeFromDamage
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ControllerShakeFromDamage ( int damage )
{
2012-11-26 18:58:24 +00:00
// If the player is local. SHAkkkkkkeeee!
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
int maxMagScale = pm_controllerShake_damageMaxMag . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
int maxDurScale = pm_controllerShake_damageMaxDur . GetFloat ( ) ;
2012-11-26 18:58:24 +00:00
// determine rumble
// >= 100 damage - will be 300 Mag
float highMag = ( Max ( damage , 100 ) / 100.0f ) * maxMagScale ;
int highDuration = idMath : : Ftoi ( ( Max ( damage , 100 ) / 100.0f ) * maxDurScale ) ;
float lowMag = highMag * 0.75f ;
int lowDuration = idMath : : Ftoi ( highDuration ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetControllerShake ( highMag , highDuration , lowMag , lowDuration ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = =
AdjustDamageAmount
Modifies the previously calculated damage to adjust for more factors .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPlayer : : AdjustDamageAmount ( const int inputDamage )
{
2012-11-26 18:58:24 +00:00
int outputDamage = inputDamage ;
2012-11-28 15:47:07 +00:00
if ( inputDamage > 0 )
{
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
float scale = new_g_damageScale ;
2012-11-28 15:47:07 +00:00
if ( g_useDynamicProtection . GetBool ( ) & & g_skill . GetInteger ( ) < 2 )
{
if ( gameLocal . time > lastDmgTime + 500 & & scale > 0.25f )
{
2012-11-26 18:58:24 +00:00
scale - = 0.05f ;
new_g_damageScale = scale ;
}
}
2012-11-28 15:47:07 +00:00
if ( scale > 0.0f )
{
2012-11-26 18:58:24 +00:00
outputDamage * = scale ;
}
}
2012-11-28 15:47:07 +00:00
if ( g_demoMode . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
outputDamage / = 2 ;
}
2012-11-28 15:47:07 +00:00
if ( outputDamage < 1 )
{
2012-11-26 18:58:24 +00:00
outputDamage = 1 ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return outputDamage ;
}
/*
= = = = = = = = = = = =
ServerDealDamage
Only called on the server and in singleplayer . This is where
the player ' s health is actually modified , but the visual and
sound effects happen elsewhere so that clients can get instant
feedback and hide lag .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ServerDealDamage ( int damage , idEntity & inflictor , idEntity & attacker , const idVec3 & dir , const char * damageDefName , const int location )
{
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ;
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * damageDef = gameLocal . FindEntityDef ( damageDefName , false ) ;
if ( ! damageDef )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Unknown damageDef '%s' " , damageDefName ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move the world direction vector to local coordinates
idVec3 damage_from ;
2012-11-28 15:47:07 +00:00
idVec3 localDamageVector ;
2012-11-26 18:58:24 +00:00
damage_from = dir ;
damage_from . Normalize ( ) ;
viewAxis . ProjectVector ( damage_from , localDamageVector ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add to the damage inflicted on a player this frame
// the total will be turned into screen blends and view angle kicks
// at the end of the frame
2012-11-28 15:47:07 +00:00
if ( health > 0 )
{
2012-11-26 18:58:24 +00:00
playerView . DamageImpulse ( localDamageVector , & damageDef - > dict ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// do the damage
2012-11-28 15:47:07 +00:00
if ( damage > 0 )
{
2012-11-26 18:58:24 +00:00
GetAchievementManager ( ) . SetPlayerTookDamage ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int oldHealth = health ;
health - = damage ;
2012-11-28 15:47:07 +00:00
if ( health < = 0 )
{
if ( health < - 999 )
{
2012-11-26 18:58:24 +00:00
health = - 999 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// HACK - A - LICIOUS - Check to see if we are being damaged by the frag chamber.
2012-11-28 15:47:07 +00:00
if ( oldHealth > 0 & & strcmp ( gameLocal . GetMapName ( ) , " maps/game/mp/d3dm3.map " ) = = 0 & & strcmp ( damageDefName , " damage_triggerhurt_1000_chamber " ) = = 0 )
{
idPlayer * fragChamberActivator = gameLocal . playerActivateFragChamber ;
if ( fragChamberActivator ! = NULL )
{
2012-11-26 18:58:24 +00:00
fragChamberActivator - > GetAchievementManager ( ) . EventCompletesAchievement ( ACHIEVEMENT_MP_CATCH_ENEMY_IN_ROFC ) ;
}
gameLocal . playerActivateFragChamber = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
isTelefragged = damageDef - > dict . GetBool ( " telefrag " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastDmgTime = gameLocal . time ;
Killed ( & inflictor , & attacker , damage , dir , location ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( ! g_testDeath . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
lastDmgTime = gameLocal . time ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// don't accumulate impulses
2012-11-28 15:47:07 +00:00
if ( af . IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
// clear impacts
af . Rest ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// physics is turned off by calling af.Rest()
BecomeActive ( TH_PHYSICS ) ;
}
}
}
/*
= = = = = = = = = = = =
Damage
this entity that is being damaged
inflictor entity that is causing the damage
attacker entity that caused the inflictor to damage targ
example : this = monster , inflictor = rocket , attacker = player
dir direction of the attack for knockback in global space
damageDef an idDict with all the options for damage effects
inflictor , attacker , dir , and point can be NULL for environmental effects
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Damage ( idEntity * inflictor , idEntity * attacker , const idVec3 & dir ,
const char * damageDefName , const float damageScale , const int location )
{
2012-11-26 18:58:24 +00:00
idVec3 kick ;
int damage ;
int armorSave ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetTimeState ts ( timeGroup ) ;
2012-11-28 15:47:07 +00:00
if ( ! fl . takedamage | | noclip | | spectating | | gameLocal . inCinematic )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! inflictor )
{
2012-11-26 18:58:24 +00:00
inflictor = gameLocal . world ;
}
2012-11-28 15:47:07 +00:00
if ( ! attacker )
{
2012-11-26 18:58:24 +00:00
attacker = gameLocal . world ;
}
2012-11-28 15:47:07 +00:00
if ( attacker - > IsType ( idAI : : Type ) )
{
if ( PowerUpActive ( BERSERK ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
// don't take damage from monsters during influences
2012-11-28 15:47:07 +00:00
if ( influenceActive ! = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * damageDef = gameLocal . FindEntityDef ( damageDefName , false ) ;
if ( ! damageDef )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Unknown damageDef '%s' " , damageDefName ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( damageDef - > dict . GetBool ( " ignore_player " ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// determine knockback
int knockback = 0 ;
damageDef - > dict . GetInt ( " knockback " , " 20 " , knockback ) ;
2012-11-28 15:47:07 +00:00
if ( knockback ! = 0 & & ! fl . noknockback )
{
2012-11-26 18:58:24 +00:00
float attackerPushScale = 0.0f ;
2012-11-28 15:47:07 +00:00
if ( attacker = = this )
{
2012-11-26 18:58:24 +00:00
damageDef - > dict . GetFloat ( " attackerPushScale " , " 0 " , attackerPushScale ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
attackerPushScale = 1.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 kick = dir ;
kick . Normalize ( ) ;
kick * = g_knockback . GetFloat ( ) * knockback * attackerPushScale / 200.0f ;
physicsObj . SetLinearVelocity ( physicsObj . GetLinearVelocity ( ) + kick ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the timer so that the player can't cancel out the movement immediately
2012-11-28 15:47:07 +00:00
physicsObj . SetKnockBack ( idMath : : ClampInt ( 50 , 200 , knockback * 2 ) ) ;
if ( common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
msg . WriteFloat ( physicsObj . GetLinearVelocity ( ) [ 0 ] ) ;
msg . WriteFloat ( physicsObj . GetLinearVelocity ( ) [ 1 ] ) ;
msg . WriteFloat ( physicsObj . GetLinearVelocity ( ) [ 2 ] ) ;
msg . WriteByte ( idMath : : ClampInt ( 50 , 200 , knockback * 2 ) ) ;
ServerSendEvent ( idPlayer : : EVENT_KNOCKBACK , & msg , false ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If this is a locally controlled MP client, don't apply damage effects predictively here.
// Local clients will see the damage feedback (view kick, etc) when their health changes
// in a snapshot. This ensures that any feedback the local player sees is in sync with
// his actual health reported by the server.
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & common - > IsClient ( ) & & IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
CalcDamagePoints ( inflictor , attacker , & damageDef - > dict , damageScale , location , & damage , & armorSave ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// give feedback on the player view and audibly when armor is helping
2012-11-28 15:47:07 +00:00
if ( armorSave )
{
2012-11-26 18:58:24 +00:00
inventory . armor - = armorSave ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . time > lastArmorPulse + 200 )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_hitArmor " , SND_CHANNEL_ITEM , 0 , false , NULL ) ;
}
lastArmorPulse = gameLocal . time ;
}
2012-11-28 15:47:07 +00:00
if ( damageDef - > dict . GetBool ( " burn " ) )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_burn " , SND_CHANNEL_BODY3 , 0 , false , NULL ) ;
2012-11-28 15:47:07 +00:00
}
else if ( damageDef - > dict . GetBool ( " no_air " ) )
{
if ( ! armorSave & & health > 0 )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_airGasp " , SND_CHANNEL_ITEM , 0 , false , NULL ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( g_debugDamage . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " client:%02d \t damage type:%s \t \t health:%03d \t damage:%03d \t armor:%03d \n " , entityNumber , damageDef - > GetName ( ) , health , damage , armorSave ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
ControllerShakeFromDamage ( damage ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// The client needs to know the final damage amount for predictive pain animations.
const int finalDamage = AdjustDamageAmount ( damage ) ;
2012-11-28 15:47:07 +00:00
if ( health > 0 )
{
2012-11-26 18:58:24 +00:00
// force a blink
blink_time = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// let the anim script know we took damage
AI_PAIN = Pain ( inflictor , attacker , damage , dir , location ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Only actually deal the damage here in singleplayer and for locally controlled servers.
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) | | common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
// Server will deal his damage normally
ServerDealDamage ( finalDamage , * inflictor , * attacker , dir , damageDefName , location ) ;
2012-11-28 15:47:07 +00:00
}
else if ( attacker - > GetEntityNumber ( ) = = gameLocal . GetLocalClientNum ( ) )
{
2012-11-26 18:58:24 +00:00
// Clients send a reliable message to the server with the parameters of the hit. The
// server should make sure the client still has line-of-sight to its target before
// actually applying the damage.
2012-11-28 15:47:07 +00:00
byte msgBuffer [ MAX_GAME_MESSAGE_SIZE ] ;
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuffer , sizeof ( msgBuffer ) ) ;
msg . BeginWriting ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteShort ( attacker - > GetEntityNumber ( ) ) ;
msg . WriteShort ( GetEntityNumber ( ) ) ; // victim
msg . WriteVectorFloat ( dir ) ;
msg . WriteLong ( damageDef - > Index ( ) ) ;
msg . WriteFloat ( damageScale ) ;
msg . WriteLong ( location ) ;
2012-11-28 15:47:07 +00:00
idLobbyBase & lobby = session - > GetActingGameStateLobbyBase ( ) ;
2012-11-26 18:58:24 +00:00
lobby . SendReliableToHost ( GAME_RELIABLE_MESSAGE_CLIENT_HITSCAN_HIT , msg ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastDamageDef = damageDef - > Index ( ) ;
lastDamageDir = dir ;
lastDamageDir . Normalize ( ) ;
lastDamageLocation = location ;
}
/*
= = = = = = = = = = =
idPlayer : : Teleport
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Teleport ( const idVec3 & origin , const idAngles & angles , idEntity * destination )
{
2012-11-26 18:58:24 +00:00
idVec3 org ;
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > LowerWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetOrigin ( origin + idVec3 ( 0 , 0 , CM_CLIP_EPSILON ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) & & GetFloorPos ( 16.0f , org ) )
{
2012-11-26 18:58:24 +00:00
SetOrigin ( org ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the ik heights so model doesn't appear in the wrong place
walkIK . EnableAll ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetLinearVelocity ( vec3_origin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetViewAngles ( angles ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
legsYaw = 0.0f ;
idealLegsYaw = 0.0f ;
oldViewYaw = viewAngles . yaw ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
playerView . Flash ( colorWhite , 140 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
teleportEntity = destination ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsClient ( ) & & ! noclip )
{
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
// kill anything at the new position or mark for kill depending on immediate or delayed teleport
gameLocal . KillBox ( this , destination ! = NULL ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// kill anything at the new position
gameLocal . KillBox ( this , true ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( PowerUpActive ( HELLTIME ) )
{
2012-11-26 18:58:24 +00:00
StopHelltime ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idPlayer : : SetPrivateCameraView
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetPrivateCameraView ( idCamera * camView )
{
2012-11-26 18:58:24 +00:00
privateCameraView = camView ;
2012-11-28 15:47:07 +00:00
if ( camView )
{
2012-11-26 18:58:24 +00:00
StopFiring ( ) ;
Hide ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( ! spectating )
{
2012-11-26 18:58:24 +00:00
Show ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idPlayer : : DefaultFov
Returns the base FOV
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idPlayer : : DefaultFov ( ) const
{
2012-11-26 18:58:24 +00:00
float fov ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fov = g_fov . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
if ( fov < 80.0f )
{
2012-11-26 18:58:24 +00:00
return 80.0f ;
2012-11-28 15:47:07 +00:00
}
else if ( fov > 120.0f )
{
2012-11-26 18:58:24 +00:00
return 120.0f ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return fov ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idPlayer : : CalcFov
Fixed fov at intermissions , otherwise account for fov variable and zooms .
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idPlayer : : CalcFov ( bool honorZoom )
{
2012-11-26 18:58:24 +00:00
float fov ;
2012-11-28 15:47:07 +00:00
if ( fxFov )
{
2012-11-26 18:58:24 +00:00
return DefaultFov ( ) + 10.0f + cos ( ( gameLocal . time + 2000 ) * 0.01 ) * 10.0f ;
}
2012-11-28 15:47:07 +00:00
if ( influenceFov )
{
2012-11-26 18:58:24 +00:00
return influenceFov ;
}
2012-11-28 15:47:07 +00:00
if ( zoomFov . IsDone ( gameLocal . time ) )
{
2012-11-26 18:58:24 +00:00
fov = ( honorZoom & & usercmd . buttons & BUTTON_ZOOM ) & & weapon . GetEntity ( ) ? weapon . GetEntity ( ) - > GetZoomFov ( ) : DefaultFov ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
fov = zoomFov . GetCurrentValue ( gameLocal . time ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bound normal viewsize
2012-11-28 15:47:07 +00:00
if ( fov < 1 )
{
2012-11-26 18:58:24 +00:00
fov = 1 ;
2012-11-28 15:47:07 +00:00
}
else if ( fov > 179 )
{
2012-11-26 18:58:24 +00:00
fov = 179 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return fov ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : GunTurningOffset
generate a rotational offset for the gun based on the view angle
history in loggedViewAngles
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAngles idPlayer : : GunTurningOffset ( )
{
2012-11-26 18:58:24 +00:00
idAngles a ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
a . Zero ( ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . framenum < NUM_LOGGED_VIEW_ANGLES )
{
2012-11-26 18:58:24 +00:00
return a ;
}
2012-11-28 15:47:07 +00:00
idAngles current = loggedViewAngles [ gameLocal . framenum & ( NUM_LOGGED_VIEW_ANGLES - 1 ) ] ;
2012-11-26 18:58:24 +00:00
idAngles av , base ;
int weaponAngleOffsetAverages ;
float weaponAngleOffsetScale , weaponAngleOffsetMax ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > GetWeaponAngleOffsets ( & weaponAngleOffsetAverages , & weaponAngleOffsetScale , & weaponAngleOffsetMax ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
av = current ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calcualte this so the wrap arounds work properly
2012-11-28 15:47:07 +00:00
for ( int j = 1 ; j < weaponAngleOffsetAverages ; j + + )
{
idAngles a2 = loggedViewAngles [ ( gameLocal . framenum - j ) & ( NUM_LOGGED_VIEW_ANGLES - 1 ) ] ;
2012-11-26 18:58:24 +00:00
idAngles delta = a2 - current ;
2012-11-28 15:47:07 +00:00
if ( delta [ 1 ] > 180 )
{
2012-11-26 18:58:24 +00:00
delta [ 1 ] - = 360 ;
2012-11-28 15:47:07 +00:00
}
else if ( delta [ 1 ] < - 180 )
{
2012-11-26 18:58:24 +00:00
delta [ 1 ] + = 360 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
av + = delta * ( 1.0f / weaponAngleOffsetAverages ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
a = ( av - current ) * weaponAngleOffsetScale ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 3 ; i + + )
{
if ( a [ i ] < - weaponAngleOffsetMax )
{
2012-11-26 18:58:24 +00:00
a [ i ] = - weaponAngleOffsetMax ;
2012-11-28 15:47:07 +00:00
}
else if ( a [ i ] > weaponAngleOffsetMax )
{
2012-11-26 18:58:24 +00:00
a [ i ] = weaponAngleOffsetMax ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return a ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : GunAcceleratingOffset
generate a positional offset for the gun based on the movement
history in loggedAccelerations
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idVec3 idPlayer : : GunAcceleratingOffset ( )
{
2012-11-26 18:58:24 +00:00
idVec3 ofs ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float weaponOffsetTime , weaponOffsetScale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ofs . Zero ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > GetWeaponTimeOffsets ( & weaponOffsetTime , & weaponOffsetScale ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int stop = currentLoggedAccel - NUM_LOGGED_ACCELS ;
2012-11-28 15:47:07 +00:00
if ( stop < 0 )
{
2012-11-26 18:58:24 +00:00
stop = 0 ;
}
2012-11-28 15:47:07 +00:00
for ( int i = currentLoggedAccel - 1 ; i > stop ; i - - )
{
loggedAccel_t * acc = & loggedAccel [ i & ( NUM_LOGGED_ACCELS - 1 ) ] ;
2012-11-26 18:58:24 +00:00
float f ;
float t = gameLocal . time - acc - > time ;
2012-11-28 15:47:07 +00:00
if ( t > = weaponOffsetTime )
{
2012-11-26 18:58:24 +00:00
break ; // remainder are too old to care about
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
f = t / weaponOffsetTime ;
f = ( cos ( f * 2.0f * idMath : : PI ) - 1.0f ) * 0.5f ;
ofs + = f * weaponOffsetScale * acc - > dir ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return ofs ;
}
/*
= = = = = = = = = = = = = =
idPlayer : : CalculateViewWeaponPos
Calculate the bobbing position of the view weapon
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : CalculateViewWeaponPos ( idVec3 & origin , idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
float scale ;
float fracsin ;
idAngles angles ;
int delta ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// CalculateRenderView must have been called first
2012-11-28 15:47:07 +00:00
const idVec3 & viewOrigin = firstPersonViewOrigin ;
const idMat3 & viewAxis = firstPersonViewAxis ;
2012-11-26 18:58:24 +00:00
// these cvars are just for hand tweaking before moving a value to the weapon def
idVec3 gunpos ( g_gun_x . GetFloat ( ) , g_gun_y . GetFloat ( ) , g_gun_z . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// as the player changes direction, the gun will take a small lag
idVec3 gunOfs = GunAcceleratingOffset ( ) ;
origin = viewOrigin + ( gunpos + gunOfs ) * viewAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// on odd legs, invert some angles
2012-11-28 15:47:07 +00:00
if ( bobCycle & 128 )
{
2012-11-26 18:58:24 +00:00
scale = - xyspeed ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
scale = xyspeed ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// gun angles from bobbing
angles . roll = scale * bobfracsin * 0.005f ;
angles . yaw = scale * bobfracsin * 0.01f ;
angles . pitch = xyspeed * bobfracsin * 0.005f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// gun angles from turning
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
idAngles offset = GunTurningOffset ( ) ;
offset * = g_mpWeaponAngleScale . GetFloat ( ) ;
angles + = offset ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
angles + = GunTurningOffset ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 gravity = physicsObj . GetGravityNormal ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// drop the weapon when landing after a jump / fall
delta = gameLocal . time - landTime ;
2012-11-28 15:47:07 +00:00
if ( delta < LAND_DEFLECT_TIME )
{
origin - = gravity * ( landChange * 0.25f * delta / LAND_DEFLECT_TIME ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME )
{
origin - = gravity * ( landChange * 0.25f * ( LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta ) / LAND_RETURN_TIME ) ;
}
2012-11-26 18:58:24 +00:00
// speed sensitive idle drift
scale = xyspeed + 40.0f ;
fracsin = scale * sin ( MS2SEC ( gameLocal . time ) ) * 0.01f ;
angles . roll + = fracsin ;
angles . yaw + = fracsin ;
angles . pitch + = fracsin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// decoupled weapon aiming in head mounted displays
angles . pitch + = independentWeaponPitchAngle ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const idMat3 anglesMat = angles . ToMat3 ( ) ;
const idMat3 scaledMat = anglesMat * g_gunScale . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis = scaledMat * viewAxis ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : OffsetThirdPersonView
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : OffsetThirdPersonView ( float angle , float range , float height , bool clip )
{
2012-11-26 18:58:24 +00:00
idVec3 view ;
idVec3 focusAngles ;
trace_t trace ;
idVec3 focusPoint ;
float focusDist ;
float forwardScale , sideScale ;
idVec3 origin ;
idAngles angles ;
idMat3 axis ;
idBounds bounds ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
angles = viewAngles ;
GetViewPos ( origin , axis ) ;
2012-11-28 15:47:07 +00:00
if ( angle )
{
2012-11-26 18:58:24 +00:00
angles . pitch = 0.0f ;
}
2012-11-28 15:47:07 +00:00
if ( angles . pitch > 45.0f )
{
2012-11-26 18:58:24 +00:00
angles . pitch = 45.0f ; // don't go too far overhead
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
focusPoint = origin + angles . ToForward ( ) * THIRD_PERSON_FOCUS_DISTANCE ;
focusPoint . z + = height ;
view = origin ;
view . z + = 8 + height ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
angles . pitch * = 0.5f ;
renderView - > viewaxis = angles . ToMat3 ( ) * physicsObj . GetGravityAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idMath : : SinCos ( DEG2RAD ( angle ) , sideScale , forwardScale ) ;
view - = range * forwardScale * renderView - > viewaxis [ 0 ] ;
view + = range * sideScale * renderView - > viewaxis [ 1 ] ;
2012-11-28 15:47:07 +00:00
if ( clip )
{
2012-11-26 18:58:24 +00:00
// trace a ray from the origin to the viewpoint to make sure the view isn't
// in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything
bounds = idBounds ( idVec3 ( - 4 , - 4 , - 4 ) , idVec3 ( 4 , 4 , 4 ) ) ;
gameLocal . clip . TraceBounds ( trace , origin , view , bounds , MASK_SOLID , this ) ;
2012-11-28 15:47:07 +00:00
if ( trace . fraction ! = 1.0f )
{
2012-11-26 18:58:24 +00:00
view = trace . endpos ;
view . z + = ( 1.0f - trace . fraction ) * 32.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// try another trace to this position, because a tunnel may have the ceiling
// close enough that this is poking out
gameLocal . clip . TraceBounds ( trace , origin , view , bounds , MASK_SOLID , this ) ;
view = trace . endpos ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// select pitch to look at focus point from vieword
focusPoint - = view ;
focusDist = idMath : : Sqrt ( focusPoint [ 0 ] * focusPoint [ 0 ] + focusPoint [ 1 ] * focusPoint [ 1 ] ) ;
2012-11-28 15:47:07 +00:00
if ( focusDist < 1.0f )
{
2012-11-26 18:58:24 +00:00
focusDist = 1.0f ; // should never happen
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
angles . pitch = - RAD2DEG ( atan2 ( focusPoint . z , focusDist ) ) ;
angles . yaw - = angle ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderView - > vieworg = view ;
renderView - > viewaxis = angles . ToMat3 ( ) * physicsObj . GetGravityAxis ( ) ;
renderView - > viewID = 0 ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GetEyePosition
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idVec3 idPlayer : : GetEyePosition ( ) const
{
2012-11-26 18:58:24 +00:00
idVec3 org ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// use the smoothed origin if spectating another player in multiplayer
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) & & ! IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
org = smoothedOrigin ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
org = GetPhysics ( ) - > GetOrigin ( ) ;
}
return org + ( GetPhysics ( ) - > GetGravityNormal ( ) * - eyeOffset . z ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : GetViewPos
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GetViewPos ( idVec3 & origin , idMat3 & axis ) const
{
2012-11-26 18:58:24 +00:00
idAngles angles ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if dead, fix the angle and don't add any kick
2012-11-28 15:47:07 +00:00
if ( health < = 0 )
{
2012-11-26 18:58:24 +00:00
angles . yaw = viewAngles . yaw ;
angles . roll = 40 ;
angles . pitch = - 15 ;
axis = angles . ToMat3 ( ) ;
origin = GetEyePosition ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
origin = GetEyePosition ( ) + viewBob ;
angles = viewAngles + viewBobAngles + playerView . AngleOffset ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis = angles . ToMat3 ( ) * physicsObj . GetGravityAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Move pivot point down so looking straight ahead is a no-op on the Z
2012-11-28 15:47:07 +00:00
const idVec3 & gravityVector = physicsObj . GetGravityNormal ( ) ;
2012-11-26 18:58:24 +00:00
origin + = gravityVector * g_viewNodalZ . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// adjust the origin based on the camera nodal distance (eye distance from neck)
origin + = axis [ 0 ] * g_viewNodalX . GetFloat ( ) + axis [ 2 ] * g_viewNodalZ . GetFloat ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : CalculateFirstPersonView
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : CalculateFirstPersonView ( )
{
if ( ( pm_modelView . GetInteger ( ) = = 1 ) | | ( ( pm_modelView . GetInteger ( ) = = 2 ) & & ( health < = 0 ) ) )
{
2012-11-26 18:58:24 +00:00
// Displays the view from the point of view of the "camera" joint in the player model
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idMat3 axis ;
idVec3 origin ;
idAngles ang ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ang = viewBobAngles + playerView . AngleOffset ( ) ;
ang . yaw + = viewAxis [ 0 ] . ToYaw ( ) ;
jointHandle_t joint = animator . GetJointHandle ( " camera " ) ;
animator . GetJointTransform ( joint , gameLocal . time , origin , axis ) ;
firstPersonViewOrigin = ( origin + modelOffset ) * ( viewAxis * physicsObj . GetGravityAxis ( ) ) + physicsObj . GetOrigin ( ) + viewBob ;
firstPersonViewAxis = axis * ang . ToMat3 ( ) * physicsObj . GetGravityAxis ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// offset for local bobbing and kicks
GetViewPos ( firstPersonViewOrigin , firstPersonViewAxis ) ;
#if 0
// shakefrom sound stuff only happens in first person
firstPersonViewAxis = firstPersonViewAxis * playerView . ShakeAxis ( ) ;
# endif
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : GetRenderView
Returns the renderView that was calculated for this tic
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
renderView_t * idPlayer : : GetRenderView ( )
{
2012-11-26 18:58:24 +00:00
return renderView ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : CalculateRenderView
create the renderView for the current tic
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : CalculateRenderView ( )
{
2012-11-26 18:58:24 +00:00
int i ;
float range ;
2012-11-28 15:47:07 +00:00
if ( ! renderView )
{
renderView = new ( TAG_ENTITY ) renderView_t ;
2012-11-26 18:58:24 +00:00
}
memset ( renderView , 0 , sizeof ( * renderView ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// copy global shader parms
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_GLOBAL_SHADER_PARMS ; i + + )
{
2012-11-26 18:58:24 +00:00
renderView - > shaderParms [ i ] = gameLocal . globalShaderParms [ i ] ;
}
renderView - > globalMaterial = gameLocal . GetGlobalMaterial ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderView - > time [ 0 ] = gameLocal . slow . time ;
renderView - > time [ 1 ] = gameLocal . fast . time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderView - > viewID = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we should be drawing from a camera's POV
2012-11-28 15:47:07 +00:00
if ( ! noclip & & ( gameLocal . GetCamera ( ) | | privateCameraView ) )
{
2012-11-26 18:58:24 +00:00
// get origin, axis, and fov
2012-11-28 15:47:07 +00:00
if ( privateCameraView )
{
2012-11-26 18:58:24 +00:00
privateCameraView - > GetViewParms ( renderView ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameLocal . GetCamera ( ) - > GetViewParms ( renderView ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( g_stopTime . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
renderView - > vieworg = firstPersonViewOrigin ;
renderView - > viewaxis = firstPersonViewAxis ;
2012-11-28 15:47:07 +00:00
if ( ! pm_thirdPerson . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
// set the viewID to the clientNum + 1, so we can suppress the right player bodies and
// allow the right player view weapons
renderView - > viewID = entityNumber + 1 ;
}
2012-11-28 15:47:07 +00:00
}
else if ( pm_thirdPerson . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
OffsetThirdPersonView ( pm_thirdPersonAngle . GetFloat ( ) , pm_thirdPersonRange . GetFloat ( ) , pm_thirdPersonHeight . GetFloat ( ) , pm_thirdPersonClip . GetBool ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else if ( pm_thirdPersonDeath . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
range = gameLocal . time < minRespawnTime ? ( gameLocal . time + RAGDOLL_DEATH_TIME - minRespawnTime ) * ( 120.0f / RAGDOLL_DEATH_TIME ) : 120.0f ;
OffsetThirdPersonView ( 0.0f , 20.0f + range , 0.0f , false ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderView - > vieworg = firstPersonViewOrigin ;
renderView - > viewaxis = firstPersonViewAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the viewID to the clientNum + 1, so we can suppress the right player bodies and
// allow the right player view weapons
renderView - > viewID = entityNumber + 1 ;
}
gameLocal . CalcFov ( CalcFov ( true ) , renderView - > fov_x , renderView - > fov_y ) ;
}
2012-11-28 15:47:07 +00:00
if ( renderView - > fov_y = = 0 )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " renderView->fov_y == 0 " ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_showviewpos . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " %s : %s \n " , renderView - > vieworg . ToString ( ) , renderView - > viewaxis . ToAngles ( ) . ToString ( ) ) ;
}
}
/*
= = = = = = = = = = = = =
idPlayer : : AddAIKill
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : AddAIKill ( )
{
2012-11-26 18:58:24 +00:00
int max_souls ;
int ammo_souls ;
2012-11-28 15:47:07 +00:00
if ( ( weapon_soulcube < 0 ) | | ( inventory . weapons & ( 1 < < weapon_soulcube ) ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ammo_souls = idWeapon : : GetAmmoNumForName ( " ammo_souls " ) ;
max_souls = inventory . MaxAmmoForAmmoClass ( this , " ammo_souls " ) ;
const int currentSoulAmmo = inventory . GetInventoryAmmoForType ( ammo_souls ) ;
2012-11-28 15:47:07 +00:00
if ( currentSoulAmmo < max_souls )
{
2012-11-26 18:58:24 +00:00
inventory . SetInventoryAmmoForType ( ammo_souls , currentSoulAmmo + 1 ) ;
2012-11-28 15:47:07 +00:00
if ( inventory . GetInventoryAmmoForType ( ammo_souls ) > = max_souls )
{
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > UpdateSoulCube ( true ) ;
}
StartSound ( " snd_soulcube_ready " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
}
}
/*
= = = = = = = = = = = = =
idPlayer : : SetSoulCubeProjectile
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetSoulCubeProjectile ( idProjectile * projectile )
{
2012-11-26 18:58:24 +00:00
soulCubeProjectile = projectile ;
}
/*
= = = = = = = = = = = = =
idPlayer : : AddProjectilesFired
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : AddProjectilesFired ( int count )
{
2012-11-26 18:58:24 +00:00
numProjectilesFired + = count ;
}
/*
= = = = = = = = = = = = =
idPlayer : : AddProjectileHites
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : AddProjectileHits ( int count )
{
2012-11-26 18:58:24 +00:00
numProjectileHits + = count ;
}
/*
= = = = = = = = = = = = =
idPlayer : : SetLastHitTime
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetLastHitTime ( int time )
{
idPlayer * aimed = NULL ;
if ( time & & lastHitTime ! = time )
{
2012-11-26 18:58:24 +00:00
lastHitToggle ^ = 1 ;
}
lastHitTime = time ;
2012-11-28 15:47:07 +00:00
if ( ! time )
{
2012-11-26 18:58:24 +00:00
// level start and inits
return ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & ( time - lastSndHitTime ) > 10 )
{
2012-11-26 18:58:24 +00:00
lastSndHitTime = time ;
StartSound ( " snd_hit_feedback " , SND_CHANNEL_ANY , SSF_PRIVATE_SOUND , false , NULL ) ;
}
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
hud - > CombatCursorFlash ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( MPAim ! = - 1 )
{
if ( gameLocal . entities [ MPAim ] & & gameLocal . entities [ MPAim ] - > IsType ( idPlayer : : Type ) )
{
aimed = static_cast < idPlayer * > ( gameLocal . entities [ MPAim ] ) ;
2012-11-26 18:58:24 +00:00
}
assert ( aimed ) ;
// full highlight, no fade till loosing aim
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
int color = 0 ;
2012-11-28 15:47:07 +00:00
if ( aimed )
{
2012-11-26 18:58:24 +00:00
color = aimed - > team + 1 ;
}
hud - > TriggerHitTarget ( true , session - > GetActingGameStateLobbyBase ( ) . GetLobbyUserName ( gameLocal . lobbyUserIDs [ MPAim ] ) , color ) ;
}
MPAimHighlight = true ;
MPAimFadeTime = 0 ;
2012-11-28 15:47:07 +00:00
}
else if ( lastMPAim ! = - 1 )
{
if ( gameLocal . entities [ lastMPAim ] & & gameLocal . entities [ lastMPAim ] - > IsType ( idPlayer : : Type ) )
{
aimed = static_cast < idPlayer * > ( gameLocal . entities [ lastMPAim ] ) ;
2012-11-26 18:58:24 +00:00
}
assert ( aimed ) ;
// start fading right away
2012-11-28 15:47:07 +00:00
if ( hud )
{
2012-11-26 18:58:24 +00:00
int color = 0 ;
2012-11-28 15:47:07 +00:00
if ( aimed )
{
2012-11-26 18:58:24 +00:00
color = aimed - > team + 1 ;
}
hud - > TriggerHitTarget ( true , session - > GetActingGameStateLobbyBase ( ) . GetLobbyUserName ( gameLocal . lobbyUserIDs [ lastMPAim ] ) , color ) ;
hud - > TriggerHitTarget ( false , " " ) ;
}
MPAimHighlight = false ;
MPAimFadeTime = gameLocal . realClientTime ;
}
}
/*
= = = = = = = = = = = = =
idPlayer : : SetInfluenceLevel
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetInfluenceLevel ( int level )
{
if ( level ! = influenceActive )
{
if ( level )
{
for ( idEntity * ent = gameLocal . spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
if ( ent - > IsType ( idProjectile : : Type ) )
{
2012-11-26 18:58:24 +00:00
// remove all projectiles
ent - > PostEventMS ( & EV_Remove , 0 ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( weaponEnabled & & weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > EnterCinematic ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
physicsObj . SetLinearVelocity ( vec3_origin ) ;
2012-11-28 15:47:07 +00:00
if ( weaponEnabled & & weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > ExitCinematic ( ) ;
}
}
influenceActive = level ;
}
}
/*
= = = = = = = = = = = = =
idPlayer : : SetInfluenceView
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetInfluenceView ( const char * mtr , const char * skinname , float radius , idEntity * ent )
{
2012-11-26 18:58:24 +00:00
influenceMaterial = NULL ;
influenceEntity = NULL ;
influenceSkin = NULL ;
2012-11-28 15:47:07 +00:00
if ( mtr & & * mtr )
{
2012-11-26 18:58:24 +00:00
influenceMaterial = declManager - > FindMaterial ( mtr ) ;
}
2012-11-28 15:47:07 +00:00
if ( skinname & & * skinname )
{
2012-11-26 18:58:24 +00:00
influenceSkin = declManager - > FindSkin ( skinname ) ;
2012-11-28 15:47:07 +00:00
if ( head . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
head . GetEntity ( ) - > GetRenderEntity ( ) - > shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
}
UpdateVisuals ( ) ;
}
influenceRadius = radius ;
2012-11-28 15:47:07 +00:00
if ( radius > 0.0f )
{
2012-11-26 18:58:24 +00:00
influenceEntity = ent ;
}
}
/*
= = = = = = = = = = = = =
idPlayer : : SetInfluenceFov
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetInfluenceFov ( float fov )
{
2012-11-26 18:58:24 +00:00
influenceFov = fov ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : OnLadder
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : OnLadder ( ) const
{
2012-11-26 18:58:24 +00:00
return physicsObj . OnLadder ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_GetButtons
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GetButtons ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( usercmd . buttons ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_GetMove
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GetMove ( )
{
2012-11-26 18:58:24 +00:00
int upmove = ( ( usercmd . buttons & BUTTON_JUMP ) ? 127 : 0 ) - ( ( usercmd . buttons & BUTTON_CROUCH ) ? 127 : 0 ) ;
idVec3 move ( usercmd . forwardmove , usercmd . rightmove , upmove ) ;
idThread : : ReturnVector ( move ) ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : Event_GetViewAngles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GetViewAngles ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( idVec3 ( viewAngles [ 0 ] , viewAngles [ 1 ] , viewAngles [ 2 ] ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_StopFxFov
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_StopFxFov ( )
{
2012-11-26 18:58:24 +00:00
fxFov = false ;
}
/*
= = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idPlayer : : StartFxFov
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : StartFxFov ( float duration )
{
2012-11-26 18:58:24 +00:00
fxFov = true ;
PostEventSec ( & EV_Player_StopFxFov , duration ) ;
}
/*
= = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idPlayer : : Event_EnableWeapon
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_EnableWeapon ( )
{
2012-11-26 18:58:24 +00:00
hiddenWeapon = gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) ;
weaponEnabled = true ;
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > ExitCinematic ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_DisableWeapon
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_DisableWeapon ( )
{
2012-11-26 18:58:24 +00:00
hiddenWeapon = gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) ;
weaponEnabled = false ;
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > EnterCinematic ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idPlayer : : Event_GiveInventoryItem
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GiveInventoryItem ( const char * name )
{
GiveInventoryItem ( name ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idPlayer : : Event_RemoveInventoryItem
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_RemoveInventoryItem ( const char * name )
{
RemoveInventoryItem ( name ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idPlayer : : Event_GetIdealWeapon
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GetIdealWeapon ( )
{
const char * weapon ;
if ( idealWeapon . Get ( ) > = 0 )
{
2012-11-26 18:58:24 +00:00
weapon = spawnArgs . GetString ( va ( " def_weapon%d " , idealWeapon . Get ( ) ) ) ;
idThread : : ReturnString ( weapon ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnString ( " " ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idPlayer : : Event_SetPowerupTime
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_SetPowerupTime ( int powerup , int time )
{
if ( time > 0 )
{
2012-11-26 18:58:24 +00:00
GivePowerUp ( powerup , time , ITEM_GIVE_FEEDBACK | ITEM_GIVE_UPDATE_STATE ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
ClearPowerup ( powerup ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idPlayer : : Event_IsPowerupActive
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_IsPowerupActive ( int powerup )
{
idThread : : ReturnInt ( this - > PowerUpActive ( powerup ) ? 1 : 0 ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_StartWarp
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_StartWarp ( )
{
2012-11-26 18:58:24 +00:00
playerView . AddWarp ( idVec3 ( 0 , 0 , 0 ) , SCREEN_WIDTH / 2 , SCREEN_HEIGHT / 2 , 100 , 1000 ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_StopHelltime
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_StopHelltime ( int mode )
{
if ( mode = = 1 )
{
2012-11-26 18:58:24 +00:00
StopHelltime ( true ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
StopHelltime ( false ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_WeaponAvailable
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_WeaponAvailable ( const char * name )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idThread : : ReturnInt ( WeaponAvailable ( name ) ? 1 : 0 ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
bool idPlayer : : WeaponAvailable ( const char * name )
{
for ( int i = 0 ; i < MAX_WEAPONS ; i + + )
{
if ( inventory . weapons & ( 1 < < i ) )
{
const char * weap = spawnArgs . GetString ( va ( " def_weapon%d " , i ) ) ;
if ( ! idStr : : Cmp ( weap , name ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_GetCurrentWeapon
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GetCurrentWeapon ( )
{
const char * weapon ;
if ( currentWeapon > = 0 )
{
2012-11-26 18:58:24 +00:00
weapon = spawnArgs . GetString ( va ( " def_weapon%d " , currentWeapon ) ) ;
idThread : : ReturnString ( weapon ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnString ( " " ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_GetPreviousWeapon
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GetPreviousWeapon ( )
{
const char * weapon ;
if ( previousWeapon > = 0 )
{
2012-11-26 18:58:24 +00:00
int pw = ( gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) ) ? 0 : previousWeapon ;
2012-11-28 15:47:07 +00:00
weapon = spawnArgs . GetString ( va ( " def_weapon%d " , pw ) ) ;
2012-11-26 18:58:24 +00:00
idThread : : ReturnString ( weapon ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnString ( spawnArgs . GetString ( " def_weapon0 " ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_SelectWeapon
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_SelectWeapon ( const char * weaponName )
{
2012-11-26 18:58:24 +00:00
int i ;
int weaponNum ;
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Cannot switch weapons from script in multiplayer " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( hiddenWeapon & & gameLocal . world - > spawnArgs . GetBool ( " no_Weapons " ) )
{
2012-11-26 18:58:24 +00:00
idealWeapon = weapon_fists ;
weapon . GetEntity ( ) - > HideWeapon ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
weaponNum = - 1 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_WEAPONS ; i + + )
{
if ( inventory . weapons & ( 1 < < i ) )
{
const char * weap = spawnArgs . GetString ( va ( " def_weapon%d " , i ) ) ;
if ( ! idStr : : Cmp ( weap , weaponName ) )
{
2012-11-26 18:58:24 +00:00
weaponNum = i ;
break ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( weaponNum < 0 )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " %s is not carrying weapon '%s' " , name . c_str ( ) , weaponName ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hiddenWeapon = false ;
idealWeapon = weaponNum ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateHudWeapon ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_GetWeaponEntity
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_GetWeaponEntity ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnEntity ( weapon . GetEntity ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_OpenPDA
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_OpenPDA ( )
{
if ( ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
TogglePDA ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_InPDA
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_InPDA ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( objectiveSystemOpen ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : TeleportDeath
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : TeleportDeath ( int killer )
{
2012-11-26 18:58:24 +00:00
teleportKiller = killer ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_ExitTeleporter
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_ForceOrigin ( idVec3 & origin , idAngles & angles )
{
2012-11-26 18:58:24 +00:00
SetOrigin ( origin + idVec3 ( 0 , 0 , CM_CLIP_EPSILON ) ) ;
//SetViewAngles( angles );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idPlayer : : Event_ExitTeleporter
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_ExitTeleporter ( )
{
idEntity * exitEnt ;
2012-11-26 18:58:24 +00:00
float pushVel ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// verify and setup
exitEnt = teleportEntity . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! exitEnt )
{
2012-11-26 18:58:24 +00:00
common - > DPrintf ( " Event_ExitTeleporter player %d while not being teleported \n " , entityNumber ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pushVel = exitEnt - > spawnArgs . GetFloat ( " push " , " 300 " ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
ServerSendEvent ( EVENT_EXIT_TELEPORTER , NULL , false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetPrivateCameraView ( NULL ) ;
// setup origin and push according to the exit target
SetOrigin ( exitEnt - > GetPhysics ( ) - > GetOrigin ( ) + idVec3 ( 0 , 0 , CM_CLIP_EPSILON ) ) ;
SetViewAngles ( exitEnt - > GetPhysics ( ) - > GetAxis ( ) . ToAngles ( ) ) ;
physicsObj . SetLinearVelocity ( exitEnt - > GetPhysics ( ) - > GetAxis ( ) [ 0 ] * pushVel ) ;
physicsObj . ClearPushedVelocity ( ) ;
// teleport fx
playerView . Flash ( colorWhite , 120 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the ik heights so model doesn't appear in the wrong place
walkIK . EnableAll ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
StartSound ( " snd_teleport_exit " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( teleportKiller ! = - 1 )
{
2012-11-26 18:58:24 +00:00
// we got killed while being teleported
Damage ( gameLocal . entities [ teleportKiller ] , gameLocal . entities [ teleportKiller ] , vec3_origin , " damage_telefrag " , 1.0f , INVALID_JOINT ) ;
teleportKiller = - 1 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// kill anything that would have waited at teleport exit
gameLocal . KillBox ( this ) ;
}
teleportEntity = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : ClientThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ClientThink ( const int curTime , const float fraction , const bool predict )
{
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
aimAssist . Update ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateSkinSetup ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
// ignore attack button of other clients. that's no good for predictions
usercmd . buttons & = ~ BUTTON_ATTACK ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
buttonMask & = usercmd . buttons ;
usercmd . buttons & = ~ buttonMask ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
buttonMask & = usercmd . buttons ;
usercmd . buttons & = ~ buttonMask ;
2012-11-28 15:47:07 +00:00
if ( mountedObject )
{
2012-11-26 18:58:24 +00:00
usercmd . forwardmove = 0 ;
usercmd . rightmove = 0 ;
2012-11-28 15:47:07 +00:00
usercmd . buttons & = ~ ( BUTTON_JUMP | BUTTON_CROUCH ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( objectiveSystemOpen )
{
2012-11-26 18:58:24 +00:00
usercmd . forwardmove = 0 ;
usercmd . rightmove = 0 ;
2012-11-28 15:47:07 +00:00
usercmd . buttons & = ~ ( BUTTON_JUMP | BUTTON_CROUCH ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
// zooming
2012-11-28 15:47:07 +00:00
if ( ( usercmd . buttons ^ oldCmd . buttons ) & BUTTON_ZOOM )
{
if ( ( usercmd . buttons & BUTTON_ZOOM ) & & weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
zoomFov . Init ( gameLocal . time , 200.0f , CalcFov ( false ) , weapon . GetEntity ( ) - > GetZoomFov ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
zoomFov . Init ( gameLocal . time , 200.0f , zoomFov . GetCurrentValue ( gameLocal . time ) , DefaultFov ( ) ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the ik before we do anything else so the skeleton doesn't get updated twice
walkIK . ClearJointMods ( ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . isNewFrame )
{
if ( usercmd . impulseSequence ! = oldImpulseSequence )
{
2012-11-26 18:58:24 +00:00
PerformImpulse ( usercmd . impulse ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( forceScoreBoard )
{
2012-11-26 18:58:24 +00:00
gameLocal . mpGame . SetScoreboardActive ( true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AdjustSpeed ( ) ;
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
UpdateViewAngles ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idQuat interpolatedAngles = Slerp ( previousViewQuat , nextViewQuat , fraction ) ;
viewAngles = interpolatedAngles . ToAngles ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
smoothedOriginUpdated = false ;
2012-11-28 15:47:07 +00:00
if ( ! af . IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
AdjustBodyAngles ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! isLagged )
{
2012-11-26 18:58:24 +00:00
// don't allow client to move when lagged
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
// Locally-controlled clients are authoritative on their positions, so they can move normally.
2012-11-26 18:58:24 +00:00
Move ( ) ;
usercmd . pos = physicsObj . GetOrigin ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Non-locally controlled players are interpolated.
2012-11-28 15:47:07 +00:00
Move_Interpolated ( fraction ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
if ( ! g_stopTime . GetBool ( ) )
{
if ( ! noclip & & ! spectating & & ( health > 0 ) & & ! IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
TouchTriggers ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update GUIs, Items, and character interactions
UpdateFocus ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// service animations
2012-11-28 15:47:07 +00:00
if ( ! spectating & & ! af . IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
UpdateConditions ( ) ;
UpdateAnimState ( ) ;
CheckBlink ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear out our pain flag so we can tell if we recieve any damage between now and the next time we think
AI_PAIN = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateLocation ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calculate the exact bobbed view position, which is used to
// position the view weapon, among other things
CalculateFirstPersonView ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// this may use firstPersonView, or a thirdPerson / camera view
CalculateRenderView ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . inCinematic & & weapon . GetEntity ( ) & & ( health > 0 ) & & ! ( common - > IsMultiplayer ( ) & & spectating ) )
{
2012-11-26 18:58:24 +00:00
UpdateWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateFlashlight ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateHud ( ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . isNewFrame )
{
2012-11-26 18:58:24 +00:00
UpdatePowerUps ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateDeathSkin ( false ) ;
2012-11-28 15:47:07 +00:00
renderEntity_t * headRenderEnt = NULL ;
if ( head . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
headRenderEnt = head . GetEntity ( ) - > GetRenderEntity ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( headRenderEnt )
{
if ( influenceSkin )
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > customSkin = influenceSkin ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > customSkin = NULL ;
}
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) | | g_showPlayerShadow . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
renderEntity . suppressShadowInViewID = 0 ;
2012-11-28 15:47:07 +00:00
if ( headRenderEnt )
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > suppressShadowInViewID = 0 ;
}
2012-11-28 15:47:07 +00:00
}
else
{
renderEntity . suppressShadowInViewID = entityNumber + 1 ;
if ( headRenderEnt )
{
headRenderEnt - > suppressShadowInViewID = entityNumber + 1 ;
2012-11-26 18:58:24 +00:00
}
}
// never cast shadows from our first-person muzzle flashes
renderEntity . suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber ;
2012-11-28 15:47:07 +00:00
if ( headRenderEnt )
{
2012-11-26 18:58:24 +00:00
headRenderEnt - > suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber ;
}
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . inCinematic )
{
2012-11-26 18:58:24 +00:00
UpdateAnimation ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( enviroSuitLight . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
idAngles lightAng = firstPersonViewAxis . ToAngles ( ) ;
idVec3 lightOrg = firstPersonViewOrigin ;
2012-11-28 15:47:07 +00:00
const idDict * lightDef = gameLocal . FindEntityDefDict ( " envirosuit_light " , false ) ;
2012-11-26 18:58:24 +00:00
idVec3 enviroOffset = lightDef - > GetVector ( " enviro_offset " ) ;
idVec3 enviroAngleOffset = lightDef - > GetVector ( " enviro_angle_offset " ) ;
2012-11-28 15:47:07 +00:00
lightOrg + = ( enviroOffset . x * firstPersonViewAxis [ 0 ] ) ;
lightOrg + = ( enviroOffset . y * firstPersonViewAxis [ 1 ] ) ;
lightOrg + = ( enviroOffset . z * firstPersonViewAxis [ 2 ] ) ;
2012-11-26 18:58:24 +00:00
lightAng . pitch + = enviroAngleOffset . x ;
lightAng . yaw + = enviroAngleOffset . y ;
lightAng . roll + = enviroAngleOffset . z ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetOrigin ( lightOrg ) ;
enviroSuitLight . GetEntity ( ) - > GetPhysics ( ) - > SetAxis ( lightAng . ToMat3 ( ) ) ;
enviroSuitLight . GetEntity ( ) - > UpdateVisuals ( ) ;
enviroSuitLight . GetEntity ( ) - > Present ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
DrawPlayerIcons ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Present ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateDamageEffects ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
LinkCombat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stereo rendering laser sight that replaces the crosshair
UpdateLaserSight ( ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . isNewFrame & & IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
playerView . CalculateShake ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// determine if portal sky is in pvs
pvsHandle_t clientPVS = gameLocal . pvs . SetupCurrentPVS ( GetPVSAreas ( ) , GetNumPVSAreas ( ) ) ;
gameLocal . portalSkyActive = gameLocal . pvs . CheckAreasForPortalSky ( clientPVS , GetPhysics ( ) - > GetOrigin ( ) ) ;
gameLocal . pvs . FreeCurrentPVS ( clientPVS ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//InterpolatePhysics( fraction );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure voice groups are set to the right team
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & session - > GetState ( ) > = idSession : : INGAME & & entityNumber < MAX_CLIENTS ) // The entityNumber < MAX_CLIENTS seems to quiet the static analyzer
{
2012-11-26 18:58:24 +00:00
// Make sure we're on the right team (at the lobby level)
const int voiceTeam = spectating ? LOBBY_SPECTATE_TEAM_FOR_VOICE_CHAT : team ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//idLib::Printf( "CLIENT: Sending voice %i / %i\n", entityNumber, voiceTeam );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Update lobby team
session - > GetActingGameStateLobbyBase ( ) . SetLobbyUserTeam ( gameLocal . lobbyUserIDs [ entityNumber ] , voiceTeam ) ;
// Update voice groups to match in case something changed
session - > SetVoiceGroupsToTeams ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : GetPhysicsToVisualTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : GetPhysicsToVisualTransform ( idVec3 & origin , idMat3 & axis )
{
if ( af . IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
af . GetPhysicsToVisualTransform ( origin , axis ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// smoothen the rendered origin and angles of other clients
// smooth self origin if snapshots are telling us prediction is off
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) & & gameLocal . framenum > = smoothedFrame & & ( ! IsLocallyControlled ( ) | | selfSmooth ) )
{
2012-11-26 18:58:24 +00:00
// render origin and axis
idMat3 renderAxis = viewAxis * GetPhysics ( ) - > GetAxis ( ) ;
idVec3 renderOrigin = GetPhysics ( ) - > GetOrigin ( ) + modelOffset * renderAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update the smoothed origin
2012-11-28 15:47:07 +00:00
if ( ! smoothedOriginUpdated )
{
2012-11-26 18:58:24 +00:00
idVec2 originDiff = renderOrigin . ToVec2 ( ) - smoothedOrigin . ToVec2 ( ) ;
2012-11-28 15:47:07 +00:00
if ( originDiff . LengthSqr ( ) < Square ( 100.0f ) )
{
2012-11-26 18:58:24 +00:00
// smoothen by pushing back to the previous position
2012-11-28 15:47:07 +00:00
if ( selfSmooth )
{
2012-11-26 18:58:24 +00:00
assert ( IsLocallyControlled ( ) ) ;
renderOrigin . ToVec2 ( ) - = net_clientSelfSmoothing . GetFloat ( ) * originDiff ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderOrigin . ToVec2 ( ) - = gameLocal . clientSmoothing * originDiff ;
}
}
smoothedOrigin = renderOrigin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
smoothedFrame = gameLocal . framenum ;
smoothedOriginUpdated = true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis = idAngles ( 0.0f , viewAngles . yaw , 0.0f ) . ToMat3 ( ) ;
origin = ( smoothedOrigin - GetPhysics ( ) - > GetOrigin ( ) ) * axis . Transpose ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
axis = viewAxis ;
origin = modelOffset ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : GetPhysicsToSoundTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : GetPhysicsToSoundTransform ( idVec3 & origin , idMat3 & axis )
{
idCamera * camera ;
if ( privateCameraView )
{
2012-11-26 18:58:24 +00:00
camera = privateCameraView ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
camera = gameLocal . GetCamera ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( camera )
{
2012-11-26 18:58:24 +00:00
renderView_t view ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( & view , 0 , sizeof ( view ) ) ;
camera - > GetViewParms ( & view ) ;
origin = view . vieworg ;
axis = view . viewaxis ;
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return idActor : : GetPhysicsToSoundTransform ( origin , axis ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : HandleUserCmds
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : HandleUserCmds ( const usercmd_t & newcmd )
{
2012-11-26 18:58:24 +00:00
// latch button actions
oldButtons = usercmd . buttons ;
// grab out usercmd
oldCmd = usercmd ;
oldImpulseSequence = usercmd . impulseSequence ;
usercmd = newcmd ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : WriteToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
physicsObj . WriteToSnapshot ( msg ) ;
WriteBindToSnapshot ( msg ) ;
// Only remote players will use these actual viewangles.
idCQuat snapViewCQuat ( viewAngles . ToQuat ( ) . ToCQuat ( ) ) ;
msg . WriteFloat ( snapViewCQuat . x ) ;
msg . WriteFloat ( snapViewCQuat . y ) ;
msg . WriteFloat ( snapViewCQuat . z ) ;
msg . WriteDeltaFloat ( 0.0f , deltaViewAngles [ 0 ] ) ;
msg . WriteDeltaFloat ( 0.0f , deltaViewAngles [ 1 ] ) ;
msg . WriteDeltaFloat ( 0.0f , deltaViewAngles [ 2 ] ) ;
msg . WriteShort ( health ) ;
msg . WriteBits ( gameLocal . ServerRemapDecl ( - 1 , DECL_ENTITYDEF , lastDamageDef ) , gameLocal . entityDefBits ) ;
msg . WriteDir ( lastDamageDir , 9 ) ;
msg . WriteShort ( lastDamageLocation ) ;
msg . WriteBits ( idealWeapon . Get ( ) , idMath : : BitsForInteger ( MAX_WEAPONS ) ) ;
msg . WriteBits ( inventory . weapons , MAX_WEAPONS ) ;
msg . WriteBits ( weapon . GetSpawnId ( ) , 32 ) ;
msg . WriteBits ( flashlight . GetSpawnId ( ) , 32 ) ;
msg . WriteBits ( spectator , idMath : : BitsForInteger ( MAX_CLIENTS ) ) ;
msg . WriteBits ( lastHitToggle , 1 ) ;
msg . WriteBits ( weaponGone , 1 ) ;
msg . WriteBits ( isLagged , 1 ) ;
2012-11-28 15:47:07 +00:00
msg . WriteShort ( team ) ;
2012-11-26 18:58:24 +00:00
WriteToBitMsg ( respawn_netEvent , msg ) ;
2012-11-28 15:47:07 +00:00
/* Needed for the scoreboard */
msg . WriteBits ( carryingFlag , 1 ) ;
2012-11-26 18:58:24 +00:00
msg . WriteBits ( enviroSuitLight . GetSpawnId ( ) , 32 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteBits ( AI_CROUCH , 1 ) ;
msg . WriteBits ( AI_ONGROUND , 1 ) ;
msg . WriteBits ( AI_ONLADDER , 1 ) ;
msg . WriteBits ( AI_JUMP , 1 ) ;
msg . WriteBits ( AI_WEAPON_FIRED , 1 ) ;
msg . WriteBits ( AI_ATTACK_HELD , 1 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteByte ( usercmd . buttons ) ;
msg . WriteBits ( usercmd . forwardmove , - 8 ) ;
msg . WriteBits ( usercmd . rightmove , - 8 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteBool ( spectating ) ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ReadFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
int oldHealth , newIdealWeapon , weaponSpawnId ;
int flashlightSpawnId ;
bool newHitToggle ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
oldHealth = health ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . ReadFromSnapshot ( msg ) ;
ReadBindFromSnapshot ( msg ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// The remote players get updated view angles from the snapshot.
idCQuat snapViewCQuat ;
snapViewCQuat . x = msg . ReadFloat ( ) ;
snapViewCQuat . y = msg . ReadFloat ( ) ;
snapViewCQuat . z = msg . ReadFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idAngles tempDeltaViewAngles ;
tempDeltaViewAngles [ 0 ] = msg . ReadDeltaFloat ( 0.0f ) ;
tempDeltaViewAngles [ 1 ] = msg . ReadDeltaFloat ( 0.0f ) ;
tempDeltaViewAngles [ 2 ] = msg . ReadDeltaFloat ( 0.0f ) ;
2012-11-28 15:47:07 +00:00
deltaViewAngles = tempDeltaViewAngles ;
2012-11-26 18:58:24 +00:00
health = msg . ReadShort ( ) ;
lastDamageDef = gameLocal . ClientRemapDecl ( DECL_ENTITYDEF , msg . ReadBits ( gameLocal . entityDefBits ) ) ;
lastDamageDir = msg . ReadDir ( 9 ) ;
lastDamageLocation = msg . ReadShort ( ) ;
newIdealWeapon = msg . ReadBits ( idMath : : BitsForInteger ( MAX_WEAPONS ) ) ;
inventory . weapons = msg . ReadBits ( MAX_WEAPONS ) ;
weaponSpawnId = msg . ReadBits ( 32 ) ;
flashlightSpawnId = msg . ReadBits ( 32 ) ;
spectator = msg . ReadBits ( idMath : : BitsForInteger ( MAX_CLIENTS ) ) ;
newHitToggle = msg . ReadBits ( 1 ) ! = 0 ;
weaponGone = msg . ReadBits ( 1 ) ! = 0 ;
isLagged = msg . ReadBits ( 1 ) ! = 0 ;
team = msg . ReadShort ( ) ;
ReadFromBitMsg ( respawn_netEvent , msg ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
carryingFlag = msg . ReadBits ( 1 ) ! = 0 ;
int enviroSpawnId ;
enviroSpawnId = msg . ReadBits ( 32 ) ;
enviroSuitLight . SetSpawnId ( enviroSpawnId ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool snapshotCrouch = msg . ReadBool ( ) ;
bool snapshotOnGround = msg . ReadBool ( ) ;
bool snapshotOnLadder = msg . ReadBool ( ) ;
bool snapshotJump = msg . ReadBool ( ) ;
bool snapShotFired = msg . ReadBool ( ) ;
bool snapShotAttackHeld = msg . ReadBool ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
byte snapshotButtons = msg . ReadByte ( ) ;
signed char snapshotForward = msg . ReadBits ( - 8 ) ;
signed char snapshotRight = msg . ReadBits ( - 8 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool snapshotSpectating = msg . ReadBool ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// no msg reading below this
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Update remote remote player state.
2012-11-28 15:47:07 +00:00
if ( ! IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
previousViewQuat = nextViewQuat ;
nextViewQuat = snapViewCQuat . ToQuat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AI_CROUCH = snapshotCrouch ;
AI_ONGROUND = snapshotOnGround ;
AI_ONLADDER = snapshotOnLadder ;
AI_JUMP = snapshotJump ;
AI_WEAPON_FIRED = snapShotFired ;
AI_ATTACK_HELD = snapShotAttackHeld ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
oldCmd = usercmd ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
usercmd . buttons = snapshotButtons ;
usercmd . forwardmove = snapshotForward ;
usercmd . rightmove = snapshotRight ;
}
2012-11-28 15:47:07 +00:00
if ( weapon . SetSpawnId ( weaponSpawnId ) )
{
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
// maintain ownership locally
weapon . GetEntity ( ) - > SetOwner ( this ) ;
}
currentWeapon = - 1 ;
}
2012-11-28 15:47:07 +00:00
if ( flashlight . SetSpawnId ( flashlightSpawnId ) )
{
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > SetFlashlightOwner ( this ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
/*
// if not a local client
if ( ! IsLocallyControlled ( ) ) {
// assume the client has all ammo types
inventory . SetRemoteClientAmmo ( GetEntityNumber ( ) ) ;
}
*/
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Update spectating state
const bool wasSpectating = spectating ;
spectating = snapshotSpectating ;
2012-11-28 15:47:07 +00:00
if ( spectating ! = wasSpectating )
{
2012-11-26 18:58:24 +00:00
Spectate ( spectating , false ) ;
}
2012-11-28 15:47:07 +00:00
if ( oldHealth > 0 & & health < = 0 )
{
if ( snapshotStale )
{
2012-11-26 18:58:24 +00:00
// so we just hide and don't show a death skin
UpdateDeathSkin ( true ) ;
}
// die
AI_DEAD = true ;
ClearPowerUps ( ) ;
SetAnimState ( ANIMCHANNEL_LEGS , " Legs_Death " , 4 ) ;
SetAnimState ( ANIMCHANNEL_TORSO , " Torso_Death " , 4 ) ;
SetWaitState ( " " ) ;
animator . ClearAllJoints ( ) ;
StartRagdoll ( ) ;
physicsObj . SetMovementType ( PM_DEAD ) ;
2012-11-28 15:47:07 +00:00
if ( ! snapshotStale )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_death " , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
}
2012-11-28 15:47:07 +00:00
if ( weapon . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
weapon . GetEntity ( ) - > OwnerDied ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
FlashlightOff ( ) ;
flashlight . GetEntity ( ) - > OwnerDied ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
ControllerShakeFromDamage ( oldHealth - health ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( health < oldHealth & & health > 0 )
{
if ( snapshotStale )
{
2012-11-26 18:58:24 +00:00
lastDmgTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// damage feedback
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * def = static_cast < const idDeclEntityDef * > ( declManager - > DeclByIndex ( DECL_ENTITYDEF , lastDamageDef , false ) ) ;
if ( def )
{
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
playerView . DamageImpulse ( lastDamageDir * viewAxis . Transpose ( ) , & def - > dict ) ;
AI_PAIN = Pain ( NULL , NULL , oldHealth - health , lastDamageDir , lastDamageLocation ) ;
}
lastDmgTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " NET: no damage def for damage feedback '%d' \n " , lastDamageDef ) ;
}
2012-11-28 15:47:07 +00:00
if ( IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
ControllerShakeFromDamage ( oldHealth - health ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
}
else if ( health > oldHealth & & PowerUpActive ( MEGAHEALTH ) & & ! snapshotStale )
{
2012-11-26 18:58:24 +00:00
// just pulse, for any health raise
healthPulse = true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// handle respawns
2012-11-28 15:47:07 +00:00
if ( respawn_netEvent . Get ( ) )
{
2012-11-26 18:58:24 +00:00
Init ( ) ;
StopRagdoll ( ) ;
SetPhysics ( & physicsObj ) ;
// Explicitly set the current origin, since locally-controlled clients
// don't interpolate. Reading the physics object from the snapshot only
// updates the next state, not the current state.
physicsObj . SnapToNextState ( ) ;
physicsObj . EnableClip ( ) ;
SetCombatContents ( true ) ;
2012-11-28 15:47:07 +00:00
if ( flashlight . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
flashlight . GetEntity ( ) - > Show ( ) ;
}
Respawn_Shared ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If the player is alive, restore proper physics object
2012-11-28 15:47:07 +00:00
if ( health > 0 & & IsActiveAF ( ) )
{
2012-11-26 18:58:24 +00:00
StopRagdoll ( ) ;
SetPhysics ( & physicsObj ) ;
physicsObj . EnableClip ( ) ;
SetCombatContents ( true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int oldIdealWeapon = idealWeapon . Get ( ) ;
idealWeapon . UpdateFromSnapshot ( newIdealWeapon , GetEntityNumber ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( oldIdealWeapon ! = idealWeapon . Get ( ) )
{
if ( snapshotStale )
{
2012-11-26 18:58:24 +00:00
weaponCatchup = true ;
}
UpdateHudWeapon ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( lastHitToggle ! = newHitToggle )
{
2012-11-26 18:58:24 +00:00
SetLastHitTime ( gameLocal . realClientTime ) ;
}
2012-11-28 15:47:07 +00:00
if ( msg . HasChanged ( ) )
{
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : WritePlayerStateToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : WritePlayerStateToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
msg . WriteByte ( bobCycle ) ;
msg . WriteLong ( stepUpTime ) ;
msg . WriteFloat ( stepUpDelta ) ;
msg . WriteLong ( inventory . weapons ) ;
msg . WriteByte ( inventory . armor ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . WriteAmmoToSnapshot ( msg ) ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : ReadPlayerStateFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ReadPlayerStateFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
int newBobCycle = 0 ;
int newStepUpTime = 0 ;
int newStepUpDelta = 0 ;
2012-11-28 15:47:07 +00:00
newBobCycle = msg . ReadByte ( ) ;
newStepUpTime = msg . ReadLong ( ) ;
2012-11-26 18:58:24 +00:00
newStepUpDelta = msg . ReadFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . weapons = msg . ReadLong ( ) ;
inventory . armor = msg . ReadByte ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inventory . ReadAmmoFromSnapshot ( msg , GetEntityNumber ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : ServerReceiveEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : ServerReceiveEvent ( int event , int time , const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( idEntity : : ServerReceiveEvent ( event , time , msg ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg )
{
switch ( event )
{
2012-11-26 18:58:24 +00:00
case EVENT_EXIT_TELEPORTER :
Event_ExitTeleporter ( ) ;
return true ;
case EVENT_ABORT_TELEPORTER :
SetPrivateCameraView ( NULL ) ;
return true ;
2012-11-28 15:47:07 +00:00
case EVENT_POWERUP :
{
2012-11-26 18:58:24 +00:00
int powerup = msg . ReadShort ( ) ;
int powertime = msg . ReadShort ( ) ;
2012-11-28 15:47:07 +00:00
if ( powertime > 0 )
{
2012-11-26 18:58:24 +00:00
GivePowerUp ( powerup , powertime , ITEM_GIVE_UPDATE_STATE ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
ClearPowerup ( powerup ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
case EVENT_PICKUPNAME :
{
2012-11-26 18:58:24 +00:00
char buf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
msg . ReadString ( buf , MAX_EVENT_PARAM_SIZE ) ;
inventory . AddPickupName ( buf , this ) ; //_D3XP
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
case EVENT_SPECTATE :
{
2012-11-26 18:58:24 +00:00
bool spectate = ( msg . ReadBits ( 1 ) ! = 0 ) ;
Spectate ( spectate , true ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
case EVENT_ADD_DAMAGE_EFFECT :
{
if ( spectating )
{
2012-11-26 18:58:24 +00:00
// if we're spectating, ignore
// happens if the event and the spectate change are written on the server during the same frame (fraglimit)
return true ;
}
return idActor : : ClientReceiveEvent ( event , time , msg ) ;
}
2012-11-28 15:47:07 +00:00
case EVENT_FORCE_ORIGIN :
{
2012-11-26 18:58:24 +00:00
idVec3 forceOrigin = ReadFloatArray < idVec3 > ( msg ) ;
idAngles forceAngles ;
forceAngles [ 0 ] = msg . ReadFloat ( ) ;
forceAngles [ 1 ] = msg . ReadFloat ( ) ;
forceAngles [ 2 ] = msg . ReadFloat ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Event_ForceOrigin ( forceOrigin , forceAngles ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
case EVENT_KNOCKBACK :
{
2012-11-26 18:58:24 +00:00
idVec3 linearVelocity = ReadFloatArray < idVec3 > ( msg ) ;
int knockbacktime = msg . ReadByte ( ) ;
physicsObj . SetLinearVelocity ( linearVelocity ) ;
physicsObj . SetKnockBack ( knockbacktime ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
return idActor : : ClientReceiveEvent ( event , time , msg ) ;
}
}
// return false;
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : Hide
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Hide ( )
{
idWeapon * weap ;
2012-11-26 18:58:24 +00:00
idActor : : Hide ( ) ;
weap = weapon . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( weap )
{
2012-11-26 18:58:24 +00:00
weap - > HideWorldModel ( ) ;
}
2012-11-28 15:47:07 +00:00
idWeapon * flash = flashlight . GetEntity ( ) ;
if ( flash )
{
2012-11-26 18:58:24 +00:00
flash - > HideWorldModel ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idPlayer : : Show
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Show ( )
{
idWeapon * weap ;
2012-11-26 18:58:24 +00:00
idActor : : Show ( ) ;
weap = weapon . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( weap )
{
2012-11-26 18:58:24 +00:00
weap - > ShowWorldModel ( ) ;
}
2012-11-28 15:47:07 +00:00
idWeapon * flash = flashlight . GetEntity ( ) ;
if ( flash )
{
2012-11-26 18:58:24 +00:00
flash - > ShowWorldModel ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : IsSoundChannelPlaying
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : IsSoundChannelPlaying ( const s_channelType channel )
{
if ( GetSoundEmitter ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
return GetSoundEmitter ( ) - > CurrentlyPlaying ( channel ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : ShowTip
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ShowTip ( const char * title , const char * tip , bool autoHide )
{
if ( tipUp )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( hudManager )
{
hudManager - > ShowTip ( title , tip , autoHide ) ;
2012-11-26 18:58:24 +00:00
}
tipUp = true ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : HideTip
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : HideTip ( )
{
if ( hudManager )
{
hudManager - > HideTip ( ) ;
2012-11-26 18:58:24 +00:00
}
tipUp = false ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Event_HideTip
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_HideTip ( )
{
2012-11-26 18:58:24 +00:00
HideTip ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : HideObjective
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : HideObjective ( )
{
2012-11-26 18:58:24 +00:00
StartSound ( " snd_objectivedown " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( hud )
{
if ( objectiveUp )
{
2012-11-26 18:58:24 +00:00
hud - > HideObjective ( false ) ;
objectiveUp = false ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hud - > HideObjective ( true ) ;
}
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Event_StopAudioLog
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_StopAudioLog ( )
{
2012-11-26 18:58:24 +00:00
//EndAudioLog();
}
/*
= = = = = = = = = = = = = = =
idPlayer : : SetSpectateOrigin
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetSpectateOrigin ( )
{
2012-11-26 18:58:24 +00:00
idVec3 neworig ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
neworig = GetPhysics ( ) - > GetOrigin ( ) ;
neworig [ 2 ] + = pm_normalviewheight . GetFloat ( ) ;
neworig [ 2 ] + = SPECTATE_RAISE ;
SetOrigin ( neworig ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : RemoveWeapon
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RemoveWeapon ( const char * weap )
{
if ( weap & & * weap )
{
2012-11-26 18:58:24 +00:00
inventory . Drop ( spawnArgs , spawnArgs . GetString ( weap ) , - 1 ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : RemoveAllButEssentialWeapons
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : RemoveAllButEssentialWeapons ( )
{
const idKeyValue * kv = spawnArgs . MatchPrefix ( " def_weapon " , NULL ) ;
for ( ; kv ! = NULL ; kv = spawnArgs . MatchPrefix ( " def_weapon " , kv ) )
{
2012-11-26 18:58:24 +00:00
// This list probably ought to be placed int the player's def
2012-11-28 15:47:07 +00:00
if ( kv - > GetValue ( ) = = " weapon_fists " | | kv - > GetValue ( ) = = " weapon_soulcube " | | kv - > GetValue ( ) = = " weapon_pda "
| | kv - > GetValue ( ) = = " weapon_flashlight " | | kv - > GetValue ( ) = = " weapon_flashlight_new " )
{
2012-11-26 18:58:24 +00:00
continue ;
}
inventory . Drop ( spawnArgs , kv - > GetValue ( ) , - 1 ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : CanShowWeaponViewmodel
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : CanShowWeaponViewmodel ( ) const
{
2012-11-26 18:58:24 +00:00
return ui_showGun . GetBool ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : SetLevelTrigger
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetLevelTrigger ( const char * levelName , const char * triggerName )
{
if ( levelName & & * levelName & & triggerName & & * triggerName )
{
2012-11-26 18:58:24 +00:00
idLevelTriggerInfo lti ;
lti . levelName = levelName ;
lti . triggerName = triggerName ;
inventory . levelTriggers . Append ( lti ) ;
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Event_LevelTrigger
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_LevelTrigger ( )
{
2012-11-26 18:58:24 +00:00
idStr mapName = gameLocal . GetMapName ( ) ;
mapName . StripPath ( ) ;
mapName . StripFileExtension ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = inventory . levelTriggers . Num ( ) - 1 ; i > = 0 ; i - - )
{
if ( idStr : : Icmp ( mapName , inventory . levelTriggers [ i ] . levelName ) = = 0 )
{
idEntity * ent = gameLocal . FindEntity ( inventory . levelTriggers [ i ] . triggerName ) ;
if ( ent )
{
2012-11-26 18:58:24 +00:00
ent - > PostEventMS ( & EV_Activate , 1 , this ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = =
idPlayer : : Event_Gibbed
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : Event_Gibbed ( )
{
2012-11-26 18:58:24 +00:00
// do nothing
}
extern idCVar net_clientMaxPrediction ;
/*
= = = = = = = = = = = = = = =
idPlayer : : UpdatePlayerIcons
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : UpdatePlayerIcons ( )
{
idLobbyBase & lobby = session - > GetActingGameStateLobbyBase ( ) ;
2012-11-26 18:58:24 +00:00
int lastPacketTime = lobby . GetPeerTimeSinceLastPacket ( lobby . PeerIndexFromLobbyUser ( gameLocal . lobbyUserIDs [ entityNumber ] ) ) ;
isLagged = ( lastPacketTime > net_clientMaxPrediction . GetInteger ( ) ) ;
//isChatting = ( ( usercmd.buttons & BUTTON_CHATTING ) && ( health > 0 ) );
}
/*
= = = = = = = = = = = = = = =
idPlayer : : DrawPlayerIcons
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : DrawPlayerIcons ( )
{
if ( ! NeedsIcon ( ) )
{
2012-11-26 18:58:24 +00:00
playerIcon . FreeIcon ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
// Never draw icons for hidden players.
if ( this - > IsHidden ( ) )
return ;
2012-11-26 18:58:24 +00:00
playerIcon . Draw ( this , headJoint ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : HidePlayerIcons
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : HidePlayerIcons ( )
{
2012-11-26 18:58:24 +00:00
playerIcon . FreeIcon ( ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : NeedsIcon
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPlayer : : NeedsIcon ( )
{
2012-11-26 18:58:24 +00:00
// local clients don't render their own icons... they're only info for other clients
// always draw icons in CTF games
return ! IsLocallyControlled ( ) & & ( ( g_CTFArrows . GetBool ( ) & & gameLocal . mpGame . IsGametypeFlagBased ( ) & & ! IsHidden ( ) & & ! AI_DEAD ) | | ( isLagged ) ) ;
}
/*
= = = = = = = = = = = = = = =
idPlayer : : DropFlag ( )
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : DropFlag ( )
{
if ( ! carryingFlag | | ! common - > IsMultiplayer ( ) | | ! gameLocal . mpGame . IsGametypeFlagBased ( ) ) /* CTF */
2012-11-26 18:58:24 +00:00
return ;
2012-11-28 15:47:07 +00:00
idEntity * entity = gameLocal . mpGame . GetTeamFlag ( 1 - team ) ;
if ( entity )
{
idItemTeam * item = static_cast < idItemTeam * > ( entity ) ;
if ( item - > carried & & ! item - > dropped )
{
2012-11-26 18:58:24 +00:00
item - > Drop ( health < = 0 ) ;
carryingFlag = false ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
void idPlayer : : ReturnFlag ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! carryingFlag | | ! common - > IsMultiplayer ( ) | | ! gameLocal . mpGame . IsGametypeFlagBased ( ) ) /* CTF */
2012-11-26 18:58:24 +00:00
return ;
2012-11-28 15:47:07 +00:00
idEntity * entity = gameLocal . mpGame . GetTeamFlag ( 1 - team ) ;
if ( entity )
{
idItemTeam * item = static_cast < idItemTeam * > ( entity ) ;
if ( item - > carried & & ! item - > dropped )
{
2012-11-26 18:58:24 +00:00
item - > Return ( ) ;
carryingFlag = false ;
}
}
}
2012-11-28 15:47:07 +00:00
void idPlayer : : FreeModelDef ( )
{
2012-11-26 18:58:24 +00:00
idAFEntity_Base : : FreeModelDef ( ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & gameLocal . mpGame . IsGametypeFlagBased ( ) )
2012-11-26 18:58:24 +00:00
playerIcon . FreeIcon ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idView : : SetControllerShake
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : SetControllerShake ( float highMagnitude , int highDuration , float lowMagnitude , int lowDuration )
{
2012-11-26 18:58:24 +00:00
// the main purpose of having these buffer is so multiple, individual shake events can co-exist with each other,
// for instance, a constant low rumble from the chainsaw when it's idle and a harsh rumble when it's being used.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find active buffer with similar magnitude values
int activeBufferWithSimilarMags = - 1 ;
int inactiveBuffer = - 1 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_SHAKE_BUFFER ; i + + )
{
if ( gameLocal . GetTime ( ) < = controllerShakeHighTime [ i ] | | gameLocal . GetTime ( ) < = controllerShakeLowTime [ i ] )
{
if ( idMath : : Fabs ( highMagnitude - controllerShakeHighMag [ i ] ) < = 0.1f & & idMath : : Fabs ( lowMagnitude - controllerShakeLowMag [ i ] ) < = 0.1f )
{
2012-11-26 18:58:24 +00:00
activeBufferWithSimilarMags = i ;
break ;
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( inactiveBuffer = = - 1 )
{
2012-11-26 18:58:24 +00:00
inactiveBuffer = i ; // first, inactive buffer..
}
}
}
2012-11-28 15:47:07 +00:00
if ( activeBufferWithSimilarMags > - 1 )
{
2012-11-26 18:58:24 +00:00
// average the magnitudes and adjust the time
controllerShakeHighMag [ activeBufferWithSimilarMags ] + = highMagnitude ;
controllerShakeHighMag [ activeBufferWithSimilarMags ] * = 0.5f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
controllerShakeLowMag [ activeBufferWithSimilarMags ] + = lowMagnitude ;
controllerShakeLowMag [ activeBufferWithSimilarMags ] * = 0.5f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
controllerShakeHighTime [ activeBufferWithSimilarMags ] = gameLocal . GetTime ( ) + highDuration ;
controllerShakeLowTime [ activeBufferWithSimilarMags ] = gameLocal . GetTime ( ) + lowDuration ;
controllerShakeTimeGroup = gameLocal . selectedGroup ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( inactiveBuffer = = - 1 )
{
2012-11-26 18:58:24 +00:00
inactiveBuffer = 0 ; // FIXME: probably want to use the oldest buffer..
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
controllerShakeHighMag [ inactiveBuffer ] = highMagnitude ;
controllerShakeLowMag [ inactiveBuffer ] = lowMagnitude ;
controllerShakeHighTime [ inactiveBuffer ] = gameLocal . GetTime ( ) + highDuration ;
controllerShakeLowTime [ inactiveBuffer ] = gameLocal . GetTime ( ) + lowDuration ;
controllerShakeTimeGroup = gameLocal . selectedGroup ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idView : : ResetControllerShake
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : ResetControllerShake ( )
{
for ( int i = 0 ; i < MAX_SHAKE_BUFFER ; i + + )
{
2012-11-26 18:58:24 +00:00
controllerShakeHighTime [ i ] = 0 ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_SHAKE_BUFFER ; i + + )
{
2012-11-26 18:58:24 +00:00
controllerShakeHighMag [ i ] = 0.0f ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_SHAKE_BUFFER ; i + + )
{
2012-11-26 18:58:24 +00:00
controllerShakeLowTime [ i ] = 0 ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_SHAKE_BUFFER ; i + + )
{
2012-11-26 18:58:24 +00:00
controllerShakeLowMag [ i ] = 0.0f ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idPlayer : : GetControllerShake
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPlayer : : GetControllerShake ( int & highMagnitude , int & lowMagnitude ) const
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( gameLocal . inCinematic )
{
2012-11-26 18:58:24 +00:00
// no controller shake during cinematics
highMagnitude = 0 ;
lowMagnitude = 0 ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float lowMag = 0.0f ;
float highMag = 0.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lowMagnitude = 0 ;
highMagnitude = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// use highest values from active buffers
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_SHAKE_BUFFER ; i + + )
{
if ( gameLocal . GetTimeGroupTime ( controllerShakeTimeGroup ) < controllerShakeLowTime [ i ] )
{
if ( controllerShakeLowMag [ i ] > lowMag )
{
2012-11-26 18:58:24 +00:00
lowMag = controllerShakeLowMag [ i ] ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . GetTimeGroupTime ( controllerShakeTimeGroup ) < controllerShakeHighTime [ i ] )
{
if ( controllerShakeHighMag [ i ] > highMag )
{
2012-11-26 18:58:24 +00:00
highMag = controllerShakeHighMag [ i ] ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lowMagnitude = idMath : : Ftoi ( lowMag * 65535.0f ) ;
highMagnitude = idMath : : Ftoi ( highMag * 65535.0f ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idPlayer : : GetExpansionType
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
gameExpansionType_t idPlayer : : GetExpansionType ( ) const
{
const char * expansion = spawnArgs . GetString ( " player_expansion " , " d3 " ) ;
if ( idStr : : Icmp ( expansion , " d3 " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return GAME_BASE ;
}
2012-11-28 15:47:07 +00:00
if ( idStr : : Icmp ( expansion , " d3xp " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return GAME_D3XP ;
}
2012-11-28 15:47:07 +00:00
if ( idStr : : Icmp ( expansion , " d3le " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return GAME_D3LE ;
}
return GAME_UNKNOWN ;
}