2016-03-27 11:49:47 +02:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2024-06-03 20:29:41 +02:00
Copyright ( C ) 2024 the OpenMoHAA team
2016-03-27 11:49:47 +02:00
This file is part of OpenMoHAA source code .
OpenMoHAA 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 2 of the License ,
or ( at your option ) any later version .
OpenMoHAA 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 OpenMoHAA source code ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// player.h: Class definition of the player.
# include "g_local.h"
# include "bg_local.h"
2023-04-29 21:56:38 +02:00
# include "g_spawn.h"
# include "g_phys.h"
2016-03-27 11:49:47 +02:00
# include "entity.h"
2023-08-11 00:48:09 +02:00
# include "consoleevent.h"
2016-03-27 11:49:47 +02:00
# include "player.h"
2023-10-08 00:07:12 +02:00
# include "worldspawn.h"
2016-03-27 11:49:47 +02:00
# include "weapon.h"
# include "trigger.h"
# include "scriptmaster.h"
2023-04-29 21:56:38 +02:00
# include "scriptexception.h"
2016-03-27 11:49:47 +02:00
# include "navigate.h"
# include "misc.h"
# include "earthquake.h"
# include "gravpath.h"
# include "armor.h"
# include "inventoryitem.h"
# include "gibs.h"
# include "actor.h"
# include "object.h"
# include "characterstate.h"
# include "weaputils.h"
# include "dm_manager.h"
2023-04-29 21:56:38 +02:00
# include "parm.h"
2016-03-27 11:49:47 +02:00
# include "body.h"
2023-02-01 19:29:13 +01:00
# include "playerstart.h"
2023-10-13 19:35:29 +02:00
# include "camera.h"
2016-03-27 11:49:47 +02:00
# include "weapturret.h"
# include "vehicleturret.h"
2023-08-10 17:01:55 +02:00
# include "portableturret.h"
2023-08-11 03:13:36 +02:00
# include "fixedturret.h"
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
const Vector power_color ( 0.0 , 1.0 , 0.0 ) ;
const Vector acolor ( 1.0 , 1.0 , 1.0 ) ;
const Vector bcolor ( 1.0 , 0.0 , 0.0 ) ;
2023-11-03 21:56:31 +01:00
//
// mohaas 2.0 and above
//
const char * pInstantMsgEng [ 6 ] [ 9 ] = {
{ " Good job team! " ,
" Alright! " , " We've done it! " ,
" Wooohoo! " , " Objective achieved. " ,
" We've completed an objective. " , " We've lost an objective! " ,
" The enemy has overrun our objective! " , NULL } ,
{ " Squad, move in! " ,
" Squad, fall back! " , " Squad, attack right flank! " ,
" Squad, attack left flank! " , " Squad, hold this position! " ,
" Squad, covering fire! " , " Squad, regroup! " ,
" Squad, split up! " , NULL } ,
{ " Cover me! " ,
" I'll cover you! " , " Follow me! " ,
" You take point. " , " Taking Fire! Need some help! " ,
" Get ready to move in on my signal. " , " Attack! " ,
" Open fire! " , NULL } ,
{ " Yes sir! " ,
" No sir! " , " Enemy Spotted. " ,
" Sniper! " , " Grenade! Take Cover! " ,
" Area Clear. " , " Thanks. " ,
" I owe you one. " , NULL } ,
{ " Who wants more?! " ,
" Never send boys to do a man's job. " , " This is too easy! " ,
" You mess with the best, you die like the rest. " , " Watch that friendly fire! " ,
" Hey! I'm on your team! " , " Come on out you cowards! " ,
" Where are you hiding? " , NULL } ,
2023-11-14 00:49:32 +01:00
// Added in 2.30
2023-11-03 21:56:31 +01:00
{ " Guard our jail! " ,
" Capture the enemy jail! " , " I'm defending our jail! " ,
" I'm attacking the enemy jail! " , " Rescue the Prisoners! " ,
" The enemy is attacking our jail! " }
} ;
//
// for mohaa version 1.11 and below
//
const char * pInstantMsgEng_ver6 [ 5 ] [ 9 ] = {
{ " Squad, move in! " ,
" Squad, fall back! " , " Squad, attack right flank! " ,
" Squad, attack left flank! " , " Squad, hold this position! " ,
" Squad, covering fire! " , " Squad, regroup! " ,
" " , " " } ,
{
" Cover me! " , " I'll cover you! " ,
" Follow me! " , " You take point. " ,
" You take the lead. " , " Taking Fire! Need some help! " ,
" Charge! " , " Attack! " ,
" Open fire! " , } ,
{
" Yes sir! " , " No sir! " ,
" Enemy Spotted. " , " Sniper! " ,
" Grenade! Take Cover! " , " Area Clear. " ,
" Great Shot! " , " Thanks. " ,
" I owe you one. " , } ,
{
" Is that all you've got? " , " I think they are all out of real men! " ,
" Go on and run, you yellow-bellies! " , " They're a bunch of cowards! " ,
" Come back when you've had some target practice! " , " Come prepared next time! " ,
" Try again! " , " I've seen French school girls shoot better! " ,
" That made a mess. " , } ,
{ " He's going to get us killed! " ,
" A lot of good men are going to die because of his poor leadership " , " Good riddance! " ,
" That guy is going to get us all killed! " , " Hey buddy, get down! " ,
" Stay out of my foxhole, pal! " , " Find your own hiding place! " ,
" Get out of my way! " , " " }
} ;
2023-08-13 16:11:25 +02:00
Event EV_Player_DumpState
(
" state " ,
EV_CHEAT ,
NULL ,
NULL ,
" Dumps the player's state to the console. " ,
EV_NORMAL
) ;
Event EV_Player_ForceTorsoState
(
" forcetorsostate " ,
EV_DEFAULT ,
" s " ,
" torsostate " ,
" Force the player's torso to a certain state " ,
EV_NORMAL
) ;
Event EV_Player_ForceLegsState
(
" forcelegsstate " ,
EV_DEFAULT ,
" s " ,
" legsstate " ,
" Force the player's legs to a certain state " ,
EV_NORMAL
) ;
Event EV_Player_GiveAllCheat
(
" wuss " ,
EV_CONSOLE | EV_CHEAT ,
NULL ,
NULL ,
" Gives player all weapons. " ,
EV_NORMAL
) ;
Event EV_Player_GiveNewWeaponsCheat
(
" giveweapon " ,
EV_CONSOLE | EV_CHEAT ,
" s " ,
" weapon_name " ,
" Gives player all weapons. " ,
EV_NORMAL
) ;
Event EV_Player_EndLevel
(
" endlevel " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Called when the player gets to the end of the level. " ,
EV_NORMAL
) ;
Event EV_Player_DevGodCheat
(
" dog " ,
EV_CHEAT | EV_CONSOLE ,
" I " ,
" god_mode " ,
" Sets the god mode cheat or toggles it. " ,
EV_NORMAL
) ;
Event EV_Player_FullHeal
(
" fullheal " ,
EV_CHEAT | EV_CONSOLE ,
NULL ,
NULL ,
" Heals player. " ,
EV_NORMAL
) ;
Event EV_Player_DevNoTargetCheat
(
" notarget " ,
EV_CHEAT ,
NULL ,
NULL ,
" Toggles the notarget cheat. " ,
EV_NORMAL
) ;
Event EV_Player_DevNoClipCheat
(
" noclip " ,
EV_CHEAT | EV_CONSOLE ,
NULL ,
NULL ,
" Toggles the noclip cheat. " ,
EV_NORMAL
) ;
Event EV_Player_PrevItem
(
" invprev " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Cycle to player's previous item. " ,
EV_NORMAL
) ;
Event EV_Player_NextItem
(
" invnext " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Cycle to player's next item. " ,
EV_NORMAL
) ;
Event EV_Player_PrevWeapon
(
" weapprev " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Cycle to player's previous weapon. " ,
EV_NORMAL
) ;
Event EV_Player_NextWeapon
(
" weapnext " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Cycle to player's next weapon. " ,
EV_NORMAL
) ;
Event EV_Player_DropWeapon
(
" weapdrop " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Drops the player's current weapon. " ,
EV_NORMAL
) ;
Event EV_Player_Reload
(
" reload " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Reloads the player's weapon " ,
EV_NORMAL
) ;
Event EV_Player_CorrectWeaponAttachments
(
2023-08-09 23:49:38 +02:00
" correctweaponattachments " ,
EV_CONSOLE ,
NULL ,
NULL ,
2024-09-19 10:52:47 +02:00
" makes sure the weapons is properly attached when interrupting a reload " ,
2023-08-09 23:49:38 +02:00
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GiveCheat
(
2023-08-04 00:04:29 +02:00
" give " ,
EV_CONSOLE | EV_CHEAT ,
" sI " ,
" name amount " ,
" Gives the player the specified thing (weapon, ammo, item, etc.) and optionally the amount. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GiveWeaponCheat
(
" giveweapon " ,
EV_CONSOLE | EV_CHEAT ,
" s " ,
" weapon_name " ,
" Gives the player the specified weapon. " ,
EV_NORMAL
2023-08-09 23:09:14 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GameVersion
(
" gameversion " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Prints the game version. " ,
EV_NORMAL
) ;
Event EV_Player_Fov
(
" fov " ,
EV_CONSOLE ,
" F " ,
" fov " ,
" Sets the fov. " ,
EV_NORMAL
) ;
Event EV_Player_Dead
(
" dead " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Called when the player is dead. " ,
EV_NORMAL
) ;
Event EV_Player_SpawnEntity
(
2023-08-04 00:04:29 +02:00
" spawn " ,
EV_CHEAT ,
" sSSSSSSSS " ,
" entityname keyname1 value1 keyname2 value2 keyname3 value3 keyname4 value4 " ,
" Spawns an entity. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SpawnActor
(
2023-08-04 00:04:29 +02:00
" actor " ,
EV_CHEAT ,
" sSSSSSSSS " ,
" modelname keyname1 value1 keyname2 value2 keyname3 value3 keyname4 value4 " ,
" Spawns an actor. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Respawn
(
" respawn " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Respawns the player. " ,
EV_NORMAL
) ;
Event EV_Player_TestThread
(
" testthread " ,
EV_CHEAT ,
" sS " ,
" scriptfile label " ,
" Starts the named thread at label if provided. " ,
EV_NORMAL
2023-08-09 23:09:14 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_PowerupTimer
(
" poweruptimer " ,
EV_DEFAULT ,
" ii " ,
" poweruptimer poweruptype " ,
" Sets the powerup timer and powerup type. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_UpdatePowerupTimer
(
" updatepoweruptime " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Called once a second to decrement powerup time. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ResetState
(
" resetstate " ,
EV_CHEAT ,
NULL ,
NULL ,
" Reset the player's state table. " ,
EV_NORMAL
) ;
Event EV_Player_WhatIs
(
" whatis " ,
EV_CHEAT ,
" i " ,
" entity_number " ,
" Prints info on the specified entity. " ,
EV_NORMAL
) ;
Event EV_Player_ActorInfo
(
" actorinfo " ,
EV_CHEAT ,
" i " ,
" actor_number " ,
" Prints info on the specified actor. " ,
EV_NORMAL
) ;
Event EV_Player_KillEnt
(
" killent " ,
EV_CHEAT ,
" i " ,
" entity_number " ,
" Kills the specified entity. " ,
EV_NORMAL
) ;
Event EV_Player_KillClass
(
2023-08-04 00:04:29 +02:00
" killclass " ,
EV_CHEAT ,
" sI " ,
" classname except_entity_number " ,
" Kills all of the entities in the specified class. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_RemoveEnt
(
" removeent " ,
EV_CHEAT ,
" i " ,
" entity_number " ,
" Removes the specified entity. " ,
EV_NORMAL
) ;
Event EV_Player_RemoveClass
(
2023-08-04 00:04:29 +02:00
" removeclass " ,
EV_CHEAT ,
" sI " ,
" classname except_entity_number " ,
" Removes all of the entities in the specified class. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Jump
(
" jump " ,
EV_DEFAULT ,
" f " ,
" height " ,
" Makes the player jump. " ,
EV_NORMAL
) ;
Event EV_Player_AnimLoop_Torso
(
" animloop_torso " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Called when the torso animation has finished. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_AnimLoop_Legs
(
" animloop_legs " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Called when the legs animation has finished. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_AnimLoop_Pain // Added in 2.0
2024-01-02 00:43:27 +01:00
(
" animloop_pain " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Called when the pain animation has finished. " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_DoUse
(
" usestuff " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Makes the player try to use whatever is in front of her. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ListInventory
(
" listinventory " ,
EV_CONSOLE ,
NULL ,
NULL ,
" List of the player's inventory. " ,
EV_NORMAL
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ActivateShield
(
" activateshield " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Activates the player's shield " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_DeactivateShield
(
" deactivateshield " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Deactivates the player's shield " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Turn
(
" turn " ,
EV_DEFAULT ,
" f " ,
" yawangle " ,
" Causes player to turn the specified amount. " ,
EV_NORMAL
) ;
Event EV_Player_TurnUpdate
(
" turnupdate " ,
EV_DEFAULT ,
" ff " ,
" yaw timeleft " ,
" Causes player to turn the specified amount. " ,
EV_NORMAL
) ;
Event EV_Player_TurnLegs
(
" turnlegs " ,
EV_DEFAULT ,
" f " ,
" yawangle " ,
" Turns the players legs instantly by the specified amount. " ,
EV_NORMAL
2023-08-09 23:09:14 +02:00
) ;
2023-08-09 23:49:38 +02:00
Event EV_Player_NextPainTime (
2023-08-04 00:04:29 +02:00
" nextpaintime " ,
EV_DEFAULT ,
" f " ,
" seconds " ,
" Set the next time the player experiences pain (Current time + seconds specified). " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-04 00:04:29 +02:00
2023-08-13 16:11:25 +02:00
Event EV_Player_FinishUseAnim
(
" finishuseanim " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Fires off all targets associated with a particular useanim. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Holster
(
2023-08-04 00:04:29 +02:00
" holster " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Holsters all wielded weapons, or unholsters previously put away weapons " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SafeHolster
(
2023-08-04 00:04:29 +02:00
" safeholster " ,
EV_CONSOLE ,
" b " ,
" putaway " ,
" Holsters all wielded weapons, or unholsters previously put away weapons \n "
" preserves state, so it will not holster or unholster unless necessary " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2024-01-02 00:43:27 +01:00
Event EV_Player_SafeZoom
(
2023-08-09 23:49:38 +02:00
" safezoom " ,
EV_DEFAULT ,
" b " ,
" zoomin " ,
" 0 turns off zoom, "
" and 1 returns zoom to previous setting "
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ZoomOff
(
" zoomoff " ,
EV_DEFAULT ,
NULL ,
NULL ,
" makes sure that zoom is off " ,
EV_NORMAL
) ;
Event EV_Player_StartUseObject
(
" startuseobject " ,
EV_DEFAULT ,
NULL ,
NULL ,
" starts up the useobject's animations. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_FinishUseObject
(
2023-08-04 00:04:29 +02:00
" finishuseobject " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Fires off all targets associated with a particular useobject. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_WatchActor
(
" watchactor " ,
EV_DEFAULT ,
" e " ,
" actor_to_watch " ,
" Makes the player's camera watch the specified actor. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_StopWatchingActor
(
2023-08-04 00:04:29 +02:00
" stopwatchingactor " ,
EV_DEFAULT ,
" e " ,
" actor_to_stop_watching " ,
" Makes the player's camera stop watching the specified actor. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetDamageMultiplier
(
" damage_multiplier " ,
EV_DEFAULT ,
" f " ,
" damage_multiplier " ,
" Sets the current damage multiplier " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_WaitForState
(
2023-08-04 00:04:29 +02:00
" waitForState " ,
EV_DEFAULT ,
" s " ,
" stateToWaitFor " ,
" When set, the player will clear waitforplayer when this state is hit \n "
" in the legs or torso. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_LogStats
(
" logstats " ,
EV_CHEAT ,
" b " ,
" state " ,
" Turn on/off the debugging playlog " ,
EV_NORMAL
) ;
Event EV_Player_TakePain
(
" takepain " ,
EV_DEFAULT ,
" b " ,
" bool " ,
" Set whether or not to take pain " ,
EV_NORMAL
) ;
Event EV_Player_SkipCinematic
(
" skipcinematic " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Skip the current cinematic " ,
EV_NORMAL
) ;
Event EV_Player_ResetHaveItem
(
2023-08-04 00:04:29 +02:00
" resethaveitem " ,
EV_CONSOLE ,
" s " ,
" weapon_name " ,
" Resets the game var that keeps track that we have gotten this weapon " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ModifyHeight
(
2023-08-04 00:04:29 +02:00
" modheight " ,
EV_DEFAULT ,
" s " ,
" height " ,
" change the maximum height of the player \n can specify 'stand', 'duck' or 'prone'. " ,
2023-08-09 23:49:38 +02:00
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ModifyHeightFloat // Added in 2.40
2024-01-02 00:43:27 +01:00
(
" modheightfloat " ,
2023-08-13 16:11:25 +02:00
EV_DEFAULT ,
" ff " ,
" height max_z " ,
" Specify the view height of the player and the height of his bounding box. " ,
2024-01-02 00:43:27 +01:00
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetMovePosFlags
(
2023-08-09 23:49:38 +02:00
" moveposflags " ,
EV_DEFAULT ,
" sS " ,
" position movement " ,
" used by the state files to tell the game dll what the player is doing " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetPosition
(
" getposition " ,
2023-08-10 14:18:40 +02:00
EV_DEFAULT ,
NULL ,
NULL ,
2023-08-13 16:11:25 +02:00
" returns the player current position " ,
EV_RETURN
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetMovement
(
" getmovement " ,
2023-08-04 00:04:29 +02:00
EV_DEFAULT ,
NULL ,
NULL ,
2023-08-13 16:11:25 +02:00
" returns the player current movement " ,
EV_RETURN
) ;
Event EV_Player_Score
(
" score " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Show the score for the current deathmatch game " ,
EV_NORMAL
) ;
Event EV_Player_JoinDMTeam
(
" join_team " ,
EV_CONSOLE ,
" s " ,
" team " ,
" Join the specified team (allies or axis) " ,
EV_NORMAL
) ;
Event EV_Player_AutoJoinDMTeam
(
" auto_join_team " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Join the team with fewer players " ,
EV_NORMAL
) ;
Event EV_Player_PickWeapon
(
" pickweapon " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Pick your weapon. " ,
EV_NORMAL
) ;
Event EV_Player_SetInJail // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" injail " ,
EV_DEFAULT ,
" i " ,
" boolean " ,
" set to 1 to indicate when player is in jail, "
" 0 when they are free " ,
EV_SETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetInJail // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" injail " ,
EV_DEFAULT ,
NULL ,
NULL ,
" returns 1 if player is in jail, "
" 0 if out " ,
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetNationalityPrefix // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" nationalityprefix " ,
EV_DEFAULT ,
NULL ,
NULL ,
" get the three or five letter prefix that denotes the player's nationality " ,
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_IsSpectator // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" isSpectator " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Check to see if player is a spectator (non-zero return value) " ,
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Spectator
(
" spectator " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Become a spectator " ,
EV_NORMAL
) ;
Event EV_Player_JoinArena
(
" join_arena " ,
EV_CONSOLE ,
" i " ,
" arena_id_num " ,
" Join the specified arena " ,
EV_NORMAL
) ;
Event EV_Player_LeaveArena
(
" leave_arena " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Leave the current arena " ,
EV_NORMAL
) ;
Event EV_Player_CreateTeam
(
" create_team " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Create a team in the current arena " ,
EV_NORMAL
) ;
Event EV_Player_LeaveTeam
(
" leave_team " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Leave the current team " ,
EV_NORMAL
) ;
Event EV_Player_RefreshArenaUI
(
" arena_ui " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Refresh the arena UI " ,
EV_NORMAL
) ;
Event EV_Player_CallVote
(
" callvote " ,
EV_CONSOLE ,
" ss " ,
" arg1 arg2 " ,
" Player calls a vote " ,
EV_NORMAL
) ;
Event EV_Player_Vote
(
" vote " ,
EV_CONSOLE ,
" s " ,
" arg1 " ,
" Player votes either yes or no " ,
2023-08-09 23:09:14 +02:00
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_RetrieveVoteOptions // Added in 2.0
2024-01-02 00:43:27 +01:00
(
" gvo " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Retrieves the server's vote options file " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_PrimaryDMWeapon
(
" primarydmweapon " ,
EV_CONSOLE ,
" s " ,
" weaptype " ,
" Sets the player's primary DM weapon " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_DeadBody
(
" deadbody " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Spawn a dead body " ,
EV_NORMAL
) ;
Event EV_Player_Physics_On
(
" physics_on " ,
EV_DEFAULT ,
NULL ,
NULL ,
" turn player physics on. " ,
EV_NORMAL
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Physics_Off
(
" physics_off " ,
EV_DEFAULT ,
NULL ,
NULL ,
" turn player physics off. " ,
EV_NORMAL
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ArmWithWeapons // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" armwithweapons " ,
EV_DEFAULT ,
NULL ,
NULL ,
" give player their primary and secondary weapons. " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetCurrentDMWeaponType // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" getcurrentdmweapontype " ,
EV_DEFAULT ,
NULL ,
NULL ,
" get the player's current DM weapon type. " ,
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_AttachToLadder
(
" attachtoladder " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Attaches the sentient to a ladder " ,
EV_NORMAL
) ;
Event EV_Player_UnattachFromLadder
(
" unattachfromladder " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Unattaches the sentient from a ladder " ,
EV_NORMAL
) ;
Event EV_Player_TweakLadderPos
(
" tweakladderpos " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Tweaks the player's position on a ladder to be proper " ,
EV_NORMAL
) ;
Event EV_Player_EnsureOverLadder
(
" ensureoverladder " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Ensures that the player is at the proper height when getting off the top of a ladder " ,
EV_NORMAL
) ;
Event EV_Player_EnsureForwardOffLadder
(
" ensureforwardoffladder " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Ensures that the player went forward off the ladder. " ,
EV_NORMAL
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_JailIsEscaping // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" isEscaping " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Return non-zero if escaping or assisting escape " ,
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_JailEscape // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" jailescape " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Start the escape from jail animation " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_JailAssistEscape // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" jailassistescape " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Start the assist jail escape animation " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_JailEscapeStop // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" jailescapestop " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Stop either the escape from jail or assist animation " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetIsDisguised
(
2023-08-09 23:49:38 +02:00
" is_disguised " ,
EV_DEFAULT ,
2023-08-09 23:09:14 +02:00
NULL ,
NULL ,
2023-08-09 23:49:38 +02:00
" zero = not disguised "
" non-zero = disguised " ,
2023-08-09 23:09:14 +02:00
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetHasDisguise
(
2023-08-09 23:49:38 +02:00
" has_disguise " ,
EV_DEFAULT ,
2023-08-09 23:09:14 +02:00
NULL ,
NULL ,
2023-08-09 23:49:38 +02:00
" zero = does not have a disguise, "
" non - zero = has a disguise " ,
2023-08-09 23:09:14 +02:00
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetHasDisguise
(
2023-08-09 23:49:38 +02:00
" has_disguise " ,
EV_DEFAULT ,
2023-08-09 23:09:14 +02:00
" i " ,
" is_disguised " ,
2023-08-09 23:49:38 +02:00
" zero = does not have a disguise, "
" non - zero = has a disguise " ,
2023-08-09 23:09:14 +02:00
EV_SETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ObjectiveCount
(
2023-08-04 00:04:29 +02:00
" objective " ,
EV_DEFAULT ,
" ii " ,
" num_completed out_of " ,
2023-08-09 23:09:14 +02:00
" Sets the number of objectives completed and the total number of objectives " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Stats
(
" stats " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Display the MissionLog. " ,
EV_NORMAL
) ;
Event EV_Player_Teleport
(
" tele " ,
EV_CHEAT | EV_CONSOLE ,
" v " ,
" location " ,
" Teleport to location " ,
EV_NORMAL
) ;
Event EV_Player_Face
(
" face " ,
EV_CHEAT | EV_CONSOLE ,
" v " ,
" angles " ,
" Force angles to specified vector " ,
EV_NORMAL
) ;
Event EV_Player_Coord
(
" coord " ,
EV_CONSOLE ,
NULL ,
NULL ,
" Prints out current location and angles " ,
EV_NORMAL
) ;
Event EV_Player_TestAnim
(
" testplayeranim " ,
EV_CHEAT ,
" fS " ,
" weight anim " ,
" Plays a test animation on the player " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_StuffText
(
" stufftext " ,
EV_DEFAULT ,
" s " ,
" stuffstrings " ,
" Stuffs text to the player's console " ,
EV_NORMAL
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_DMMessage
(
" dmmessage " ,
EV_CONSOLE ,
" is " ,
" mode stuffstrings " ,
" sends a DM message to the appropriate players " ,
EV_NORMAL
) ;
Event EV_Player_IPrint
(
2023-08-09 23:49:38 +02:00
" iprint " ,
EV_CONSOLE ,
2023-08-09 23:09:14 +02:00
" sI " ,
" string bold " ,
2023-08-09 23:49:38 +02:00
" prints a string to the player, "
" optionally in bold " ,
2023-08-09 23:09:14 +02:00
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_SetViewangles
(
" viewangles " ,
EV_DEFAULT ,
" v " ,
" newAngles " ,
" set the view angles of the entity to newAngles. " ,
EV_SETTER
2023-08-09 23:09:14 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_GetViewangles
(
" viewangles " ,
EV_DEFAULT ,
NULL ,
NULL ,
" get the angles of the entity. " ,
EV_GETTER
) ;
Event EV_GetUseHeld
(
2023-08-09 23:49:38 +02:00
" useheld " ,
EV_DEFAULT ,
2023-08-09 23:09:14 +02:00
NULL ,
NULL ,
2023-08-09 23:49:38 +02:00
" returns 1 if this player is holding use, "
" or 0 if he is not " ,
2023-08-09 23:09:14 +02:00
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_GetFireHeld
(
2023-08-09 23:49:38 +02:00
" fireheld " ,
EV_DEFAULT ,
2023-08-09 23:09:14 +02:00
NULL ,
NULL ,
2023-08-09 23:49:38 +02:00
" returns 1 if this player is holding fire, "
" or 0 if he is not " ,
2023-08-09 23:09:14 +02:00
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_GetPrimaryFireHeld // Added in 2.30
2024-11-08 21:46:25 +01:00
(
" primaryfireheld " ,
2023-08-13 16:11:25 +02:00
EV_DEFAULT ,
NULL ,
NULL ,
" returns 1 if this player is holding the primary fire, or 0 if not " ,
EV_GETTER ) ;
Event EV_GetSecondaryFireHeld // Added in 2.30
2024-11-08 21:46:25 +01:00
(
" secondaryfireheld " ,
2023-08-13 16:11:25 +02:00
EV_DEFAULT ,
NULL ,
NULL ,
" returns 1 if this player is holding the secondary fire, or 0 if not " ,
2024-11-08 21:46:25 +01:00
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetReady
(
" ready " ,
2023-08-10 14:18:40 +02:00
EV_DEFAULT ,
NULL ,
NULL ,
2023-08-13 16:11:25 +02:00
" returns 1 if this player is ready, "
" 0 otherwise " ,
2023-08-10 14:18:40 +02:00
EV_GETTER
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetReady
(
" ready " ,
EV_CONSOLE ,
2023-08-10 14:18:40 +02:00
NULL ,
NULL ,
2023-08-13 16:11:25 +02:00
" makes this player ready for the round to start " ,
EV_NORMAL
) ;
Event EV_Player_SetNotReady
(
" notready " ,
EV_CONSOLE ,
NULL ,
NULL ,
" makes this player not ready for the round to start " ,
EV_NORMAL
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetName
(
" netname " ,
2023-08-09 23:49:38 +02:00
EV_DEFAULT ,
2023-08-09 23:09:14 +02:00
NULL ,
NULL ,
2023-08-13 16:11:25 +02:00
" returns player's name " ,
2023-08-09 23:09:14 +02:00
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetDMTeam
(
2023-08-09 23:49:38 +02:00
" dmteam " ,
EV_DEFAULT ,
NULL ,
NULL ,
" returns 'allies', "
" 'axis', "
" 'spectator', "
" or 'freeforall' " ,
2023-08-09 23:09:14 +02:00
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetViewModelAnim
(
" viewmodelanim " ,
EV_DEFAULT ,
" sI " ,
" name force_restart " ,
" Sets the player's view model animation. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_DMDeathDrop
(
" dmdeathdrop " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Drops the player inventory in DM after's he's been killed " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Stopwatch
(
2023-08-09 23:49:38 +02:00
" stopwatch " ,
2023-08-09 23:09:14 +02:00
EV_DEFAULT ,
2023-08-09 23:49:38 +02:00
" i " ,
" duration " ,
" Starts a stopwatch for a given duration... use 0 to clear the stopwatch " ,
2023-08-09 23:09:14 +02:00
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_EnterIntermission
(
" _enterintermission " ,
EV_CODEONLY ,
NULL ,
NULL ,
" CODE USE ONLY " ,
EV_NORMAL
) ;
Event EV_Player_SetPerferredWeapon
(
2023-08-09 23:49:38 +02:00
" perferredweapon " ,
2023-08-09 23:09:14 +02:00
EV_DEFAULT ,
2023-08-09 23:49:38 +02:00
" s " ,
" weapon_name " ,
2024-09-19 10:52:47 +02:00
" Overrides your preferred weapon that is displayed in the stats screen. " ,
2023-08-09 23:49:38 +02:00
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetVoiceType
(
" voicetype " ,
EV_DEFAULT ,
" s " ,
" voice_name " ,
" Sets the voice type to use the player. " ,
2023-08-10 03:46:28 +02:00
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_AddKills // Added in 2.0
2024-01-02 00:43:27 +01:00
(
" addkills " ,
EV_DEFAULT ,
" i " ,
" kills " ,
" Give or take kills from the player " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_KillAxis // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" killaxis " ,
EV_CHEAT ,
" f " ,
" radius " ,
" Kills all of the axis that are in the passed radius, or all of them if radius is 0. " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetTurret // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" turret " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Returns the turret the player is using. NULL if player isn't using a turret. " ,
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetVehicle // Added in 2.30
2024-01-02 00:43:27 +01:00
(
" vehicle " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Returns the vehicle the player is using. NULL if player isn't using a vehicle. " ,
EV_GETTER
) ;
2023-08-13 16:11:25 +02:00
////////////////////////////
//
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-08-13 16:11:25 +02:00
//
////////////////////////////
Event EV_Player_AddDeaths
(
" adddeaths " ,
2023-08-10 14:18:40 +02:00
EV_DEFAULT ,
2023-08-13 16:11:25 +02:00
" i " ,
" deaths " ,
" adds deaths number to player " ,
EV_NORMAL
2023-08-10 03:46:28 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_AdminRights
(
" adminrights " ,
2023-08-10 14:18:40 +02:00
EV_DEFAULT ,
NULL ,
NULL ,
2023-08-13 16:11:25 +02:00
" returns client admin rights " ,
2023-08-10 14:18:40 +02:00
EV_GETTER
2023-08-10 03:46:28 +02:00
) ;
2024-09-22 19:59:10 +02:00
Event EV_Player_IsAdmin
(
" isadmin " ,
EV_DEFAULT ,
NULL ,
NULL ,
" checks if player is logged as admin " ,
EV_RETURN
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_BindWeap
(
" bindweap " ,
EV_DEFAULT ,
" ei " ,
" weapon handnum " ,
" binds weapon to player and sets him as weapon owner " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Dive
(
" dive " ,
EV_DEFAULT ,
" fF " ,
" height airborne_duration " ,
" Makes the player dive into prone position. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_FreezeControls
(
" freezecontrols " ,
EV_DEFAULT ,
" b " ,
" freeze_state " ,
" Blocks or unblocks control input from this player. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetConnState
(
" getconnstate " ,
EV_DEFAULT ,
NULL ,
NULL ,
" gets connection state. [DEPRECATED] " ,
EV_RETURN
) ;
Event EV_Player_GetDamageMultiplier
(
" damage_multiplier " ,
EV_DEFAULT ,
" Gets the current damage multiplier " ,
NULL ,
NULL ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetKillHandler
(
2023-08-04 00:04:29 +02:00
" killhandler " ,
EV_DEFAULT ,
" s " ,
" label " ,
" Gets the player's current killed event handler. Returns NIL if no custom killhandler was set. " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetKills
(
" getkills " ,
EV_DEFAULT ,
NULL ,
NULL ,
" gets kills number of player " ,
EV_RETURN
) ;
Event EV_Player_GetDeaths
(
" getdeaths " ,
EV_DEFAULT ,
NULL ,
NULL ,
" gets deaths number of player " ,
EV_RETURN
) ;
Event EV_Player_GetLegsState
(
" getlegsstate " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Gets the player's current legs state name " ,
EV_RETURN
2023-08-09 23:09:14 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_GetStateFile
(
" statefile " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Gets the player's current state file. " ,
EV_GETTER
) ;
Event EV_Player_GetTorsoState
(
" gettorsostate " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Gets the player's current torso state name " ,
EV_RETURN
2023-08-09 23:09:14 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Inventory
(
" inventory " ,
EV_DEFAULT ,
NULL ,
NULL ,
" returns player's inventory " ,
EV_GETTER
) ;
Event EV_Player_InventorySet
(
" inventory " ,
EV_DEFAULT ,
" e " ,
" array " ,
" Set up the player's inventory " ,
EV_SETTER
) ;
Event EV_Player_LeanLeftHeld
(
2023-08-04 00:04:29 +02:00
" leanleftheld " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Returns 1 if this player is holding lean left key, or 0 if he is not " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_LeanRightHeld
(
2023-08-04 00:04:29 +02:00
" leanrightheld " ,
EV_DEFAULT ,
NULL ,
NULL ,
" returns EV_RETURN if this player is holding lean right key, or 0 if he is not " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_MoveSpeedScale
(
" moveSpeedScale " ,
EV_DEFAULT ,
" f " ,
" speed " ,
" Sets the player's speed multiplier (default 1.0). " ,
EV_SETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_MoveSpeedScaleGet
(
" moveSpeedScale " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Gets the player's speed multiplier. " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_PlayLocalSound
(
2023-08-04 00:04:29 +02:00
" playlocalsound " ,
EV_DEFAULT ,
" sBF " ,
" soundName loop time " ,
" Plays a local sound to the player. The sound must be aliased globally. Requires sv_reborn to be set for stereo "
" sounds. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_RunHeld
(
2023-08-09 23:49:38 +02:00
" runheld " ,
EV_DEFAULT ,
2023-08-09 23:09:14 +02:00
NULL ,
NULL ,
2023-08-09 23:49:38 +02:00
" returns 1 if this player is holding run key, "
" or 0 if he is not " ,
2023-08-09 23:09:14 +02:00
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SecFireHeld
(
2023-08-04 00:04:29 +02:00
" secfireheld " ,
EV_DEFAULT ,
NULL ,
NULL ,
2024-09-22 19:59:10 +02:00
" returns 1 if this player is holding secondary fire, or 0 if he is not " ,
2023-08-04 00:04:29 +02:00
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetAnimSpeed
(
" setanimspeed " ,
EV_DEFAULT ,
" f " ,
" speed " ,
" set the player's animation speed multiplier (default 1.0). " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetFov
(
" setfov " ,
EV_DEFAULT ,
" f " ,
" fov " ,
" set the player's fov (default 80). " ,
EV_NORMAL
) ;
Event EV_Player_SetKillHandler
(
2023-08-04 00:04:29 +02:00
" killhandler " ,
EV_DEFAULT ,
" s " ,
" label " ,
" Replace the player's killed event by a new scripted handler. None or an empty string will revert to the default "
" killed event handler. " ,
EV_SETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetSpeed
(
2023-08-04 00:04:29 +02:00
" setspeed " ,
EV_DEFAULT ,
" fI " ,
" speed index " ,
" Sets the player's speed multiplier (default 1.0). Index specify which array value will be used (maximum 4). " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetStateFile
(
2023-08-04 00:04:29 +02:00
" statefile " ,
EV_DEFAULT ,
" S " ,
" statefile " ,
" Sets the player's current state file (setting NIL, NULL or an empty string will revert to the global statefile). " ,
EV_SETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_SetTeam
(
2023-08-04 00:04:29 +02:00
" setteam " ,
EV_DEFAULT ,
" s " ,
" team_name " ,
" sets the player's team without respawning. \n "
" Available team names are 'none', 'spectator', 'freeforall', 'axis' and 'allies'. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2024-09-22 19:59:10 +02:00
Event EV_Player_HideEnt
2023-08-13 16:11:25 +02:00
(
2024-09-22 19:59:10 +02:00
" hideent " ,
2023-08-13 16:11:25 +02:00
EV_DEFAULT ,
2024-09-22 19:59:10 +02:00
" e " ,
" entity " ,
" Hides the specified entity to the player. " ,
2023-08-13 16:11:25 +02:00
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ShowEnt
(
" showent " ,
EV_DEFAULT ,
" e " ,
" entity " ,
" Shows the specified entity to the player. " ,
EV_NORMAL
) ;
Event EV_Player_StopLocalSound
(
" stoplocalsound " ,
EV_DEFAULT ,
" sF " ,
" soundName time " ,
" Stops the specified sound. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_Userinfo
(
" userinfo " ,
EV_DEFAULT ,
NULL ,
NULL ,
" returns userinfo string " ,
EV_GETTER
) ;
Event EV_Player_ViewModelGetAnim
(
" viewmodelgetanim " ,
EV_DEFAULT ,
" B " ,
" fullanim " ,
" Gets the player's current view model animation. " ,
EV_RETURN
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ViewModelAnimFinished
(
2023-08-04 00:04:29 +02:00
" viewmodelanimfinished " ,
EV_DEFAULT ,
NULL ,
NULL ,
" True if the player's current view model finished its animation. " ,
EV_RETURN
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_ViewModelAnimValid
(
" viewmodelanimvalid " ,
EV_DEFAULT ,
" sB " ,
" anim fullanim " ,
" True if the view model animation is valid. " ,
EV_RETURN
2016-03-27 11:49:47 +02:00
) ;
2024-09-22 19:59:10 +02:00
# ifdef OPM_FEATURES
Event EV_Player_Earthquake
(
" earthquake2 " ,
EV_DEFAULT ,
" ffbbVF " ,
" duration magnitude no_rampup no_rampdown location radius " ,
" Create a smooth realistic earthquake for a player. Requires sv_reborn to be set. " ,
EV_NORMAL
) ;
Event EV_Player_Replicate
(
" replicate " ,
EV_DEFAULT ,
" s " ,
" variable " ,
" Replicate a variable to the client (needs patch 1.12). " ,
EV_NORMAL
) ;
Event EV_Player_SetClientFlag
(
" setclientflag " ,
EV_DEFAULT ,
" s " ,
" name " ,
" Calls a flag to the script client. " ,
EV_NORMAL
) ;
Event EV_Player_SetEntityShader
(
" setentshader " ,
EV_DEFAULT ,
" es " ,
" entity shadername " ,
" Sets an entity shader for this player. An empty string will revert to the normal entity shader. " ,
EV_NORMAL
) ;
Event EV_Player_SetLocalSoundRate
(
" setlocalsoundrate " ,
EV_DEFAULT ,
" sfF " ,
" name rate time " ,
" Sets the local sound rate. " ,
EV_NORMAL
) ;
Event EV_Player_SetViewModelAnimSpeed
(
" setvmaspeed " ,
EV_DEFAULT ,
" sf " ,
" name speed " ,
" Sets the player's animation speed when playing it. " ,
EV_NORMAL
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_VisionSetBlur
(
2023-08-04 00:04:29 +02:00
" visionsetblur " ,
EV_DEFAULT ,
" fF " ,
" level transition_time " ,
" Sets the player's blur level. Level is a fraction from 0-1 " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_VisionGetNaked
(
" visiongetnaked " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Gets the player's current naked-eye vision. " ,
EV_RETURN
2016-03-27 11:49:47 +02:00
) ;
2023-08-13 16:11:25 +02:00
Event EV_Player_VisionSetNaked
(
2023-08-04 00:04:29 +02:00
" visionsetnaked " ,
EV_DEFAULT ,
" sFF " ,
" vision_name transition_time phase " ,
" Sets the player's naked-eye vision. Optionally give a transition time from the current vision. If vision_name is "
" an empty string, it will revert to the current global vision. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2024-09-22 19:59:10 +02:00
# endif
2016-03-27 11:49:47 +02:00
2024-01-02 18:38:21 +01:00
qboolean TryPush ( int entnum , vec3_t move_origin , vec3_t move_end ) ;
2016-03-27 11:49:47 +02:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PLAYER
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2023-08-04 00:04:29 +02:00
CLASS_DECLARATION ( Sentient , Player , " player " ) {
{ & EV_Vehicle_Enter , & Player : : EnterVehicle } ,
{ & EV_Vehicle_Exit , & Player : : ExitVehicle } ,
{ & EV_Turret_Enter , & Player : : EnterTurret } ,
{ & EV_Turret_Exit , & Player : : ExitTurret } ,
{ & EV_Player_EndLevel , & Player : : EndLevel } ,
{ & EV_Player_PrevItem , & Player : : SelectPreviousItem } ,
{ & EV_Player_NextItem , & Player : : SelectNextItem } ,
{ & EV_Player_PrevWeapon , & Player : : SelectPreviousWeapon } ,
{ & EV_Player_NextWeapon , & Player : : SelectNextWeapon } ,
{ & EV_Player_DropWeapon , & Player : : DropCurrentWeapon } ,
{ & EV_Player_Reload , & Player : : PlayerReload } ,
{ & EV_Player_CorrectWeaponAttachments , & Player : : EventCorrectWeaponAttachments } ,
{ & EV_Player_GiveCheat , & Player : : GiveCheat } ,
{ & EV_Player_GiveWeaponCheat , & Player : : GiveWeaponCheat } ,
{ & EV_Player_GiveAllCheat , & Player : : GiveAllCheat } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_GiveNewWeaponsCheat , & Player : : GiveNewWeaponsCheat } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_DevGodCheat , & Player : : GodCheat } ,
{ & EV_Player_FullHeal , & Player : : FullHeal } ,
{ & EV_Player_DevNoTargetCheat , & Player : : NoTargetCheat } ,
{ & EV_Player_DevNoClipCheat , & Player : : NoclipCheat } ,
{ & EV_Player_GameVersion , & Player : : GameVersion } ,
{ & EV_Player_DumpState , & Player : : DumpState } ,
{ & EV_Player_ForceTorsoState , & Player : : ForceTorsoState } ,
{ & EV_Player_ForceLegsState , & Player : : ForceLegsState } ,
{ & EV_Player_Fov , & Player : : EventSetSelectedFov } ,
{ & EV_Kill , & Player : : Kill } ,
{ & EV_Player_Dead , & Player : : Dead } ,
{ & EV_Player_SpawnEntity , & Player : : SpawnEntity } ,
{ & EV_Player_SpawnActor , & Player : : SpawnActor } ,
{ & EV_Player_Respawn , & Player : : Respawn } ,
{ & EV_Player_DoUse , & Player : : DoUse } ,
{ & EV_Pain , & Player : : Pain } ,
{ & EV_Killed , & Player : : Killed } ,
{ & EV_GotKill , & Player : : GotKill } ,
{ & EV_Player_TestThread , & Player : : TestThread } ,
{ & EV_Player_PowerupTimer , & Player : : SetPowerupTimer } ,
{ & EV_Player_UpdatePowerupTimer , & Player : : UpdatePowerupTimer } ,
{ & EV_Player_ResetState , & Player : : ResetState } ,
{ & EV_Player_WhatIs , & Player : : WhatIs } ,
{ & EV_Player_ActorInfo , & Player : : ActorInfo } ,
{ & EV_Player_KillEnt , & Player : : KillEnt } ,
{ & EV_Player_RemoveEnt , & Player : : RemoveEnt } ,
{ & EV_Player_KillClass , & Player : : KillClass } ,
{ & EV_Player_RemoveClass , & Player : : RemoveClass } ,
{ & EV_Player_AnimLoop_Legs , & Player : : EndAnim_Legs } ,
{ & EV_Player_AnimLoop_Torso , & Player : : EndAnim_Torso } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_AnimLoop_Pain , & Player : : EndAnim_Pain } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_Jump , & Player : : Jump } ,
{ & EV_Sentient_JumpXY , & Player : : JumpXY } ,
{ & EV_Player_ListInventory , & Player : : ListInventoryEvent } ,
{ & EV_Player_NextPainTime , & Player : : NextPainTime } ,
{ & EV_Player_Turn , & Player : : Turn } ,
{ & EV_Player_TurnUpdate , & Player : : TurnUpdate } ,
{ & EV_Player_TurnLegs , & Player : : TurnLegs } ,
{ & EV_Player_FinishUseAnim , & Player : : FinishUseAnim } ,
{ & EV_Player_Holster , & Player : : HolsterToggle } ,
{ & EV_Player_SafeHolster , & Player : : Holster } ,
{ & EV_Player_SafeZoom , & Player : : SafeZoomed } ,
{ & EV_Player_ZoomOff , & Player : : ZoomOffEvent } ,
{ & EV_Player_StartUseObject , & Player : : StartUseObject } ,
{ & EV_Player_FinishUseObject , & Player : : FinishUseObject } ,
{ & EV_Player_WatchActor , & Player : : WatchActor } ,
{ & EV_Player_StopWatchingActor , & Player : : StopWatchingActor } ,
{ & EV_Player_SetDamageMultiplier , & Player : : SetDamageMultiplier } ,
{ & EV_Player_WaitForState , & Player : : WaitForState } ,
{ & EV_Player_LogStats , & Player : : LogStats } ,
{ & EV_Player_TakePain , & Player : : SetTakePain } ,
{ & EV_Player_SkipCinematic , & Player : : SkipCinematic } ,
{ & EV_Player_ResetHaveItem , & Player : : ResetHaveItem } ,
{ & EV_Show , & Player : : PlayerShowModel } ,
{ & EV_Player_ModifyHeight , & Player : : ModifyHeight } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_ModifyHeightFloat , & Player : : ModifyHeightFloat } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_SetMovePosFlags , & Player : : SetMovePosFlags } ,
{ & EV_Player_GetPosition , & Player : : GetPositionForScript } ,
{ & EV_Player_GetMovement , & Player : : GetMovementForScript } ,
{ & EV_Player_Teleport , & Player : : EventTeleport } ,
{ & EV_Player_Face , & Player : : EventFace } ,
{ & EV_Player_Coord , & Player : : EventCoord } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_TestAnim , & Player : : EventTestAnim } ,
{ & EV_Player_JailIsEscaping , & Player : : EventGetIsEscaping } ,
{ & EV_Player_JailEscapeStop , & Player : : EventJailEscapeStop } ,
{ & EV_Player_JailAssistEscape , & Player : : EventJailAssistEscape } ,
{ & EV_Player_JailEscape , & Player : : EventJailEscape } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_Score , & Player : : Score } ,
{ & EV_Player_JoinDMTeam , & Player : : Join_DM_Team } ,
{ & EV_Player_AutoJoinDMTeam , & Player : : Auto_Join_DM_Team } ,
{ & EV_Player_LeaveTeam , & Player : : Leave_DM_Team } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_IsSpectator , & Player : : GetIsSpectator } ,
{ & EV_Player_GetNationalityPrefix , & Player : : GetNationalityPrefix } ,
{ & EV_Player_SetInJail , & Player : : EventSetInJail } ,
{ & EV_Player_GetInJail , & Player : : EventGetInJail } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_Spectator , & Player : : Spectator } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_PickWeapon , & Player : : PickWeaponEvent } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_CallVote , & Player : : CallVote } ,
{ & EV_Player_Vote , & Player : : Vote } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_RetrieveVoteOptions , & Player : : RetrieveVoteOptions } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_PrimaryDMWeapon , & Player : : EventPrimaryDMWeapon } ,
{ & EV_Player_DeadBody , & Player : : DeadBody } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_ArmWithWeapons , & Player : : ArmWithWeapons } ,
{ & EV_Player_GetCurrentDMWeaponType , & Player : : EventGetCurrentDMWeaponType } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_Physics_On , & Player : : PhysicsOn } ,
{ & EV_Player_Physics_Off , & Player : : PhysicsOff } ,
{ & EV_Player_AttachToLadder , & Player : : AttachToLadder } ,
{ & EV_Player_UnattachFromLadder , & Player : : UnattachFromLadder } ,
{ & EV_Player_TweakLadderPos , & Player : : TweakLadderPos } ,
{ & EV_Player_EnsureOverLadder , & Player : : EnsureOverLadder } ,
{ & EV_Player_EnsureForwardOffLadder , & Player : : EnsureForwardOffLadder } ,
{ & EV_Damage , & Player : : ArmorDamage } ,
{ & EV_Player_GetIsDisguised , & Player : : GetIsDisguised } ,
{ & EV_Player_GetHasDisguise , & Player : : GetHasDisguise } ,
{ & EV_Player_SetHasDisguise , & Player : : SetHasDisguise } ,
{ & EV_Player_ObjectiveCount , & Player : : SetObjectiveCount } ,
{ & EV_Player_Stats , & Player : : Stats } ,
{ & EV_Player_StuffText , & Player : : EventStuffText } ,
{ & EV_Player_DMMessage , & Player : : EventDMMessage } ,
{ & EV_Player_IPrint , & Player : : EventIPrint } ,
{ & EV_SetViewangles , & Player : : SetViewangles } ,
{ & EV_GetViewangles , & Player : : GetViewangles } ,
{ & EV_GetUseHeld , & Player : : EventGetUseHeld } ,
{ & EV_GetFireHeld , & Player : : EventGetFireHeld } ,
2023-08-10 03:46:28 +02:00
{ & EV_GetPrimaryFireHeld , & Player : : EventGetPrimaryFireHeld } ,
{ & EV_GetSecondaryFireHeld , & Player : : EventGetSecondaryFireHeld } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_GetReady , & Player : : EventGetReady } ,
{ & EV_Player_SetReady , & Player : : EventSetReady } ,
{ & EV_Player_SetNotReady , & Player : : EventSetNotReady } ,
{ & EV_Player_GetDMTeam , & Player : : EventGetDMTeam } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_GetName , & Player : : EventGetNetName } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_SetViewModelAnim , & Player : : EventSetViewModelAnim } ,
{ & EV_Player_DMDeathDrop , & Player : : EventDMDeathDrop } ,
{ & EV_Player_Stopwatch , & Player : : EventStopwatch } ,
{ & EV_Player_EnterIntermission , & Player : : EventEnterIntermission } ,
{ & EV_Player_SetPerferredWeapon , & Player : : EventSetPerferredWeapon } ,
{ & EV_Player_SetVoiceType , & Player : : EventSetVoiceType } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_AddKills , & Player : : EventAddKills } ,
{ & EV_Player_KillAxis , & Player : : EventKillAxis } ,
{ & EV_Player_GetTurret , & Player : : EventGetTurret } ,
{ & EV_Player_GetVehicle , & Player : : EventGetVehicle } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_AddDeaths , & Player : : AddDeaths } ,
{ & EV_Player_AdminRights , & Player : : AdminRights } ,
{ & EV_Player_BindWeap , & Player : : BindWeap } ,
{ & EV_Player_Dive , & Player : : Dive } ,
{ & EV_Player_DMMessage , & Player : : EventDMMessage } ,
{ & EV_Player_FreezeControls , & Player : : FreezeControls } ,
{ & EV_Player_SetTeam , & Player : : EventSetTeam } ,
{ & EV_Player_GetConnState , & Player : : GetConnState } ,
{ & EV_Player_GetDamageMultiplier , & Player : : GetDamageMultiplier } ,
{ & EV_Player_GetDeaths , & Player : : GetDeaths } ,
{ & EV_Player_GetKillHandler , & Player : : GetKillHandler } ,
{ & EV_Player_GetKills , & Player : : GetKills } ,
{ & EV_Player_GetLegsState , & Player : : GetLegsState } ,
{ & EV_Player_GetStateFile , & Player : : GetStateFile } ,
{ & EV_Player_GetTorsoState , & Player : : GetTorsoState } ,
{ & EV_Player_HideEnt , & Player : : HideEntity } ,
{ & EV_Player_Inventory , & Player : : Inventory } ,
{ & EV_Player_InventorySet , & Player : : InventorySet } ,
2023-08-10 03:46:28 +02:00
{ & EV_Player_IsSpectator , & Player : : GetIsSpectator } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_IsAdmin , & Player : : IsAdmin } ,
{ & EV_Player_LeanLeftHeld , & Player : : LeanLeftHeld } ,
{ & EV_Player_LeanRightHeld , & Player : : LeanRightHeld } ,
{ & EV_Player_MoveSpeedScale , & Player : : SetSpeed } ,
{ & EV_Player_MoveSpeedScaleGet , & Player : : GetMoveSpeedScale } ,
{ & EV_Player_PlayLocalSound , & Player : : PlayLocalSound } ,
{ & EV_Player_RunHeld , & Player : : RunHeld } ,
{ & EV_Player_SecFireHeld , & Player : : SecFireHeld } ,
{ & EV_Player_SetAnimSpeed , & Player : : SetAnimSpeed } ,
{ & EV_Player_SetKillHandler , & Player : : SetKillHandler } ,
{ & EV_Player_SetSpeed , & Player : : SetSpeed } ,
{ & EV_Player_SetStateFile , & Player : : SetStateFile } ,
{ & EV_Player_ShowEnt , & Player : : ShowEntity } ,
{ & EV_Player_Spectator , & Player : : Spectator } ,
{ & EV_Player_StopLocalSound , & Player : : StopLocalSound } ,
{ & EV_Player_Userinfo , & Player : : Userinfo } ,
{ & EV_Player_ViewModelAnimFinished , & Player : : EventGetViewModelAnimFinished } ,
{ & EV_Player_ViewModelGetAnim , & Player : : EventGetViewModelAnim } ,
{ & EV_Player_ViewModelAnimValid , & Player : : EventGetViewModelAnimValid } ,
2024-09-22 19:59:10 +02:00
# ifdef OPM_FEATURES
{ & EV_Player_Earthquake , & Player : : EventEarthquake } ,
{ & EV_Player_SetClientFlag , & Player : : SetClientFlag } ,
{ & EV_Player_SetEntityShader , & Player : : SetEntityShader } ,
{ & EV_Player_SetLocalSoundRate , & Player : : SetLocalSoundRate } ,
{ & EV_Player_SetViewModelAnimSpeed , & Player : : SetVMASpeed } ,
2023-08-04 00:04:29 +02:00
{ & EV_Player_VisionGetNaked , & Player : : VisionGetNaked } ,
{ & EV_Player_VisionSetBlur , & Player : : VisionSetBlur } ,
{ & EV_Player_VisionSetNaked , & Player : : VisionSetNaked } ,
2024-09-22 19:59:10 +02:00
# endif
2023-08-04 00:04:29 +02:00
{ NULL , NULL }
2016-03-27 11:49:47 +02:00
} ;
2023-08-04 00:04:29 +02:00
movecontrolfunc_t Player : : MoveStartFuncs [ ] = {
NULL , // MOVECONTROL_USER, // Quake style
NULL , // MOVECONTROL_LEGS, // Quake style, legs state system active
NULL , // MOVECONTROL_USER_MOVEANIM, // Quake style, legs state system active
NULL , // MOVECONTROL_ANIM, // move based on animation, with full collision testing
NULL , // MOVECONTROL_ABSOLUTE, // move based on animation, with full collision testing but no turning
NULL , // MOVECONTROL_HANGING, // move based on animation, with full collision testing, hanging
NULL , // MOVECONTROL_ROPE_GRAB
NULL , // MOVECONTROL_ROPE_RELEASE
NULL , // MOVECONTROL_ROPE_MOVE
NULL , // MOVECONTROL_PICKUPENEMY
& Player : : StartPush , // MOVECONTROL_PUSH
NULL , // MOVECONTROL_CLIMBWALL
& Player : : StartUseAnim , // MOVECONTROL_USEANIM
NULL , // MOVECONTROL_CROUCH
& Player : : StartLoopUseAnim , // MOVECONTROL_LOOPUSEANIM
& Player : : SetupUseObject , // MOVECONTROL_USEOBJECT
NULL , // MOVECONTROL_COOLOBJECT
} ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Player : : Player ( )
{
//
// set the entity type
//
2023-11-16 23:11:48 +01:00
entflags | = ECF_PLAYER ;
2023-08-04 00:04:29 +02:00
mCurTrailOrigin = 0 ;
2023-08-13 16:11:25 +02:00
mLastTrailTime = 0 ;
2023-08-04 00:04:29 +02:00
m_pLastSpawnpoint = NULL ;
2023-08-13 16:11:25 +02:00
voted = false ;
m_fInvulnerableTimeElapsed = 0 ;
m_voiceType = PVT_NONE_SET ;
m_fTalkTime = 0 ;
num_deaths = 0 ;
num_kills = 0 ;
num_won_matches = 0 ;
num_lost_matches = 0 ;
num_team_kills = 0 ;
m_iLastNumTeamKills = 0 ;
m_bTempSpectator = false ;
m_bSpectator = false ;
m_bSpectatorSwitching = false ;
m_bAllowFighting = false ;
m_bReady = false ;
m_iPlayerSpectating = 0 ;
dm_team = TEAM_NONE ;
m_fTeamSelectTime = - 30 ;
votecount = 0 ;
m_fNextVoteOptionTime = 0 ;
m_fWeapSelectTime = 0 ;
fAttackerDispTime = 0 ;
m_iInfoClient = 0 ;
m_iInfoClientHealth = 0 ;
m_fInfoClientTime = 0 ;
m_bDeathSpectator = false ;
m_fSpawnTimeLeft = 0 ;
m_bWaitingForRespawn = 0 ;
m_bShouldRespawn = false ;
last_camera_type = - 1 ;
m_fLastInvulnerableTime = 0 ;
m_iInvulnerableTimeRemaining = 0 ;
m_fLastVoteTime = 0 ;
2023-11-27 20:07:57 +01:00
//
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-11-27 20:07:57 +01:00
//====
2024-09-22 19:59:10 +02:00
# ifdef OPM_FEATURES
2023-11-27 20:07:57 +01:00
m_bShowingHint = false ;
2024-09-22 19:59:10 +02:00
# endif
2023-11-27 20:07:57 +01:00
m_fpsTiki = NULL ;
m_bConnected = false ;
2024-09-26 19:27:49 +02:00
m_iInstantMessageTime = 0 ;
m_iTextChatTime = 0 ;
2023-11-27 20:07:57 +01:00
//====
2023-08-04 00:04:29 +02:00
if ( LoadingSavegame ) {
return ;
}
2023-08-13 16:11:25 +02:00
actor_camera_right = false ;
starting_actor_camera_right = false ;
useanim_numloops = 1 ;
move_right_vel = 0 ;
m_iInfoClient = - 1 ;
m_iInfoClientHealth = 0 ;
m_fInfoClientTime = 0.0 ;
2023-08-04 00:04:29 +02:00
2023-08-13 16:11:25 +02:00
music_current_volume = - 1 ;
music_saved_volume = - 1 ;
music_volume_fade_time = - 1 ;
feetfalling = false ;
edict - > s . eType = ET_PLAYER ;
2023-08-04 00:04:29 +02:00
buttons = 0 ;
2023-08-13 16:11:25 +02:00
new_buttons = 0 ;
2023-08-04 00:04:29 +02:00
server_new_buttons = 0 ;
2023-08-13 16:11:25 +02:00
respawn_time = - 1.0 ;
//
// State
//
2023-08-04 00:04:29 +02:00
statemap_Legs = NULL ;
statemap_Torso = NULL ;
2023-08-13 16:11:25 +02:00
m_fPartBlends [ 0 ] = 0 ;
m_fPartBlends [ 1 ] = 0 ;
m_iPartSlot [ legs ] = 0 ;
m_iPartSlot [ torso ] = 2 ;
partBlendMult [ 0 ] = 0 ;
partBlendMult [ 1 ] = 0 ;
m_fPainBlend = 0 ;
animdone_Pain = false ;
2023-08-04 00:04:29 +02:00
m_fLastDeltaTime = level . time ;
camera = NULL ;
atobject = NULL ;
atobject_dist = 0 ;
toucheduseanim = NULL ;
useitem_in_use = NULL ;
damage_blood = 0 ;
damage_count = 0 ;
damage_from = vec_zero ;
damage_alpha = 0 ;
damage_yaw = 0 ;
fAttackerDispTime = 0 ;
pAttackerDistPointer = NULL ;
last_attack_button = 0 ;
attack_blocked = false ;
canfall = false ;
move_left_vel = 0 ;
move_right_vel = 0 ;
move_backward_vel = 0 ;
move_forward_vel = 0 ;
move_up_vel = 0 ;
move_down_vel = 0 ;
2023-08-13 16:11:25 +02:00
moveresult = 0 ;
animspeed = 0 ;
airspeed = 200.0f ;
2023-08-04 00:04:29 +02:00
weapons_holstered_by_code = false ;
2023-08-13 16:11:25 +02:00
actor_camera = NULL ;
2023-08-04 00:04:29 +02:00
damage_multiplier = 1.0f ;
take_pain = true ;
2023-08-13 16:11:25 +02:00
m_bIsInJail = false ;
dm_team = TEAM_NONE ;
2023-08-04 00:04:29 +02:00
current_team = NULL ;
2023-08-13 16:11:25 +02:00
m_bTempSpectator = false ;
m_bSpectator = false ;
m_bSpectatorSwitching = false ;
m_bAllowFighting = false ;
m_bReady = true ;
m_fTeamSelectTime = - 30 ;
m_fTalkTime = 0 ;
num_deaths = 0 ;
num_kills = 0 ;
num_team_kills = 0 ;
m_iLastNumTeamKills = 0 ;
num_won_matches = 0 ;
num_lost_matches = 0 ;
client - > ps . voted = false ;
votecount = 0 ;
m_fLastVoteTime = 0 ;
m_fNextVoteOptionTime = 0 ;
m_fWeapSelectTime = 0 ;
m_jailstate = JAILSTATE_NONE ;
2023-08-04 00:04:29 +02:00
SetSelectedFov ( atof ( Info_ValueForKey ( client - > pers . userinfo , " fov " ) ) ) ;
SetFov ( selectedfov ) ;
m_iInZoomMode = 0 ;
m_iNumShotsFired = 0 ;
2023-08-13 16:11:25 +02:00
m_iNumHits = 0 ;
2023-08-04 00:04:29 +02:00
m_iNumGroinShots = 0 ;
m_iNumHeadShots = 0 ;
m_iNumLeftArmShots = 0 ;
m_iNumLeftLegShots = 0 ;
m_iNumRightArmShots = 0 ;
m_iNumRightLegShots = 0 ;
m_iNumTorsoShots = 0 ;
m_sPerferredWeaponOverride = " " ;
SetTargetName ( " player " ) ;
2023-08-13 16:11:25 +02:00
Init ( ) ;
for ( int i = 0 ; i < MAX_TRAILS ; i + + ) {
mvTrail [ i ] = Vector ( 0 , 0 , 0 ) ;
}
for ( int i = 0 ; i < MAX_TRAILS ; i + + ) {
mvTrailEyes [ i ] = Vector ( 0 , 0 , 0 ) ;
}
client - > ps . pm_flags & = ~ PMF_NO_HUD ;
m_fLastSprintTime = 0 ;
m_bHasJumped = false ;
m_fLastInvulnerableTime = 0 ;
m_iInvulnerableTimeRemaining = - 1 ;
m_fSpawnTimeLeft = 0 ;
m_bWaitingForRespawn = false ;
m_bShouldRespawn = false ;
m_bDeathSpectator = false ;
m_vViewPos = vec_zero ;
//
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-11-27 20:07:57 +01:00
//====
2024-01-02 00:43:27 +01:00
m_bFrozen = false ;
animDoneVM = true ;
m_fVMAtime = 0 ;
2023-11-27 20:07:57 +01:00
//====
2023-08-04 00:04:29 +02:00
for ( int i = 0 ; i < MAX_SPEED_MULTIPLIERS ; i + + ) {
speed_multiplier [ i ] = 1.0f ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
Player : : ~ Player ( )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
int i , num ;
Conditional * cond ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
num = legs_conditionals . NumObjects ( ) ;
for ( i = num ; i > 0 ; i - - ) {
cond = legs_conditionals . ObjectAt ( i ) ;
delete cond ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
num = torso_conditionals . NumObjects ( ) ;
for ( i = num ; i > 0 ; i - - ) {
cond = torso_conditionals . ObjectAt ( i ) ;
delete cond ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
legs_conditionals . FreeObjectList ( ) ;
torso_conditionals . FreeObjectList ( ) ;
2023-08-21 23:44:13 +02:00
2024-10-13 23:22:13 +02:00
// Added in 2.11
// Make sure to clean turret stuff up
// when the player is deleted
RemoveFromVehiclesAndTurrets ( ) ;
2023-11-16 23:11:48 +01:00
entflags & = ~ ECF_PLAYER ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
static qboolean logfile_started = qfalse ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : Init ( void )
{
InitClient ( ) ;
InitPhysics ( ) ;
InitPowerups ( ) ;
InitWorldEffects ( ) ;
InitSound ( ) ;
InitView ( ) ;
InitState ( ) ;
InitEdict ( ) ;
2023-08-10 19:36:14 +02:00
InitMaxAmmo ( ) ;
2023-08-04 00:04:29 +02:00
InitWeapons ( ) ;
InitInventory ( ) ;
InitHealth ( ) ;
InitStats ( ) ;
InitModel ( ) ;
2023-08-10 19:14:33 +02:00
InitInvulnerable ( ) ;
2023-08-04 00:04:29 +02:00
LoadStateTable ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 19:14:33 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
InitDeathmatch ( ) ;
} else if ( ! LoadingSavegame ) {
ChooseSpawnPoint ( ) ;
JoinNearbySquads ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 19:36:14 +02:00
// make sure we put the player back into the world
link ( ) ;
logfile_started = qfalse ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// notify scripts for the spawning player
parm . other = this ;
parm . owner = this ;
level . Unregister ( STRING_PLAYERSPAWN ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 19:36:14 +02:00
//
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-08-10 19:36:14 +02:00
//
2023-08-04 00:04:29 +02:00
if ( ! m_bConnected ) {
m_bConnected = true ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Event * ev = new Event ;
ev - > AddEntity ( this ) ;
scriptedEvents [ SE_CONNECTED ] . Trigger ( ev ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Spawned ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InitStats ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:21:19 +02:00
m_iNumObjectives = 0 ;
2023-08-04 00:04:29 +02:00
m_iObjectivesCompleted = 0 ;
2023-08-04 00:21:19 +02:00
m_iNumHitsTaken = 0 ;
m_iNumEnemiesKilled = 0 ;
2023-08-04 00:04:29 +02:00
m_iNumObjectsDestroyed = 0 ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InitEdict ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
// entity state stuff
setSolidType ( SOLID_BBOX ) ;
2023-08-10 20:14:34 +02:00
if ( m_bSpectator ) {
//
// 2.0: always noclip when spectating
//
setMoveType ( MOVETYPE_NOCLIP ) ;
} else {
setMoveType ( MOVETYPE_WALK ) ;
}
2023-08-04 00:04:29 +02:00
setSize ( Vector ( - 16 , - 16 , 0 ) , Vector ( 16 , 16 , 72 ) ) ;
2023-08-10 20:14:34 +02:00
edict - > clipmask = MASK_PLAYERSOLID ;
2023-08-04 00:04:29 +02:00
edict - > r . ownerNum = ENTITYNUM_NONE ;
// clear entity state values
edict - > s . eFlags = 0 ;
edict - > s . wasframe = 0 ;
// players have precise shadows
edict - > s . renderfx | = RF_SHADOW_PRECISE | RF_SHADOW ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InitSound ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
//
// reset the music
//
client - > ps . current_music_mood = mood_normal ;
client - > ps . fallback_music_mood = mood_normal ;
ChangeMusic ( " normal " , " normal " , false ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . music_volume = 1.0 ;
client - > ps . music_volume_fade_time = 0.0 ;
ChangeMusicVolume ( 1.0 , 0.0 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
music_forced = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Reset the reverb stuff
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . reverb_type = eax_generic ;
client - > ps . reverb_level = 0 ;
SetReverb ( client - > ps . reverb_type , client - > ps . reverb_level ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InitClient ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-10 13:34:04 +02:00
client_persistant_t saved ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// deathmatch wipes most client data every spawn
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
char userinfo [ MAX_INFO_STRING ] ;
char dm_primary [ MAX_QPATH ] ;
float enterTime = client - > pers . enterTime ;
2023-08-10 18:49:57 +02:00
teamtype_t team = client - > pers . teamnum ;
2023-08-10 13:34:04 +02:00
int round_kills = client - > pers . round_kills ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
memcpy ( userinfo , client - > pers . userinfo , sizeof ( userinfo ) ) ;
memcpy ( dm_primary , client - > pers . dm_primary , sizeof ( dm_primary ) ) ;
G_InitClientPersistant ( client ) ;
G_ClientUserinfoChanged ( edict , userinfo ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
memcpy ( client - > pers . dm_primary , dm_primary , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 13:34:04 +02:00
client - > pers . enterTime = enterTime ;
2023-08-10 18:49:57 +02:00
client - > pers . teamnum = team ;
2023-08-10 13:34:04 +02:00
client - > pers . round_kills = round_kills ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// clear everything but the persistant data and fov
saved = client - > pers ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
memset ( client , 0 , sizeof ( * client ) ) ;
client - > pers = saved ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . clientNum = client - game . clients ;
client - > lastActiveTime = level . inttime ;
client - > ps . commandTime = level . svsTime ;
2016-03-27 11:49:47 +02:00
2023-08-10 19:36:14 +02:00
SetStopwatch ( 0 ) ;
2023-08-04 00:04:29 +02:00
2024-09-22 19:59:10 +02:00
# ifdef OPM_FEATURES
2023-08-04 00:04:29 +02:00
m_bShowingHint = false ;
2024-09-22 19:59:10 +02:00
# endif
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InitState ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-10 19:36:14 +02:00
gibbed = false ;
pain = 0 ;
nextpaintime = 0 ;
m_fMineDist = 1000 ;
m_fMineCheckTime = 0 ;
m_sDmPrimary = " " ;
knockdown = false ;
pain_dir = PAIN_NONE ;
pain_type = MOD_NONE ;
pain_location = - 2 ;
takedamage = DAMAGE_AIM ;
deadflag = DEAD_NO ;
2023-08-04 00:04:29 +02:00
flags & = ~ FL_TEAMSLAVE ;
flags | = ( FL_POSTTHINK | FL_THINK | FL_DIE_EXPLODE | FL_BLOOD ) ;
2023-08-10 19:36:14 +02:00
m_iMovePosFlags = MPF_POSITION_STANDING ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! com_blood - > integer ) {
flags & = ~ ( FL_DIE_EXPLODE | FL_BLOOD ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InitHealth ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-10 20:14:34 +02:00
static cvar_t * pMaxHealth = gi . Cvar_Get ( " g_maxplayerhealth " , " 250 " , 0 ) ;
static cvar_t * pDMHealth = gi . Cvar_Get ( " g_playerdmhealth " , " 100 " , 0 ) ;
2023-08-04 00:04:29 +02:00
// Don't do anything if we're loading a server game.
// This is either a loadgame or a restart
if ( LoadingSavegame ) {
return ;
}
2024-02-23 23:21:44 +01:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER & & ! g_realismmode - > integer ) {
2023-08-10 20:14:34 +02:00
max_health = pMaxHealth - > integer ;
2024-02-23 23:21:44 +01:00
} else if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & pDMHealth - > integer > 0 ) {
max_health = pDMHealth - > integer ;
2023-08-10 20:14:34 +02:00
} else {
// reset the health values
2024-02-23 23:21:44 +01:00
max_health = 100 ;
2023-08-10 20:14:34 +02:00
}
2024-02-23 23:21:44 +01:00
health = max_health ;
2023-08-10 20:14:34 +02:00
// 2.0:
// Make sure to clear the heal rate and the dead flag when respawning
//
m_fHealRate = 0 ;
edict - > s . eFlags & = ~ EF_DEAD ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InitModel ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-10 20:14:34 +02:00
// 2.0:
// Make sure to detach from any object before initializing
// To prevent any glitches
RemoveFromVehiclesAndTurrets ( ) ;
UnattachFromLadder ( NULL ) ;
2023-08-04 00:04:29 +02:00
gi . clearmodel ( edict ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 20:14:34 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
setModel ( " models/player/ " + str ( g_playermodel - > string ) + " .tik " ) ;
2023-08-10 20:14:34 +02:00
} else if ( dm_team = = TEAM_AXIS ) {
2024-06-09 18:23:06 +02:00
if ( Q_stricmpn ( client - > pers . dm_playergermanmodel , " german " , 6 )
& & Q_stricmpn ( client - > pers . dm_playergermanmodel , " axis " , 4 )
2023-08-10 20:14:34 +02:00
//
// 2.30 models
//
& & Q_stricmpn ( client - > pers . dm_playergermanmodel , " it " , 2 )
& & Q_stricmpn ( client - > pers . dm_playergermanmodel , " sc " , 2 ) ) {
setModel ( " models/player/german_wehrmacht_soldier.tik " ) ;
} else {
setModel ( " models/player/ " + str ( client - > pers . dm_playergermanmodel ) + " .tik " ) ;
}
} else {
2023-08-10 18:43:21 +02:00
if ( Q_stricmpn ( client - > pers . dm_playermodel , " american " , 8 )
& & Q_stricmpn ( client - > pers . dm_playermodel , " allied " , 6 ) ) {
2023-08-04 00:04:29 +02:00
setModel ( " models/player/american_army.tik " ) ;
} else {
2023-08-10 13:34:04 +02:00
setModel ( " models/player/ " + str ( client - > pers . dm_playermodel ) + " .tik " ) ;
2023-08-04 00:04:29 +02:00
}
}
2016-03-27 11:49:47 +02:00
2023-08-10 20:14:34 +02:00
//
// Fallback to a default model if not found
//
2023-08-04 00:04:29 +02:00
if ( ! edict - > tiki ) {
if ( dm_team = = TEAM_AXIS ) {
setModel ( " models/player/german_wehrmacht_soldier.tik " ) ;
} else {
setModel ( " models/player/american_army.tik " ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetControllerTag ( HEAD_TAG , gi . Tag_NumForName ( edict - > tiki , " Bip01 Head " ) ) ;
SetControllerTag ( TORSO_TAG , gi . Tag_NumForName ( edict - > tiki , " Bip01 Spine2 " ) ) ;
SetControllerTag ( ARMS_TAG , gi . Tag_NumForName ( edict - > tiki , " Bip01 Spine1 " ) ) ;
SetControllerTag ( PELVIS_TAG , gi . Tag_NumForName ( edict - > tiki , " Bip01 Pelvis " ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 20:14:34 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & IsSpectator ( ) ) {
hideModel ( ) ;
2023-08-04 00:04:29 +02:00
} else {
showModel ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( GetActiveWeapon ( WEAPON_MAIN ) ) {
2023-08-10 20:14:34 +02:00
// Show the arms
2023-08-04 00:04:29 +02:00
edict - > s . eFlags & = ~ EF_UNARMED ;
} else {
edict - > s . eFlags | = EF_UNARMED ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
edict - > s . eFlags & = ~ EF_ANY_TEAM ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( dm_team = = TEAM_ALLIES ) {
edict - > s . eFlags | = EF_ALLIES ;
} else if ( dm_team = = TEAM_AXIS ) {
edict - > s . eFlags | = EF_AXIS ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 20:14:34 +02:00
G_SetClientConfigString ( edict ) ;
2023-08-04 00:04:29 +02:00
client - > ps . iViewModelAnim = 0 ;
client - > ps . iViewModelAnimChanged = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-10 20:14:34 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
if ( dm_team = = TEAM_AXIS ) {
if ( m_voiceType < = PVT_AXIS_START | | m_voiceType > = PVT_AXIS_END ) {
m_voiceType = PVT_AXIS_GERMAN ;
}
} else {
if ( m_voiceType < = PVT_ALLIED_START | | m_voiceType > = PVT_ALLIED_END ) {
m_voiceType = PVT_ALLIED_AMERICAN ;
}
2023-08-04 00:04:29 +02:00
}
} else {
2023-08-10 20:14:34 +02:00
if ( dm_team = = TEAM_AXIS ) {
if ( m_voiceType > = PVT_AXIS_END ) {
m_voiceType = PVT_AXIS_AXIS4 ;
}
} else {
if ( m_voiceType > = PVT_ALLIED_END ) {
m_voiceType = PVT_ALLIED_PILOT ;
}
2023-08-04 00:04:29 +02:00
}
}
2016-03-27 11:49:47 +02:00
2023-11-26 20:36:23 +01:00
InitModelFps ( ) ;
}
void Player : : InitModelFps ( void )
{
2023-08-04 00:04:29 +02:00
char model_name [ MAX_STRING_TOKENS ] ;
char * model_replace ;
2016-03-27 11:49:47 +02:00
2024-09-20 21:53:48 +02:00
Q_strncpyz ( model_name , model . c_str ( ) , sizeof ( model_name ) ) ;
2023-08-04 00:04:29 +02:00
size_t len = strlen ( model_name ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
model_replace = model_name + len - 4 ;
2016-03-27 11:49:47 +02:00
2024-09-20 21:53:48 +02:00
Q_strncpyz ( model_replace , " _fps.tik " , sizeof ( model_name ) - ( model_replace - model_name ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_fpsTiki = gi . modeltiki ( model_name ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitPhysics ( void )
{
// Physics stuff
oldvelocity = vec_zero ;
velocity = vec_zero ;
old_v_angle = v_angle ;
gravity = 1.0 ;
falling = false ;
mediumimpact = false ;
hardimpact = false ;
setContents ( CONTENTS_BODY ) ;
mass = 500 ;
memset ( & last_ucmd , 0 , sizeof ( last_ucmd ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . groundTrace . fraction = 1.0f ;
2023-11-15 20:41:41 +01:00
// Added in OPM
// Prevent the player from being stuck
flags & = ~ FL_PARTIAL_IMMOBILE ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitPowerups ( void )
{
// powerups
poweruptimer = 0 ;
poweruptype = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitWorldEffects ( void )
{
// world effects
next_painsound_time = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitMaxAmmo ( void )
{
GiveAmmo ( " pistol " , 0 , 200 ) ;
GiveAmmo ( " rifle " , 0 , 200 ) ;
GiveAmmo ( " smg " , 0 , 300 ) ;
GiveAmmo ( " mg " , 0 , 500 ) ;
GiveAmmo ( " grenade " , 0 , 5 ) ;
GiveAmmo ( " agrenade " , 0 , 5 ) ;
GiveAmmo ( " heavy " , 0 , 5 ) ;
GiveAmmo ( " shotgun " , 0 , 50 ) ;
2023-08-10 19:36:14 +02:00
2024-02-03 21:19:04 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTT ) {
//
// Team tactics ammunition
//
GiveAmmo ( " landmine " , 0 , 5 ) ;
}
2023-08-10 19:36:14 +02:00
2024-02-03 21:19:04 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
//
// Team assault ammunition
//
GiveAmmo ( " smokegrenade " , 0 , 5 ) ;
GiveAmmo ( " asmokegrenade " , 0 , 5 ) ;
GiveAmmo ( " riflegrenade " , 0 , 3 ) ;
}
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitWeapons ( void )
{
// Don't do anything if we're loading a server game.
// This is either a loadgame or a restart
if ( LoadingSavegame ) {
return ;
}
2023-11-14 14:06:39 +01:00
// Added in OPM
// This fixes a bug where player can charge then go to spectator or respawn.
// The grenade would immediately explode when firing
charge_start_time = 0 ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitInventory ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitView ( void )
{
// view stuff
camera = NULL ;
v_angle = vec_zero ;
SetViewAngles ( v_angle ) ;
viewheight = DEFAULT_VIEWHEIGHT ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// blend stuff
damage_blend = vec_zero ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : ChooseSpawnPoint ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
// set up the player's spawn location
PlayerStart * p = SelectSpawnPoint ( this ) ;
2023-08-10 19:14:33 +02:00
setOrigin ( p - > origin + Vector ( 0 , 0 , 1 ) ) ;
2023-08-04 00:04:29 +02:00
origin . copyTo ( edict - > s . origin2 ) ;
edict - > s . renderfx | = RF_FRAMELERP ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & ! IsSpectator ( ) ) {
2023-08-04 00:04:29 +02:00
KillBox ( this ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
setAngles ( p - > angles ) ;
SetViewAngles ( p - > angles ) ;
2023-08-10 19:14:33 +02:00
SetupView ( ) ;
VectorCopy ( origin , client - > ps . vEyePos ) ;
client - > ps . vEyePos [ 2 ] + = client - > ps . viewheight ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
for ( int i = 1 ; i < = 4 ; i + + ) {
Event * ev = new Event ( EV_SetViewangles ) ;
ev - > AddVector ( p - > angles ) ;
PostEvent ( ev , level . frametime * i ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( p - > m_bDeleteOnSpawn ) {
delete p ;
} else {
p - > Unregister ( STRING_SPAWN ) ;
m_pLastSpawnpoint = p ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EndLevel ( Event * ev )
{
InitPowerups ( ) ;
if ( health > max_health ) {
health = max_health ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( health < 1 ) {
health = 1 ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Respawn ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-10 20:14:34 +02:00
bool bOldVoted ;
2023-08-04 00:04:29 +02:00
if ( health < = 0.0f ) {
2023-08-09 23:09:14 +02:00
DeadBody ( NULL ) ;
2023-08-04 00:04:29 +02:00
hideModel ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
respawn_time = level . time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// This is not present in MOHAA
ProcessEvent ( EV_Player_UnattachFromLadder ) ;
RemoveFromVehiclesAndTurrets ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
FreeInventory ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 20:14:34 +02:00
// Save the previous vote value
bOldVoted = client - > ps . voted ;
Init ( ) ;
client - > ps . voted = bOldVoted ;
2023-08-04 00:04:29 +02:00
client - > ps . pm_flags | = PMF_RESPAWNED ;
2023-08-10 20:14:34 +02:00
SetInvulnerable ( ) ;
// Clear the center message
gi . centerprintf ( edict , " " ) ;
m_bShouldRespawn = false ;
2023-08-04 00:04:29 +02:00
} else {
if ( g_lastsave - > string & & * g_lastsave - > string ) {
gi . SendConsoleCommand ( " loadlastgame \n " ) ;
} else {
gi . SendConsoleCommand ( " restart \n " ) ;
}
logfile_started = qfalse ;
}
2023-08-10 20:14:34 +02:00
//
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-08-10 20:14:34 +02:00
//
2023-08-04 00:04:29 +02:00
Unregister ( STRING_RESPAWN ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetDeltaAngles ( void )
{
int i ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Use v_angle since we may be in a camera
for ( i = 0 ; i < 3 ; i + + ) {
client - > ps . delta_angles [ i ] = ANGLE2SHORT ( v_angle [ i ] ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : Obituary ( Entity * attacker , Entity * inflictor , int meansofdeath , int iLocation )
{
2023-08-10 21:26:28 +02:00
str s1 ;
str s2 ;
qboolean bDispLocation ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 21:26:28 +02:00
s1 = " x " ;
s2 = " x " ;
2023-08-04 00:04:29 +02:00
bDispLocation = qfalse ;
2016-03-27 11:49:47 +02:00
2023-08-10 21:26:28 +02:00
if ( attacker = = this ) {
2023-08-10 21:38:37 +02:00
//
// Player killed themselves
//
2023-08-10 21:26:28 +02:00
switch ( meansofdeath ) {
case MOD_SUICIDE :
s1 = " took himself out of commision " ;
break ;
case MOD_LAVA :
s1 = " was burned to a crisp " ;
break ;
case MOD_SLIME :
s1 = " was melted to nothing " ;
break ;
case MOD_FALLING :
s1 = " cratered " ;
break ;
case MOD_EXPLOSION :
s1 = " blew himself up " ;
break ;
case MOD_GRENADE :
if ( G_Random ( ) > = 0.5f ) {
s1 = " played catch with himself " ;
} else {
s1 = " tripped on his own grenade " ;
}
break ;
case MOD_ROCKET :
s1 = " rocketed himself " ;
break ;
case MOD_BULLET :
if ( iLocation > - 1 ) {
s1 = " shot himself " ;
} else {
s1 = " shot himself in the " ;
bDispLocation = qtrue ;
}
break ;
case MOD_FAST_BULLET :
2023-08-11 01:58:15 +02:00
if ( iLocation = = HITLOC_GENERAL | | iLocation = = HITLOC_MISS ) {
2023-08-10 21:26:28 +02:00
s1 = " shot himself " ;
} else {
s1 = " shot himself in the " ;
bDispLocation = qtrue ;
}
break ;
2023-08-14 23:37:05 +02:00
case MOD_LANDMINE :
2023-08-10 21:26:28 +02:00
s1 = " was hoist on his own pitard " ;
break ;
default :
s1 = " died " ;
break ;
}
if ( bDispLocation & & g_obituarylocation - > integer ) {
2024-10-02 16:42:10 +02:00
str szConv2 = s2 + " in the " + G_LocationNumToDispString ( iLocation ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 21:26:28 +02:00
if ( dedicated - > integer ) {
2024-10-02 16:42:10 +02:00
gi . Printf ( " %s %s \n " , client - > pers . netname , gi . LV_ConvertString ( szConv2 . c_str ( ) ) ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2024-10-02 16:42:10 +02:00
G_PrintDeathMessage ( s1 , szConv2 . c_str ( ) , " x " , client - > pers . netname , this , " s " ) ;
2023-08-10 21:26:28 +02:00
} else {
if ( dedicated - > integer ) {
gi . Printf ( " %s %s \n " , client - > pers . netname , gi . LV_ConvertString ( s1 . c_str ( ) ) ) ;
}
G_PrintDeathMessage ( s1 . c_str ( ) , s2 . c_str ( ) , " x " , client - > pers . netname , this , " s " ) ;
}
} else if ( attacker & & attacker - > client ) {
2023-08-10 21:38:37 +02:00
//
// Killed by another player
//
2023-08-10 21:26:28 +02:00
Weapon * pAttackerWeap = NULL ;
if ( attacker - > IsSubclassOfPlayer ( ) ) {
pAttackerWeap = ( ( Player * ) attacker ) - > GetActiveWeapon ( WEAPON_MAIN ) ;
}
switch ( meansofdeath ) {
case MOD_CRUSH :
case MOD_CRUSH_EVERY_FRAME :
s1 = " was crushed by " ;
break ;
case MOD_TELEFRAG :
s1 = " was telefragged by " ;
break ;
case MOD_LAVA :
case MOD_FIRE :
case MOD_ON_FIRE :
s1 = " was burned up by " ;
break ;
case MOD_SLIME :
s1 = " was melted by " ;
break ;
case MOD_FALLING :
s1 = " was pushed over the edge by " ;
break ;
case MOD_EXPLOSION :
s1 = " was blown away by " ;
break ;
case MOD_GRENADE :
if ( G_Random ( ) > = 0.5f ) {
s1 = " tripped on " ;
2023-08-18 14:14:11 +02:00
s2 = " 's grenade " ;
2023-08-10 21:26:28 +02:00
} else {
s1 = " is picking " ;
2023-08-18 14:14:11 +02:00
s2 = " 's shrapnel out of his teeth " ;
2023-08-10 21:26:28 +02:00
}
break ;
case MOD_ROCKET :
s1 = " took " ;
if ( G_Random ( ) > = 0.5f ) {
s2 = " 's rocket right in the kisser " ;
} else {
s2 = " 's rocket in the face " ;
}
break ;
case MOD_IMPACT :
s1 = " was knocked out by " ;
break ;
case MOD_BULLET :
case MOD_FAST_BULLET :
s1 = " was shot by " ;
if ( pAttackerWeap ) {
if ( pAttackerWeap - > GetWeaponClass ( ) & WEAPON_CLASS_PISTOL ) {
s1 = " was gunned down by " ;
} else if ( pAttackerWeap - > GetWeaponClass ( ) & WEAPON_CLASS_RIFLE ) {
2023-08-11 23:54:43 +02:00
if ( pAttackerWeap - > GetZoom ( ) ) {
2023-08-10 21:26:28 +02:00
s1 = " was sniped by " ;
} else {
s1 = " was rifled by " ;
2023-08-04 00:04:29 +02:00
}
2023-08-10 21:26:28 +02:00
} else if ( pAttackerWeap - > GetWeaponClass ( ) & WEAPON_CLASS_SMG ) {
s1 = " was perforated by " ;
s2 = " 's' SMG " ;
} else if ( pAttackerWeap - > GetWeaponClass ( ) & WEAPON_CLASS_MG ) {
s1 = " was machine-gunned by " ;
2023-08-04 00:04:29 +02:00
}
2023-08-10 21:26:28 +02:00
}
2023-08-04 00:04:29 +02:00
2023-08-10 21:26:28 +02:00
if ( iLocation > - 1 ) {
bDispLocation = qtrue ;
}
break ;
case MOD_VEHICLE :
s1 = " was run over by " ;
break ;
case MOD_IMPALE :
s1 = " was impaled by " ;
break ;
case MOD_BASH :
if ( G_Random ( ) > = 0.5f ) {
s1 = " was bashed by " ;
} else {
s1 = " was clubbed by " ;
}
break ;
case MOD_SHOTGUN :
if ( G_Random ( ) > = 0.5f ) {
s1 = " was hunted down by " ;
} else {
s1 = " was pumped full of buckshot by " ;
2023-08-04 00:04:29 +02:00
}
2023-08-10 21:26:28 +02:00
break ;
2023-08-14 23:37:05 +02:00
case MOD_LANDMINE :
2023-08-10 21:26:28 +02:00
s1 = " stepped on " ;
s2 = " 's landmine " ;
break ;
default :
s1 = " was killed by " ;
break ;
}
2023-08-04 00:04:29 +02:00
2023-08-10 21:26:28 +02:00
if ( bDispLocation & & g_obituarylocation - > integer ) {
2024-10-02 16:42:10 +02:00
str szConv2 = s2 + " in the " + G_LocationNumToDispString ( iLocation ) ;
2023-08-04 00:04:29 +02:00
2023-08-10 21:26:28 +02:00
G_PrintDeathMessage (
2024-10-02 16:42:10 +02:00
s1 . c_str ( ) , szConv2 . c_str ( ) , attacker - > client - > pers . netname , client - > pers . netname , this , " p "
2023-08-10 21:26:28 +02:00
) ;
2023-08-04 00:04:29 +02:00
2023-08-10 21:26:28 +02:00
if ( dedicated - > integer ) {
str szLoc1 , szLoc2 ;
2023-08-04 00:04:29 +02:00
2024-10-02 16:42:10 +02:00
szLoc1 = gi . LV_ConvertString ( s1 . c_str ( ) ) ;
2023-08-10 21:26:28 +02:00
if ( s2 = = ' x ' ) {
gi . Printf ( " %s %s %s \n " , client - > pers . netname , szLoc1 . c_str ( ) , attacker - > client - > pers . netname ) ;
2023-08-04 00:04:29 +02:00
} else {
2024-10-02 16:42:10 +02:00
szLoc2 = gi . LV_ConvertString ( szConv2 . c_str ( ) ) ;
2023-08-10 21:26:28 +02:00
gi . Printf (
" %s %s %s%s \n " ,
client - > pers . netname ,
szLoc1 . c_str ( ) ,
attacker - > client - > pers . netname ,
szLoc2 . c_str ( )
2023-08-04 00:04:29 +02:00
) ;
}
}
} else {
2023-08-10 21:26:28 +02:00
G_PrintDeathMessage (
s1 . c_str ( ) , s2 . c_str ( ) , attacker - > client - > pers . netname , client - > pers . netname , this , " p "
) ;
2016-03-27 11:49:47 +02:00
2023-08-10 21:26:28 +02:00
if ( dedicated - > integer ) {
str szLoc1 , szLoc2 ;
2016-03-27 11:49:47 +02:00
2023-08-10 21:26:28 +02:00
szLoc1 = gi . LV_ConvertString ( s1 . c_str ( ) ) ;
if ( s2 = = ' x ' ) {
gi . Printf ( " %s %s %s \n " , client - > pers . netname , szLoc1 . c_str ( ) , attacker - > client - > pers . netname ) ;
} else {
szLoc2 = gi . LV_ConvertString ( s2 . c_str ( ) ) ;
gi . Printf (
" %s %s %s%s \n " ,
client - > pers . netname ,
szLoc1 . c_str ( ) ,
attacker - > client - > pers . netname ,
szLoc2 . c_str ( )
) ;
2023-08-04 00:04:29 +02:00
}
}
}
} else {
2023-08-10 21:38:37 +02:00
//
// No attacker and not self
//
2023-08-04 00:04:29 +02:00
switch ( meansofdeath ) {
case MOD_LAVA :
s1 = " was burned to a crisp " ;
break ;
2023-08-10 21:26:28 +02:00
case MOD_SLIME :
s1 = " was melted to nothing " ;
break ;
2023-08-04 00:04:29 +02:00
case MOD_FALLING :
s1 = " cratered " ;
break ;
case MOD_EXPLOSION :
2023-08-10 21:26:28 +02:00
s1 = " blew up " ;
2023-08-04 00:04:29 +02:00
break ;
case MOD_GRENADE :
2023-08-10 21:26:28 +02:00
s1 = " caught some shrapnel " ;
2023-08-04 00:04:29 +02:00
break ;
case MOD_ROCKET :
2023-08-10 21:26:28 +02:00
s1 = " caught a rocket " ;
2023-08-04 00:04:29 +02:00
break ;
case MOD_BULLET :
case MOD_FAST_BULLET :
2023-08-11 01:58:15 +02:00
if ( iLocation = = HITLOC_GENERAL | | iLocation = = HITLOC_MISS ) {
2023-08-10 21:26:28 +02:00
s1 = " was shot " ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-10 21:26:28 +02:00
s1 = " was shot in the " ;
2023-08-04 00:04:29 +02:00
bDispLocation = qtrue ;
}
2023-08-10 21:26:28 +02:00
break ;
2023-08-14 23:37:05 +02:00
case MOD_LANDMINE :
2023-08-10 21:26:28 +02:00
s1 = " stepped on a land mine " ;
break ;
2023-08-04 00:04:29 +02:00
default :
s1 = " died " ;
break ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 21:26:28 +02:00
if ( bDispLocation & & g_obituarylocation - > integer ) {
2024-10-02 16:42:10 +02:00
str szConv2 = s2 + " in the " + G_LocationNumToDispString ( iLocation ) ;
2023-08-10 21:26:28 +02:00
2024-10-02 16:42:10 +02:00
G_PrintDeathMessage ( s1 . c_str ( ) , szConv2 . c_str ( ) , " x " , client - > pers . netname , this , " w " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( dedicated - > integer ) {
2023-08-10 21:26:28 +02:00
gi . Printf ( " %s %s \n " , client - > pers . netname , gi . LV_ConvertString ( s1 . c_str ( ) ) ) ;
2023-08-04 00:04:29 +02:00
}
} else {
2023-08-10 21:26:28 +02:00
G_PrintDeathMessage ( s1 . c_str ( ) , s2 . c_str ( ) , " x " , client - > pers . netname , this , " w " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( dedicated - > integer ) {
2023-08-10 21:26:28 +02:00
gi . Printf ( " %s %s \n " , client - > pers . netname , gi . LV_ConvertString ( s1 . c_str ( ) ) ) ;
2023-08-04 00:04:29 +02:00
}
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : Dead ( Event * ev )
{
if ( deadflag = = DEAD_DEAD ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
health = 0 ;
deadflag = DEAD_DEAD ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
edict - > s . renderfx & = ~ RF_SHADOW ;
server_new_buttons = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
CancelEventsOfType ( EV_Player_Dead ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// stop animating
StopPartAnimating ( legs ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// pause the torso anim
PausePartAnim ( torso ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
partAnim [ torso ] = " " ;
2016-03-27 11:49:47 +02:00
2023-08-10 13:31:35 +02:00
if ( m_fPainBlend ! = 0 ) {
// Clear pain blend
StopAnimating ( ANIMSLOT_PAIN ) ;
edict - > s . frameInfo [ ANIMSLOT_PAIN ] . weight = 0 ;
2023-08-10 18:43:21 +02:00
m_fPainBlend = 0 ;
animdone_Pain = false ;
2023-08-10 13:31:35 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-13 16:11:25 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
if ( dmManager . AllowRespawn ( ) ) {
2023-08-10 13:31:35 +02:00
respawn_time = level . time + 1.0f ;
2023-08-10 14:18:40 +02:00
} else {
respawn_time = level . time + 2.0f ;
2023-08-04 00:04:29 +02:00
}
2023-08-10 13:31:35 +02:00
} else if ( level . current_map & & * level . current_map ) {
G_BeginIntermission ( level . current_map , TRANS_LEVEL ) ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-10 13:31:35 +02:00
respawn_time = level . time + 1.f ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ZoomOff ( ) ;
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
if ( ShouldForceSpectatorOnDeath ( ) ) {
2023-08-10 14:18:40 +02:00
m_bDeathSpectator = true ;
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
Spectator ( ) ;
SetPlayerSpectateRandom ( ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Killed ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Entity * attacker ;
Entity * inflictor ;
int meansofdeath ;
int location ;
2024-01-02 00:43:27 +01:00
Event * event ;
2016-03-27 11:49:47 +02:00
2023-08-10 21:38:37 +02:00
//
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-08-10 21:38:37 +02:00
// This one is openmohaa-specific
// Custom killed event will do the job
//
2023-11-27 20:07:57 +01:00
if ( m_killedLabel . IsSet ( ) ) {
event = new Event ( 0 , ev - > NumArgs ( ) ) ;
2023-08-04 00:04:29 +02:00
for ( int i = 1 ; i < = ev - > NumArgs ( ) ; i + + ) {
event - > AddValue ( ev - > GetValue ( i ) ) ;
}
2023-11-27 20:07:57 +01:00
m_killedLabel . Execute ( this , event ) ;
delete event ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Unregister ( STRING_DEATH ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 21:38:37 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
current_team - > AddDeaths ( this , 1 ) ;
} else {
AddDeaths ( 1 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
attacker = ev - > GetEntity ( 1 ) ;
inflictor = ev - > GetEntity ( 3 ) ;
meansofdeath = ev - > GetInteger ( 9 ) ;
location = ev - > GetInteger ( 10 ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 21:38:37 +02:00
if ( attacker & & inflictor ) {
2023-08-04 00:04:29 +02:00
Obituary ( attacker , inflictor , meansofdeath , location ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
RemoveFromVehiclesAndTurrets ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & attacker & & attacker - > IsSubclassOfPlayer ( ) ) {
2024-10-02 17:02:48 +02:00
static_cast < Player * > ( attacker ) - > KilledPlayerInDeathmatch ( this , ( meansOfDeath_t ) meansofdeath ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
deadflag = DEAD_DYING ;
health = 0 ;
2016-03-27 11:49:47 +02:00
2023-11-27 20:07:57 +01:00
event = new Event ( EV_Pain , 10 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
event - > AddEntity ( attacker ) ;
event - > AddFloat ( ev - > GetFloat ( 2 ) ) ;
event - > AddEntity ( inflictor ) ;
event - > AddVector ( ev - > GetVector ( 4 ) ) ;
event - > AddVector ( ev - > GetVector ( 5 ) ) ;
event - > AddVector ( ev - > GetVector ( 6 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 7 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 8 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 9 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 10 ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ProcessEvent ( event ) ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
if ( HasItem ( " Binoculars " ) ) {
takeItem ( " Binoculars " ) ;
}
PostEvent ( EV_Player_DMDeathDrop , 0.1f ) ;
edict - > s . eFlags | = EF_DEAD ;
}
edict - > clipmask = MASK_DEADSOLID ;
setContents ( CONTENTS_CORPSE ) ;
setSolidType ( SOLID_NOT ) ;
2023-08-10 21:38:37 +02:00
setMoveType ( MOVETYPE_TOSS ) ;
2023-08-04 00:04:29 +02:00
angles . x = 0 ;
angles . z = 0 ;
setAngles ( angles ) ;
//
// change music
//
ChangeMusic ( " failure " , " normal " , true ) ;
takedamage = DAMAGE_NO ;
// Post a dead event just in case
PostEvent ( EV_Player_Dead , 5.0f ) ;
ZoomOff ( ) ;
if ( g_voiceChat - > integer ) {
if ( m_voiceType = = PVT_ALLIED_MANON ) {
2023-08-10 21:38:37 +02:00
//
// manon_death doesn't exist in 2.0 anymore.
// The code is left just in case
//
2023-08-04 00:04:29 +02:00
Sound ( " manon_death " , CHAN_VOICE , - 1.0f , 160 , NULL , - 1.0f , 1 , 0 , 1 , 1200 ) ;
} else {
Sound ( " player_death " ) ;
}
} else {
Sound ( " player_death " ) ;
}
2023-08-10 21:38:37 +02:00
if ( m_fPainBlend ) {
//
// 2.0: No more pain animation after death
//
animdone_Pain = true ;
}
//
2023-12-28 20:34:49 +01:00
// Added in OPM
// Scripted events
2023-08-10 21:38:37 +02:00
//
2023-11-27 20:07:57 +01:00
event = new Event ( 0 , 11 ) ;
2023-08-04 00:04:29 +02:00
event - > AddEntity ( ev - > GetEntity ( 1 ) ) ;
event - > AddFloat ( ev - > GetFloat ( 2 ) ) ;
event - > AddEntity ( ev - > GetEntity ( 3 ) ) ;
event - > AddVector ( ev - > GetVector ( 4 ) ) ;
event - > AddVector ( ev - > GetVector ( 5 ) ) ;
event - > AddVector ( ev - > GetVector ( 6 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 7 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 8 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 9 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 10 ) ) ;
event - > AddEntity ( this ) ;
scriptedEvents [ SE_KILL ] . Trigger ( event ) ;
Unregister ( STRING_DEATH ) ;
}
void Player : : EventDMDeathDrop ( Event * ev )
{
Weapon * weapon = GetActiveWeapon ( WEAPON_MAIN ) ;
SpawnArgs args ;
ClassDef * cls ;
if ( ! m_bDontDropWeapons & & weapon & & weapon - > IsSubclassOfWeapon ( ) ) {
weapon - > Drop ( ) ;
}
args . setArg ( " model " , " models/items/dm_50_healthbox.tik " ) ;
cls = args . getClassDef ( ) ;
if ( cls ) {
Item * item = ( Item * ) cls - > newInstance ( ) ;
if ( item ) {
if ( item - > IsSubclassOfItem ( ) ) {
item - > setModel ( " models/items/dm_50_healthbox.tik " ) ;
item - > SetOwner ( this ) ;
item - > ProcessPendingEvents ( ) ;
item - > Drop ( ) ;
} else {
// useless and not pickupable, delete it
delete item ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
FreeInventory ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : EventStopwatch ( Event * ev )
{
2023-08-10 19:36:14 +02:00
stopWatchType_t eType = SWT_NORMAL ;
2023-08-04 00:04:29 +02:00
int iDuration = ev - > GetInteger ( 1 ) ;
if ( iDuration < 0 ) {
ScriptError ( " duration < 0 " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 19:36:14 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
eType = static_cast < stopWatchType_t > ( ev - > GetInteger ( 2 ) ) ;
} else {
eType = SWT_NORMAL ;
}
SetStopwatch ( iDuration , eType ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-10 19:36:14 +02:00
void Player : : SetStopwatch ( int iDuration , stopWatchType_t type )
2023-08-04 00:04:29 +02:00
{
2023-08-10 19:36:14 +02:00
int iStartTime ;
2023-08-04 00:04:29 +02:00
char szCmd [ 256 ] ;
2016-03-27 11:49:47 +02:00
2023-08-10 19:36:14 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
if ( type ! = SWT_NORMAL ) {
iStartTime = ( int ) ( level . svsFloatTime * 1000.f ) ;
} else {
iStartTime = 0 ;
if ( iDuration ) {
iStartTime = ceil ( level . svsFloatTime * 1000.f ) ;
}
}
2024-09-20 21:53:48 +02:00
Com_sprintf ( szCmd , sizeof ( szCmd ) , " stopwatch %i %i %i " , iStartTime , iDuration , type ) ;
2023-08-10 19:36:14 +02:00
} else {
iStartTime = 0 ;
if ( iDuration ) {
iStartTime = ( int ) level . svsFloatTime ;
}
2024-09-20 21:53:48 +02:00
Com_sprintf ( szCmd , sizeof ( szCmd ) , " stopwatch %i %i " , iStartTime , iDuration ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
gi . SendServerCommand ( edict - g_entities , szCmd ) ;
}
2024-10-02 17:02:48 +02:00
void Player : : KilledPlayerInDeathmatch ( Player * killed , meansOfDeath_t meansofdeath )
2023-08-04 00:04:29 +02:00
{
2023-11-03 21:56:31 +01:00
DM_Team * pDMTeam ;
2023-08-16 01:32:53 +02:00
2023-11-03 21:56:31 +01:00
pDMTeam = killed - > GetDM_Team ( ) ;
2023-08-04 00:04:29 +02:00
2024-10-02 17:02:48 +02:00
if ( meansofdeath = = MOD_TELEFRAG ) {
//
// Added in OPM
// Telefrag isn't the fault of anyone
// so don't count any kill
//
return ;
}
2023-08-04 00:04:29 +02:00
if ( killed = = this ) {
2023-08-16 01:32:53 +02:00
pDMTeam - > AddKills ( this , - 1 ) ;
2023-08-04 00:04:29 +02:00
gi . SendServerCommand (
edict - g_entities , " print \" " HUD_MESSAGE_WHITE " %s \n \" " , gi . LV_ConvertString ( " You killed yourself " )
) ;
2023-08-10 21:38:37 +02:00
2024-10-02 17:02:48 +02:00
return ;
}
2023-08-04 00:04:29 +02:00
2024-10-02 17:02:48 +02:00
if ( pDMTeam = = GetDM_Team ( ) & & g_gametype - > integer > = GT_TEAM ) {
//
// A teammate was killed
//
current_team - > AddKills ( this , - 1 ) ;
num_team_kills + + ;
} else {
current_team - > AddKills ( this , 1 ) ;
2023-08-04 00:04:29 +02:00
}
2024-10-02 17:02:48 +02:00
gi . SendServerCommand (
edict - g_entities ,
" print \" " HUD_MESSAGE_WHITE " %s %s \n \" " ,
gi . LV_ConvertString ( " You killed " ) ,
killed - > client - > pers . netname
) ;
2023-08-04 00:04:29 +02:00
}
void Player : : Pain ( Event * ev )
{
float damage , yawdiff ;
Entity * attacker ;
int meansofdeath ;
Vector dir , pos , attack_angle ;
int iLocation ;
attacker = ev - > GetEntity ( 1 ) ;
damage = ev - > GetFloat ( 2 ) ;
pos = ev - > GetVector ( 4 ) ;
dir = ev - > GetVector ( 5 ) ;
meansofdeath = ev - > GetInteger ( 9 ) ;
iLocation = ev - > GetInteger ( 10 ) ;
if ( ! damage & & ! knockdown ) {
return ;
}
client - > ps . stats [ STAT_LAST_PAIN ] = damage ;
// Determine direction
attack_angle = dir . toAngles ( ) ;
yawdiff = angles [ YAW ] - attack_angle [ YAW ] + 180 ;
yawdiff = AngleNormalize180 ( yawdiff ) ;
if ( yawdiff > - 45 & & yawdiff < 45 ) {
pain_dir = PAIN_FRONT ;
} else if ( yawdiff < - 45 & & yawdiff > - 135 ) {
pain_dir = PAIN_LEFT ;
} else if ( yawdiff > 45 & & yawdiff < 135 ) {
pain_dir = PAIN_RIGHT ;
} else {
pain_dir = PAIN_REAR ;
}
pain_type = ( meansOfDeath_t ) meansofdeath ;
pain_location = iLocation ;
// Only set the regular pain level if enough time since last pain has passed
2024-07-27 19:33:39 +02:00
if ( ( ( level . time > nextpaintime ) & & take_pain ) | | IsDead ( ) ) {
2023-08-04 00:04:29 +02:00
pain = damage ;
}
// 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
damage_blood + = damage ;
damage_from + = dir * damage ;
damage_yaw = dir . toYaw ( ) * 10.0f ;
if ( damage_yaw = = client - > ps . stats [ STAT_DAMAGEDIR ] ) {
if ( damage_yaw < 1800.0f ) {
damage_yaw + = 1.0f ;
} else {
damage_yaw - = 1.0f ;
}
}
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & attacker & & attacker - > client & & attacker ! = this ) {
2023-08-04 00:04:29 +02:00
gi . MSG_SetClient ( attacker - > edict - g_entities ) ;
if ( IsDead ( ) ) {
gi . MSG_StartCGM ( BG_MapCGMToProtocol ( g_protocol , CGM_NOTIFY_KILL ) ) ;
} else {
gi . MSG_StartCGM ( BG_MapCGMToProtocol ( g_protocol , CGM_NOTIFY_HIT ) ) ;
}
gi . MSG_EndCGM ( ) ;
}
if ( IsDead ( ) ) {
return ;
}
if ( g_voiceChat - > integer ) {
if ( m_voiceType = = PVT_ALLIED_MANON ) {
2023-08-11 00:43:40 +02:00
//
// Should have been removed since 2.0
//
2023-08-04 00:04:29 +02:00
Sound ( " manon_pain " , CHAN_DIALOG , - 1 , 160 , NULL , - 1 , 1 , 0 , 1 , 1200 ) ;
} else {
Sound ( " player_pain " ) ;
}
} else {
Sound ( " player_pain " ) ;
}
}
void Player : : DoUse ( Event * ev )
{
gentity_t * hit ;
int touch [ MAX_GENTITIES ] ;
int num ;
int i ;
2024-10-02 14:50:11 +02:00
bool bWasInTurretOrVehicle ;
2023-08-04 00:04:29 +02:00
2023-08-17 18:24:20 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & IsSpectator ( ) ) {
2023-10-17 17:41:41 +02:00
// Prevent using stuff while spectating
2023-08-04 00:04:29 +02:00
return ;
}
if ( IsDead ( ) ) {
2023-10-17 17:41:41 +02:00
// Dead players mustn't use
2023-08-04 00:04:29 +02:00
return ;
}
2024-10-02 14:50:11 +02:00
bWasInTurretOrVehicle = m_pVehicle | | m_pTurret ;
if ( bWasInTurretOrVehicle ) {
2023-08-11 00:43:40 +02:00
RemoveFromVehiclesAndTurretsInternal ( ) ;
2023-10-17 17:41:41 +02:00
return ;
}
2024-01-08 22:56:26 +01:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
if ( ( buttons & BUTTON_ATTACKLEFT ) | | ( buttons & BUTTON_ATTACKRIGHT ) ) {
//
// Added in 2.0
// Only allow use if the player isn't holding attack buttons
//
return ;
}
2023-10-17 17:41:41 +02:00
}
2023-08-04 00:04:29 +02:00
2023-10-17 17:41:41 +02:00
num = getUseableEntities ( touch , MAX_GENTITIES , true ) ;
2023-08-04 00:04:29 +02:00
2024-06-15 00:15:51 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
// Fixed in 2.0
// Since 2.0, the loop stops when the player
// uses a turret, this prevents the turret from being deleted
// after being attached to the player
//
for ( i = 0 ; i < num ; i + + ) {
hit = & g_entities [ touch [ i ] ] ;
2016-03-27 11:49:47 +02:00
2024-06-15 00:15:51 +02:00
if ( ! hit - > inuse ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2024-06-15 00:15:51 +02:00
Event * event = new Event ( EV_Use ) ;
event - > AddListener ( this ) ;
2023-08-17 18:24:20 +02:00
2024-06-15 00:15:51 +02:00
hit - > entity - > ProcessEvent ( event ) ;
2023-08-17 18:24:20 +02:00
2024-06-15 00:15:51 +02:00
if ( m_pVehicle | | m_pTurret ) {
break ;
}
}
} else {
//
// Backward compatibility
// It still allows 1.11 SP to work properly
// Such as in m1l1 when the player must man the mounted machine gun
for ( i = 0 ; i < num ; i + + ) {
hit = & g_entities [ touch [ i ] ] ;
if ( ! hit - > inuse ) {
continue ;
}
Event * event = new Event ( EV_Use ) ;
event - > AddListener ( this ) ;
hit - > entity - > ProcessEvent ( event ) ;
2023-08-04 00:04:29 +02:00
}
}
2016-03-27 11:49:47 +02:00
2024-10-02 14:50:11 +02:00
if ( ! bWasInTurretOrVehicle & & m_pVehicle ) {
2023-10-17 17:41:41 +02:00
//
// Added in 2.30
// Make the vehicle also invincible if the player is invincible
//
if ( flags & FL_GODMODE ) {
m_pVehicle - > flags | = FL_GODMODE ;
} else {
m_pVehicle - > flags & = ~ FL_GODMODE ;
2023-08-10 14:18:40 +02:00
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : TouchStuff ( pmove_t * pm )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
gentity_t * other ;
Event * event ;
int i ;
int j ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// clear out any conditionals that are controlled by touching
//
toucheduseanim = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( getMoveType ( ) ! = MOVETYPE_NOCLIP ) {
G_TouchTriggers ( this ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// touch other objects
for ( i = 0 ; i < pm - > numtouch ; i + + ) {
other = & g_entities [ pm - > touchents [ i ] ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( j = 0 ; j < i ; j + + ) {
gentity_t * ge = & g_entities [ j ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ge = = other ) {
break ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( j ! = i ) {
// duplicated
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Don't bother touching the world
if ( ( ! other - > entity ) | | ( other - > entity = = world ) ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
event = new Event ( EV_Touch ) ;
event - > AddEntity ( this ) ;
other - > entity - > ProcessEvent ( event ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
event = new Event ( EV_Touch ) ;
event - > AddEntity ( other - > entity ) ;
ProcessEvent ( event ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : GetMoveInfo ( pmove_t * pm )
{
moveresult = pm - > moveresult ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( ! deadflag | | ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & IsSpectator ( ) ) ) {
2023-08-04 00:04:29 +02:00
v_angle [ 0 ] = pm - > ps - > viewangles [ 0 ] ;
v_angle [ 1 ] = pm - > ps - > viewangles [ 1 ] ;
v_angle [ 2 ] = pm - > ps - > viewangles [ 2 ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( moveresult = = MOVERESULT_TURNED ) {
angles . y = v_angle [ 1 ] ;
setAngles ( angles ) ;
SetViewAngles ( angles ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
setOrigin ( Vector ( pm - > ps - > origin [ 0 ] , pm - > ps - > origin [ 1 ] , pm - > ps - > origin [ 2 ] ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE ) {
float backoff ;
float change ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
backoff = DotProduct ( pm - > ps - > groundTrace . plane . normal , pm - > ps - > velocity ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( i = 0 ; i < 3 ; i + + ) {
change = pm - > ps - > groundTrace . plane . normal [ i ] * backoff ;
pm - > ps - > velocity [ i ] - = change ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Set the ground entity
groundentity = NULL ;
if ( pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE ) {
groundentity = & g_entities [ pm - > ps - > groundEntityNum ] ;
airspeed = 200 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! groundentity - > entity | | groundentity - > entity - > getMoveType ( ) = = MOVETYPE_NONE ) {
m_vPushVelocity = vec_zero ;
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
//
2023-12-28 20:34:49 +01:00
// Fixed in OPM
2023-08-11 00:43:40 +02:00
// Disable predictions when the groundentity is moving up/down, looks like shaky otherwise
2023-08-04 00:04:29 +02:00
if ( groundentity - > entity & & groundentity - > entity ! = this & & groundentity - > entity - > velocity [ 2 ] ! = 0 ) {
pm - > ps - > pm_flags | = PMF_NO_PREDICTION ;
}
2024-02-23 23:09:29 +01:00
} else if ( m_pGlueMaster ) {
// Added in OPM
// Use the glue master for the ground entity to make the viewmodel will stay still
pm - > ps - > groundEntityNum = m_pGlueMaster - > entnum ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
velocity = Vector ( pm - > ps - > velocity [ 0 ] , pm - > ps - > velocity [ 1 ] , pm - > ps - > velocity [ 2 ] ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ( client - > ps . pm_flags & PMF_FROZEN ) | | ( client - > ps . pm_flags & PMF_NO_MOVE ) ) {
velocity = vec_zero ;
} else {
setSize ( pm - > mins , pm - > maxs ) ;
viewheight = pm - > ps - > viewheight ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// water type and level is set in the predicted code
waterlevel = pm - > waterlevel ;
watertype = pm - > watertype ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SetMoveInfo ( pmove_t * pm , usercmd_t * ucmd )
{
Vector move ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// set up for pmove
memset ( pm , 0 , sizeof ( pmove_t ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
velocity . copyTo ( client - > ps . velocity ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pm - > ps = & client - > ps ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ucmd ) {
pm - > cmd = * ucmd ;
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
if ( sv_drawtrace - > integer < = 1 ) {
2023-08-15 01:27:35 +02:00
pm - > trace = gi . trace ;
2023-08-11 00:43:40 +02:00
} else {
pm - > trace = & G_PMDrawTrace ;
}
2023-08-04 00:04:29 +02:00
pm - > tracemask = MASK_PLAYERSOLID ;
2023-08-15 01:27:35 +02:00
pm - > pointcontents = gi . pointcontents ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pm - > ps - > origin [ 0 ] = origin . x ;
pm - > ps - > origin [ 1 ] = origin . y ;
pm - > ps - > origin [ 2 ] = origin . z ;
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
/*
2023-08-13 17:59:41 +02:00
pm - > mins [ 0 ] = mins . x ;
pm - > mins [ 1 ] = mins . y ;
pm - > mins [ 2 ] = mins . z ;
2016-03-27 11:49:47 +02:00
2023-08-13 17:59:41 +02:00
pm - > maxs [ 0 ] = maxs . x ;
pm - > maxs [ 1 ] = maxs . y ;
pm - > maxs [ 2 ] = maxs . z ;
2023-08-11 00:43:40 +02:00
*/
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pm - > ps - > velocity [ 0 ] = velocity . x ;
pm - > ps - > velocity [ 1 ] = velocity . y ;
pm - > ps - > velocity [ 2 ] = velocity . z ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pm - > pmove_fixed = pmove_fixed - > integer ;
pm - > pmove_msec = pmove_msec - > integer ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( pmove_msec - > integer < 8 ) {
pm - > pmove_msec = 8 ;
} else if ( pmove_msec - > integer > 33 ) {
pm - > pmove_msec = 33 ;
}
2023-08-11 00:43:40 +02:00
2023-08-14 02:12:30 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
//
// Added in 2.0
// In multiplayer mode, specify if the player can lean while moving
//
if ( dmflags - > integer & DF_ALLOW_LEAN_MOVEMENT ) {
pm - > alwaysAllowLean = qtrue ;
} else {
pm - > alwaysAllowLean = qfalse ;
}
2023-08-11 00:43:40 +02:00
} else {
2023-08-20 14:02:33 +02:00
pm - > alwaysAllowLean = qfalse ;
2023-08-11 00:43:40 +02:00
}
2023-08-20 14:02:33 +02:00
2023-11-03 21:56:31 +01:00
pm - > leanMax = 45.f ;
pm - > leanAdd = 6.f ;
2023-08-20 14:02:33 +02:00
pm - > leanRecoverSpeed = 8.5f ;
2023-11-03 21:56:31 +01:00
pm - > leanSpeed = 2.f ;
2023-08-14 02:12:30 +02:00
} else {
pm - > alwaysAllowLean = qtrue ;
2023-08-20 14:02:33 +02:00
2023-11-03 21:56:31 +01:00
pm - > leanMax = 40.f ;
pm - > leanAdd = 10.f ;
2023-08-20 14:02:33 +02:00
pm - > leanRecoverSpeed = 15.f ;
2023-11-03 21:56:31 +01:00
pm - > leanSpeed = 4.f ;
2023-08-14 02:12:30 +02:00
}
2023-08-13 17:59:41 +02:00
2023-11-03 21:56:31 +01:00
pm - > protocol = g_protocol ;
2024-02-23 22:51:08 +01:00
// Added in OPM
// Initialize the ground entity
pm - > ps - > groundEntityNum = ENTITYNUM_NONE ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pmtype_t Player : : GetMovePlayerMoveType ( void )
{
if ( getMoveType ( ) = = MOVETYPE_NOCLIP | | IsSpectator ( ) ) {
return PM_NOCLIP ;
} else if ( deadflag ) {
return PM_DEAD ;
} else if ( movecontrol = = MOVECONTROL_CLIMBWALL ) {
return PM_CLIMBWALL ;
} else {
return PM_NORMAL ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : CheckGround ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
pmove_t pm ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetMoveInfo ( & pm , current_ucmd ) ;
Pmove_GroundTrace ( & pm ) ;
GetMoveInfo ( & pm ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
qboolean Player : : AnimMove ( Vector & move , Vector * endpos )
{
Vector up ;
Vector down ;
trace_t trace ;
int mask ;
Vector start ( origin ) ;
Vector end ( origin + move ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
mask = MASK_PLAYERSOLID ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// test the player position if they were a stepheight higher
trace = G_Trace ( start , mins , maxs , end , this , mask , true , " AnimMove " ) ;
if ( trace . fraction < 1 ) {
if ( ( movecontrol = = MOVECONTROL_HANGING ) | | ( movecontrol = = MOVECONTROL_CLIMBWALL ) ) {
up = origin ;
up . z + = move . z ;
trace = G_Trace ( origin , mins , maxs , up , this , mask , true , " AnimMove " ) ;
if ( trace . fraction < 1 ) {
if ( endpos ) {
* endpos = origin ;
}
return qfalse ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
origin = trace . endpos ;
end = origin ;
end . x + = move . x ;
end . y + = move . y ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( origin , mins , maxs , end , this , mask , true , " AnimMove " ) ;
if ( endpos ) {
* endpos = trace . endpos ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return ( trace . fraction > 0 ) ;
} else {
return TestMove ( move , endpos ) ;
}
} else {
if ( endpos ) {
* endpos = trace . endpos ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return qtrue ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
qboolean Player : : TestMove ( Vector & move , Vector * endpos )
{
trace_t trace ;
Vector pos ( origin + move ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( origin , mins , maxs , pos , this , MASK_PLAYERSOLID , true , " TestMove " ) ;
if ( trace . allsolid ) {
// player is completely trapped in another solid
if ( endpos ) {
* endpos = origin ;
}
return qfalse ;
}
if ( trace . fraction < 1.0f ) {
Vector up ( origin ) ;
up . z + = STEPSIZE ;
trace = G_Trace ( origin , mins , maxs , up , this , MASK_PLAYERSOLID , true , " TestMove " ) ;
if ( trace . fraction = = 0.0f ) {
if ( endpos ) {
* endpos = origin ;
}
return qfalse ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Vector temp ( trace . endpos ) ;
Vector end ( temp + move ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( temp , mins , maxs , end , this , MASK_PLAYERSOLID , true , " TestMove " ) ;
if ( trace . fraction = = 0.0f ) {
if ( endpos ) {
* endpos = origin ;
}
return qfalse ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
temp = trace . endpos ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Vector down ( trace . endpos ) ;
down . z = origin . z ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( temp , mins , maxs , down , this , MASK_PLAYERSOLID , true , " TestMove " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( endpos ) {
* endpos = trace . endpos ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return qtrue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
float Player : : TestMoveDist ( Vector & move )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Vector endpos ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
TestMove ( move , & endpos ) ;
endpos - = origin ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return endpos . length ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
static Vector vec_up = Vector ( 0 , 0 , 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : CheckMoveFlags ( void )
{
trace_t trace ;
Vector start ;
Vector end ;
float oldsp ;
Vector olddir ( oldvelocity . x , oldvelocity . y , 0 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// Check if moving forward will cause the player to fall
//
start = origin + yaw_forward * 52.0f ;
end = start ;
end . z - = STEPSIZE * 2 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( start , mins , maxs , end , this , MASK_PLAYERSOLID , true , " CheckMoveFlags " ) ;
canfall = ( trace . fraction > = 1.0f ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! groundentity & & ! ( client - > ps . walking ) ) {
falling = true ;
hardimpact = false ;
mediumimpact = false ;
} else {
falling = false ;
mediumimpact = oldvelocity . z < = - 180.0f ;
hardimpact = oldvelocity . z < - 400.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// check for running into walls
oldsp = VectorNormalize ( olddir ) ;
if ( ( oldsp > 220.0f ) & & ( velocity * olddir < 2.0f ) ) {
moveresult = MOVERESULT_HITWALL ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
move_forward_vel = DotProduct ( yaw_forward , velocity ) ;
move_backward_vel = - move_forward_vel ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( move_forward_vel < 0.0f ) {
move_forward_vel = 0.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( move_backward_vel < 0.0f ) {
move_backward_vel = 0.0f ;
}
move_left_vel = DotProduct ( yaw_left , velocity ) ;
move_right_vel = - move_left_vel ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( move_left_vel < 0.0f ) {
move_left_vel = 0.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( move_right_vel < 0.0f ) {
move_right_vel = 0.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
move_up_vel = DotProduct ( vec_up , velocity ) ;
move_down_vel = - move_up_vel ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( move_up_vel < 0.0f ) {
move_up_vel = 0.0f ;
}
if ( move_down_vel < 0.0f ) {
move_down_vel = 0.0f ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
qboolean Player : : CheckMove ( Vector & move , Vector * endpos )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
return AnimMove ( move , endpos ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
float Player : : CheckMoveDist ( Vector & move )
{
Vector endpos ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
CheckMove ( move , & endpos ) ;
endpos - = origin ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return endpos . length ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ClientMove ( usercmd_t * ucmd )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
pmove_t pm ;
Vector move ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
# ifdef OPM_FEATURES
2023-08-04 00:04:29 +02:00
int touch [ MAX_GENTITIES ] ;
int num = getUseableEntities ( touch , MAX_GENTITIES , true ) ;
bool bHintShown = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( int i = 0 ; i < num ; i + + ) {
Entity * entity = g_entities [ touch [ i ] ] . entity ;
if ( entity & & entity - > m_HintString . length ( ) ) {
entity - > ProcessHint ( edict , true ) ;
bHintShown = true ;
m_bShowingHint = true ;
break ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! bHintShown & & m_bShowingHint ) {
m_bShowingHint = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// FIXME: delete
2023-08-10 18:43:21 +02:00
if ( sv_specialgame - > integer )
2023-08-10 14:18:40 +02:00
{
gi . MSG_SetClient ( edict - g_entities ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 14:18:40 +02:00
// Send the hint string once
gi . MSG_StartCGM ( CGM_HINTSTRING ) ;
gi . MSG_WriteString ( " " ) ;
gi . MSG_EndCGM ( ) ;
}
2023-08-04 00:04:29 +02:00
}
2023-08-11 00:43:40 +02:00
# endif
2023-08-04 00:04:29 +02:00
oldorigin = origin ;
client - > ps . pm_type = GetMovePlayerMoveType ( ) ;
// set move flags
client - > ps . pm_flags & =
2024-10-02 14:35:37 +02:00
~ ( PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_TURRET | PMF_VIEW_PRONE
2023-08-04 00:04:29 +02:00
| PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START ) ;
if ( level . playerfrozen | | m_bFrozen ) {
client - > ps . pm_flags | = PMF_FROZEN ;
}
if ( ( flags & FL_IMMOBILE ) | | ( flags & FL_PARTIAL_IMMOBILE ) ) {
client - > ps . pm_flags | = PMF_NO_MOVE ;
client - > ps . pm_flags | = PMF_NO_PREDICTION ;
}
2023-08-11 00:43:40 +02:00
if ( m_pGlueMaster ) {
//
// Added in 2.0.
// Disable movement prediction/movement if the player is glued to something
//
client - > ps . pm_flags | = PMF_NO_PREDICTION ;
client - > ps . pm_flags | = PMF_NO_MOVE ;
}
2024-01-22 23:53:13 +01:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
if ( maxs . z = = 54.0f | | maxs . z = = 60.0f ) {
client - > ps . pm_flags | = PMF_DUCKED ;
} else if ( viewheight = = JUMP_START_VIEWHEIGHT ) {
client - > ps . pm_flags | = PMF_VIEW_JUMP_START ;
}
} else {
if ( maxs . z = = 60.0f ) {
client - > ps . pm_flags | = PMF_DUCKED ;
} else if ( maxs . z = = 54.0f ) {
client - > ps . pm_flags | = PMF_DUCKED | PMF_VIEW_PRONE ;
} else if ( maxs . z = = 20.0f ) {
client - > ps . pm_flags | = PMF_VIEW_PRONE ;
} else if ( maxs . z = = 53.0f ) {
client - > ps . pm_flags | = PMF_VIEW_DUCK_RUN ;
} else if ( viewheight = = JUMP_START_VIEWHEIGHT ) {
client - > ps . pm_flags | = PMF_VIEW_JUMP_START ;
}
2023-08-11 00:43:40 +02:00
}
2023-08-04 00:04:29 +02:00
switch ( movecontrol ) {
case MOVECONTROL_USER :
case MOVECONTROL_LEGS :
case MOVECONTROL_USER_MOVEANIM :
break ;
case MOVECONTROL_CROUCH :
client - > ps . pm_flags | = PMF_NO_PREDICTION | PMF_DUCKED | PMF_VIEW_PRONE ;
break ;
default :
client - > ps . pm_flags | = PMF_NO_PREDICTION ;
}
if ( movetype = = MOVETYPE_NOCLIP ) {
if ( ! ( last_ucmd . buttons & BUTTON_RUN ) ) {
2023-08-10 12:09:07 +02:00
client - > ps . speed = sv_runspeed - > value * sv_walkspeedmult - > value ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-10 12:09:07 +02:00
client - > ps . speed = sv_runspeed - > value ;
2023-08-04 00:04:29 +02:00
}
} else if ( ! groundentity ) {
client - > ps . speed = airspeed ;
} else {
2023-08-11 00:43:40 +02:00
Weapon * pWeap ;
2023-08-04 00:04:29 +02:00
2023-08-11 00:43:40 +02:00
if ( last_ucmd . buttons & BUTTON_RUN ) {
client - > ps . speed = GetRunSpeed ( ) ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-11 00:43:40 +02:00
client - > ps . speed = sv_runspeed - > value * sv_walkspeedmult - > value ;
2023-08-04 00:04:29 +02:00
}
if ( m_iMovePosFlags & MPF_POSITION_CROUCHING ) {
2023-08-11 00:43:40 +02:00
client - > ps . speed = ( float ) client - > ps . speed * sv_crouchspeedmult - > value ;
}
pWeap = GetActiveWeapon ( WEAPON_MAIN ) ;
if ( pWeap ) {
//
// Also use the weapon movement speed
//
if ( ! IsZoomed ( ) ) {
client - > ps . speed = ( float ) client - > ps . speed * pWeap - > m_fMovementSpeed ;
} else {
client - > ps . speed = ( float ) client - > ps . speed * pWeap - > m_fZoomMovement * pWeap - > m_fMovementSpeed ;
}
2023-08-04 00:04:29 +02:00
}
}
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
client - > ps . speed = ( int ) ( ( float ) client - > ps . speed * sv_dmspeedmult - > value ) ;
}
2023-08-11 00:43:40 +02:00
//====
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-08-04 00:04:29 +02:00
for ( int i = 0 ; i < MAX_SPEED_MULTIPLIERS ; i + + ) {
client - > ps . speed = ( int ) ( ( float ) client - > ps . speed * speed_multiplier [ i ] ) ;
}
2023-08-11 00:43:40 +02:00
//====
2023-08-04 00:04:29 +02:00
client - > ps . gravity = sv_gravity - > value * gravity ;
if ( ( movecontrol ! = MOVECONTROL_ABSOLUTE ) & & ( movecontrol ! = MOVECONTROL_PUSH )
& & ( movecontrol ! = MOVECONTROL_CLIMBWALL ) ) {
Vector oldpos ( origin ) ;
SetMoveInfo ( & pm , ucmd ) ;
Pmove ( & pm ) ;
GetMoveInfo ( & pm ) ;
2023-08-11 00:43:40 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & groundentity & & groundentity - > entity
& & groundentity - > entity - > IsSubclassOfSentient ( ) ) {
//
// Added in 2.0
// If the player is on another sentient, try to make it fall off
//
velocity - = Vector ( orientation [ 0 ] ) * ( random ( ) * 20.f ) ;
velocity - = Vector ( orientation [ 1 ] ) * ( random ( ) * 10.f ) ;
}
2023-08-04 00:04:29 +02:00
ProcessPmoveEvents ( pm . pmoveEvent ) ;
// if we're not moving, set the blocked flag in case the user is trying to move
2023-08-11 00:43:40 +02:00
if ( ( ucmd - > forwardmove | | ucmd - > rightmove ) & & ( ( oldpos - origin ) . length ( ) < 0.005f ) ) {
2023-08-04 00:04:29 +02:00
moveresult = MOVERESULT_BLOCKED ;
}
if ( client - > ps . walking & & moveresult > = MOVERESULT_BLOCKED ) {
setOrigin ( oldpos ) ;
VectorCopy ( origin , client - > ps . origin ) ;
}
} else {
if ( movecontrol = = MOVECONTROL_CLIMBWALL ) {
PM_UpdateViewAngles ( & client - > ps , ucmd ) ;
v_angle = client - > ps . viewangles ;
} else if ( ! deadflag ) {
v_angle = client - > ps . viewangles ;
}
// should collect objects to touch against
memset ( & pm , 0 , sizeof ( pmove_t ) ) ;
// keep the command time up to date or else the next PMove we run will try to catch up
client - > ps . commandTime = ucmd - > serverTime ;
velocity = vec_zero ;
}
if ( ( getMoveType ( ) ! = MOVETYPE_NOCLIP ) & & ( client - > ps . pm_flags & PMF_NO_PREDICTION ) ) {
if ( ( movecontrol = = MOVECONTROL_ABSOLUTE ) | | ( movecontrol = = MOVECONTROL_CLIMBWALL ) ) {
velocity = vec_zero ;
}
if ( ( movecontrol = = MOVECONTROL_ANIM ) | | ( movecontrol = = MOVECONTROL_CLIMBWALL )
| | ( movecontrol = = MOVECONTROL_USEANIM ) | | ( movecontrol = = MOVECONTROL_LOOPUSEANIM )
| | ( movecontrol = = MOVECONTROL_USER_MOVEANIM ) ) {
Vector delta = vec_zero ;
PlayerAnimDelta ( delta ) ;
// using PM_NOCLIP for a smooth move
//client->ps.pm_type = PM_NOCLIP;
if ( delta ! = vec_zero ) {
float mat [ 3 ] [ 3 ] ;
AngleVectors ( angles , mat [ 0 ] , mat [ 1 ] , mat [ 2 ] ) ;
MatrixTransformVector ( delta , mat , move ) ;
AnimMove ( move , & origin ) ;
setOrigin ( origin ) ;
CheckGround ( ) ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_fLastDeltaTime = level . time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
TouchStuff ( & pm ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : VehicleMove ( usercmd_t * ucmd )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( ! m_pVehicle ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
oldorigin = origin ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . pm_type = GetMovePlayerMoveType ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// set move flags
client - > ps . pm_flags & =
2024-10-02 14:35:37 +02:00
~ ( PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_TURRET | PMF_VIEW_PRONE
2023-08-04 00:04:29 +02:00
| PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START ) ;
2016-03-27 11:49:47 +02:00
2023-08-17 22:38:09 +02:00
// disable prediction
2024-10-02 14:35:37 +02:00
client - > ps . pm_flags | = PMF_TURRET | PMF_NO_PREDICTION ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( level . playerfrozen | | m_bFrozen ) {
client - > ps . pm_flags | = PMF_FROZEN ;
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
client - > ps . gravity = gravity * sv_gravity - > value ;
if ( m_pVehicle - > Drive ( current_ucmd ) ) {
2023-08-04 00:04:29 +02:00
client - > ps . commandTime = ucmd - > serverTime ;
2024-07-02 22:16:13 +02:00
// Added in OPM
// The player can't walk while attached to a vehicle
client - > ps . groundEntityNum = ENTITYNUM_NONE ;
client - > ps . walking = false ;
2023-08-04 00:04:29 +02:00
} else {
ClientMove ( ucmd ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : TurretMove ( usercmd_t * ucmd )
{
if ( ! m_pTurret ) {
return ;
}
oldorigin = origin ;
client - > ps . pm_type = GetMovePlayerMoveType ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// set move flags
client - > ps . pm_flags & =
2024-10-02 14:35:37 +02:00
~ ( PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_TURRET | PMF_VIEW_PRONE
2023-08-04 00:04:29 +02:00
| PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START ) ;
2023-08-17 22:38:09 +02:00
// disable prediction
2024-10-02 14:35:37 +02:00
client - > ps . pm_flags | = PMF_TURRET | PMF_NO_PREDICTION ;
2023-08-17 22:38:09 +02:00
if ( getMoveType ( ) = = MOVETYPE_PORTABLE_TURRET ) {
2024-10-02 14:35:37 +02:00
client - > ps . pm_flags | = PMF_TURRET ;
2023-08-17 22:38:09 +02:00
}
2023-08-04 00:04:29 +02:00
if ( level . playerfrozen | | m_bFrozen ) {
client - > ps . pm_flags | = PMF_FROZEN ;
}
2023-08-11 00:43:40 +02:00
client - > ps . gravity = gravity * sv_gravity - > value ;
2024-11-07 20:23:24 +01:00
if ( m_pVehicle ) {
// Added in 2.30
m_pVehicle - > PathDrive ( current_ucmd ) ;
}
2024-07-02 22:16:13 +02:00
if ( m_pTurret - > IsSubclassOfTurretGun ( ) & & m_pTurret - > UserAim ( current_ucmd ) ) {
2023-08-04 00:04:29 +02:00
client - > ps . commandTime = ucmd - > serverTime ;
2024-07-02 22:16:13 +02:00
// Added in OPM
// The player can't walk while attached to a turret
client - > ps . groundEntityNum = ENTITYNUM_NONE ;
client - > ps . walking = false ;
} else {
ClientMove ( ucmd ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ClientInactivityTimer ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_inactivekick - > integer & & g_inactivekick - > integer < 60 ) {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_inactiveKick " , " 60 " ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_inactivespectate - > integer & & g_inactivespectate - > integer < 20 ) {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_inactiveSpectate " , " 20 " ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
if ( num_team_kills > = g_teamkillkick - > integer ) {
const str message = gi . LV_ConvertString ( " was removed from the server for killing too many teammates. " ) ;
//
// The player reached maximum team kills
//
G_PrintToAllClients ( va ( " %s %s " , client - > pers . netname , message . c_str ( ) ) , qfalse ) ;
if ( Q_stricmp ( Info_ValueForKey ( client - > pers . userinfo , " ip " ) , " localhost " ) ) {
//
// Make sure to not kick the local host
//
gi . DropClient ( client - > ps . clientNum , message . c_str ( ) ) ;
} else if ( ! m_bSpectator ) {
// if it's the host, put it back in spectator mode
num_team_kills = 0 ;
m_iLastNumTeamKills = 0 ;
PostEvent ( EV_Player_Spectator , 0 ) ;
}
return ;
}
if ( num_team_kills > = g_teamkillwarn - > integer & & num_team_kills > m_iLastNumTeamKills ) {
const str sWarning = gi . LV_ConvertString ( " Warning: " ) ;
const str sTeamKills = gi . LV_ConvertString ( " more team kill(s) and you will be removed from the server. " ) ;
m_iLastNumTeamKills = num_team_kills ;
gi . centerprintf (
edict , " %s %i %s " , sWarning . c_str ( ) , g_teamkillkick - > integer - num_team_kills , sTeamKills . c_str ( )
) ;
}
2024-10-21 19:03:19 +02:00
if ( current_ucmd - > buttons & BUTTON_ANY | | ( ! g_inactivespectate - > integer & & ! g_inactivekick - > integer )
2023-08-11 00:43:40 +02:00
| | current_ucmd - > forwardmove | | current_ucmd - > rightmove | | current_ucmd - > upmove
| | ( m_bTempSpectator & & client - > lastActiveTime > = level . inttime - 5000 ) ) {
2023-08-04 00:04:29 +02:00
client - > lastActiveTime = level . inttime ;
client - > activeWarning = 0 ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_inactivekick - > integer & & client - > lastActiveTime < level . inttime - 1000 * g_inactivekick - > integer ) {
const char * s = Info_ValueForKey ( client - > pers . userinfo , " ip " ) ;
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
if ( Q_stricmp ( s , " localhost " ) ) {
2023-08-04 00:04:29 +02:00
gi . DropClient ( client - > ps . clientNum , " was dropped for inactivity " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_bSpectator ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
PostEvent ( EV_Player_Spectator , 0 ) ;
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_inactivespectate - > integer & & client - > lastActiveTime < level . inttime - g_inactivespectate - > integer * 1000
& & ! m_bSpectator ) {
2023-08-11 00:43:40 +02:00
PostEvent ( EV_Player_Spectator , 0 ) ;
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_inactivekick - > integer ) {
static struct {
int iLevel ;
int iTime ;
2023-08-11 00:43:40 +02:00
} warnkick [ 7 ] = {
{ 1 , 30 } ,
{ 8 , 15 } ,
{ 9 , 5 } ,
{ 10 , 4 } ,
{ 11 , 3 } ,
{ 12 , 2 } ,
{ 13 , 1 }
} ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
int iKickWait = g_inactivekick - > integer - ( level . inttime - client - > lastActiveTime ) / 1000 - 1 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( int i = 0 ; i < 7 ; i + + ) {
if ( client - > activeWarning < warnkick [ i ] . iLevel & & iKickWait < warnkick [ i ] . iTime ) {
2023-08-11 00:43:40 +02:00
const str sActionIn = gi . LV_ConvertString ( " You will be kicked for inactivity in " ) ;
const str sSeconds = gi . LV_ConvertString ( " seconds " ) ;
2023-08-04 00:04:29 +02:00
client - > activeWarning = warnkick [ i ] . iLevel ;
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
gi . centerprintf ( edict , " %s %i %s " , sActionIn . c_str ( ) , warnkick [ i ] . iTime , sSeconds . c_str ( ) ) ;
2023-08-04 00:04:29 +02:00
return ;
}
}
}
if ( g_inactivespectate - > integer & & dm_team ! = TEAM_SPECTATOR ) {
static struct {
int iLevel ;
int iTime ;
} warnspectate [ 6 ] = { 2 , 15 , 3 , 5 , 4 , 4 , 5 , 3 , 6 , 2 , 7 , 1 } ;
int iSpectateWait = g_inactivespectate - > integer - ( level . inttime - client - > lastActiveTime ) / 1000 - 1 ;
for ( int i = 0 ; i < 6 ; i + + ) {
if ( client - > activeWarning < warnspectate [ i ] . iLevel & & iSpectateWait < warnspectate [ i ] . iTime ) {
2023-08-11 00:43:40 +02:00
const str sActionIn = gi . LV_ConvertString ( " You will be moved to spectator for inactivity in " ) ;
const str sSeconds = gi . LV_ConvertString ( " seconds " ) ;
2023-08-04 00:04:29 +02:00
client - > activeWarning = warnspectate [ i ] . iLevel ;
2023-08-11 00:43:40 +02:00
gi . centerprintf ( edict , " %s %i %s " , sActionIn . c_str ( ) , warnspectate [ i ] . iTime , sSeconds . c_str ( ) ) ;
2023-08-04 00:04:29 +02:00
return ;
}
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : UpdateEnemies ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float fFov ;
float fMaxDist ;
float fMaxCosSquared ;
Vector vLookDir ;
2023-11-03 21:56:31 +01:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_pNextSquadMate = = this ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
fFov = fov * 0.9f ;
fMaxDist = world - > farplane_distance * 0.7867f ;
fMaxCosSquared = 0.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AngleVectors ( m_vViewAng , vLookDir , NULL , NULL ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_Enemy ) {
m_Enemy - > m_iAttackerCount - = 3 ;
m_Enemy = NULL ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( Sentient * obj = level . m_HeadSentient [ 0 ] ; obj ! = NULL ; obj = obj - > m_NextSentient ) {
Vector vDelta ;
float fDot ;
float fDotSquared ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:14 +02:00
if ( CanSee ( obj , fFov , fMaxDist , false ) ) {
2023-08-04 00:04:29 +02:00
obj - > m_fPlayerSightLevel + = level . frametime ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
vDelta = obj - > origin - origin ;
fDot = DotProduct ( vDelta , vLookDir ) ;
fDotSquared = fDot * fDot ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( fDotSquared > fMaxCosSquared * vDelta . lengthSquared ( ) ) {
fMaxCosSquared = fDotSquared / vDelta . lengthSquared ( ) ;
m_Enemy = obj ;
}
} else {
obj - > m_fPlayerSightLevel = 0.0f ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_Enemy ) {
m_Enemy - > m_iAttackerCount + = 3 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = = =
ClientThink
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
This will be called once for each client frame , which will
usually be a couple times for each server frame .
= = = = = = = = = = = = = =
*/
void Player : : ClientThink ( void )
{
// sanity check the command time to prevent speedup cheating
if ( current_ucmd - > serverTime > level . svsTime ) {
//
// we don't want any future commands, these could be from the previous game
//
return ;
}
if ( current_ucmd - > serverTime < level . svsTime - 1000 ) {
current_ucmd - > serverTime = level . svsTime - 1000 ;
}
if ( ( current_ucmd - > serverTime - client - > ps . commandTime ) < 1 ) {
return ;
}
2023-08-11 00:43:40 +02:00
TickSprint ( ) ;
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & dm_team = = TEAM_SPECTATOR & & ! IsSpectator ( ) ) {
2023-08-04 00:04:29 +02:00
Spectator ( ) ;
}
last_ucmd = * current_ucmd ;
server_new_buttons | = current_ucmd - > buttons & ~ buttons ;
new_buttons = current_ucmd - > buttons & ~ buttons ;
buttons = current_ucmd - > buttons ;
if ( camera ) {
m_vViewPos = camera - > origin ;
m_vViewAng = camera - > angles ;
} else {
m_vViewPos [ 0 ] = ( float ) current_eyeinfo - > ofs [ 0 ] + origin [ 0 ] ;
m_vViewPos [ 1 ] = ( float ) current_eyeinfo - > ofs [ 1 ] + origin [ 1 ] ;
m_vViewPos [ 2 ] = ( float ) current_eyeinfo - > ofs [ 2 ] + origin [ 2 ] ;
m_vViewAng [ 0 ] = current_eyeinfo - > angles [ 0 ] ;
m_vViewAng [ 1 ] = current_eyeinfo - > angles [ 1 ] ;
m_vViewAng [ 2 ] = 0.0f ;
}
VectorCopy ( m_vViewPos , client - > ps . vEyePos ) ;
2023-08-11 00:43:40 +02:00
if ( ! level . intermissiontime ) {
if ( new_buttons & BUTTON_ATTACKRIGHT ) {
Weapon * weapon = GetActiveWeapon ( WEAPON_MAIN ) ;
if ( weapon & & ( weapon - > GetZoom ( ) ) ) {
ToggleZoom ( weapon - > GetZoom ( ) ) ;
}
}
if ( new_buttons & BUTTON_USE ) {
DoUse ( NULL ) ;
}
moveresult = MOVERESULT_NONE ;
if ( m_pTurret ) {
TurretMove ( current_ucmd ) ;
} else if ( m_pVehicle ) {
VehicleMove ( current_ucmd ) ;
} else {
ClientMove ( current_ucmd ) ;
}
// Save cmd angles so that we can get delta angle movements next frame
client - > cmd_angles [ 0 ] = SHORT2ANGLE ( current_ucmd - > angles [ 0 ] ) ;
client - > cmd_angles [ 1 ] = SHORT2ANGLE ( current_ucmd - > angles [ 1 ] ) ;
client - > cmd_angles [ 2 ] = SHORT2ANGLE ( current_ucmd - > angles [ 2 ] ) ;
2024-10-07 00:51:01 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & g_smoothClients - > integer ) {
2023-08-11 00:43:40 +02:00
VectorCopy ( client - > ps . velocity , edict - > s . pos . trDelta ) ;
edict - > s . pos . trTime = client - > ps . commandTime ;
} else {
VectorClear ( edict - > s . pos . trDelta ) ;
edict - > s . pos . trTime = 0 ;
}
ClientInactivityTimer ( ) ;
} else {
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
client - > ps . pm_flags | = PMF_FROZEN ;
client - > ps . pm_flags | = PMF_INTERMISSION ;
if ( level . time - level . intermissiontime > 5.0f
& & ( new_buttons & ( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ) ) ) {
level . exitintermission = true ;
}
} else {
2023-08-11 00:43:40 +02:00
if ( level . intermissiontype = = TRANS_MISSION_FAILED | | IsDead ( ) ) {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_success " , " 0 " ) ;
gi . cvar_set ( " g_failed " , " 1 " ) ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_success " , " 1 " ) ;
gi . cvar_set ( " g_failed " , " 0 " ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// prevent getting medals from cheats
if ( g_medal0 - > modificationCount > 1 | | g_medal1 - > modificationCount > 1 | | g_medal2 - > modificationCount > 1
| | g_medal3 - > modificationCount > 1 | | g_medal4 - > modificationCount > 1 | | g_medal5 - > modificationCount > 1
2023-08-11 00:43:40 +02:00
| | g_medalbt1 - > modificationCount > 1 | | g_medalbt2 - > modificationCount > 1
| | g_medalbt3 - > modificationCount > 1 | | g_medalbt4 - > modificationCount > 1
2023-08-11 01:58:15 +02:00
| | g_medalbt5 - > modificationCount > 1 | | g_eogmedal0 - > modificationCount > 1
| | g_eogmedal1 - > modificationCount > 1 | | g_eogmedal2 - > modificationCount > 1 ) {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_gotmedal " , " 1 " ) ;
2024-07-23 19:53:40 +02:00
} else {
gi . cvar_set ( " g_gotmedal " , " 0 " ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
client - > ps . pm_flags | = PMF_FROZEN ;
2023-08-04 00:04:29 +02:00
if ( level . time - level . intermissiontime > 4.0f ) {
if ( level . intermissiontype ) {
2023-08-11 00:43:40 +02:00
if ( level . intermissiontype = = TRANS_MISSION_FAILED ) {
if ( ( new_buttons & BUTTON_ATTACKLEFT ) | | ( new_buttons & BUTTON_ATTACKRIGHT ) ) {
2023-08-04 00:04:29 +02:00
G_MissionFailed ( ) ;
}
2023-08-11 00:43:40 +02:00
} else if ( ( new_buttons & BUTTON_ATTACKLEFT ) | | ( new_buttons & BUTTON_ATTACKRIGHT ) ) {
g_medal0 - > modificationCount = 1 ;
g_medal1 - > modificationCount = 1 ;
g_medal2 - > modificationCount = 1 ;
g_medal3 - > modificationCount = 1 ;
g_medal4 - > modificationCount = 1 ;
g_medal5 - > modificationCount = 1 ;
g_medalbt0 - > modificationCount = 1 ;
g_medalbt1 - > modificationCount = 1 ;
g_medalbt2 - > modificationCount = 1 ;
g_medalbt3 - > modificationCount = 1 ;
g_medalbt4 - > modificationCount = 1 ;
g_medalbt5 - > modificationCount = 1 ;
g_eogmedal0 - > modificationCount = 1 ;
g_eogmedal1 - > modificationCount = 1 ;
g_eogmedal2 - > modificationCount = 1 ;
g_medal0 - > modified = false ;
g_medal1 - > modified = false ;
g_medal2 - > modified = false ;
g_medal3 - > modified = false ;
g_medal4 - > modified = false ;
g_medal5 - > modified = false ;
g_eogmedal0 - > modified = false ;
g_eogmedal1 - > modified = false ;
g_eogmedal2 - > modified = false ;
level . exitintermission = true ;
2023-08-04 00:04:29 +02:00
}
} else {
level . exitintermission = true ;
}
}
}
// Save cmd angles so that we can get delta angle movements next frame
2023-08-11 00:43:40 +02:00
client - > cmd_angles [ 0 ] = SHORT2ANGLE ( current_ucmd - > angles [ 0 ] ) ;
client - > cmd_angles [ 1 ] = SHORT2ANGLE ( current_ucmd - > angles [ 1 ] ) ;
client - > cmd_angles [ 2 ] = SHORT2ANGLE ( current_ucmd - > angles [ 2 ] ) ;
client - > ps . commandTime = current_ucmd - > serverTime ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Think ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
static cvar_t * g_aimLagTime = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
int m_iClientWeaponCommand ;
Event * m_pWeaponCommand = NULL ;
Weapon * pWeap ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( whereami - > integer & & origin ! = oldorigin ) {
gi . DPrintf ( " x %8.2f y %8.2f z %8.2f area %2d \n " , origin [ 0 ] , origin [ 1 ] , origin [ 2 ] , edict - > r . areanum ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER & & g_playermodel - > modified ) {
setModel ( " models/player/ " + str ( g_playermodel - > string ) + " .tik " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! edict - > tiki ) {
setModel ( " models/player/american_army.tik " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
g_playermodel - > modified = qfalse ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
m_bIsDisguised = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_bHasDisguise & & ! level . m_bAlarm ) {
pWeap = GetActiveWeapon ( WEAPON_MAIN ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! pWeap | | pWeap - > IsSubclassOfInventoryItem ( ) ) {
m_bIsDisguised = true ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( Sentient * pSent = level . m_HeadSentient [ 0 ] ; pSent ! = NULL ; pSent = pSent - > m_NextSentient ) {
Actor * act = ( Actor * ) pSent ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( pSent - > m_Enemy = = this & & act - > IsAttacking ( ) ) {
m_bIsDisguised = false ;
break ;
}
}
}
}
PathSearch : : PlayerCover ( this ) ;
UpdateEnemies ( ) ;
}
if ( movetype = = MOVETYPE_NOCLIP ) {
StopPartAnimating ( torso ) ;
SetPartAnim ( " idle " ) ;
client - > ps . walking = qfalse ;
groundentity = 0 ;
} else {
CheckMoveFlags ( ) ;
EvaluateState ( ) ;
}
oldvelocity = velocity ;
old_v_angle = v_angle ;
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
2023-08-11 00:43:40 +02:00
if ( ( server_new_buttons & BUTTON_ATTACKLEFT ) & & ( ! GetActiveWeapon ( WEAPON_MAIN ) ) & & ! IsDead ( )
& & ! IsNewActiveWeapon ( ) & & ! LoadingSavegame ) {
2023-08-04 00:04:29 +02:00
Event * ev = new Event ( " useweaponclass " ) ;
ev - > AddString ( " item1 " ) ;
ProcessEvent ( ev ) ;
}
} else {
2023-08-11 00:43:40 +02:00
// Added in 2.0: Invulnerability and team spawn
TickInvulnerable ( ) ;
TickTeamSpawn ( ) ;
2023-08-04 00:04:29 +02:00
if ( deadflag = = DEAD_DEAD & & level . time > respawn_time ) {
2023-08-11 00:43:40 +02:00
if ( dmManager . AllowRespawn ( ) & & AllowTeamRespawn ( ) ) {
2023-08-04 00:04:29 +02:00
if ( ( ( server_new_buttons & BUTTON_ATTACKLEFT ) | | ( server_new_buttons & BUTTON_ATTACKRIGHT ) )
| | ( g_forcerespawn - > integer > 0 & & level . time > g_forcerespawn - > integer + respawn_time ) ) {
2023-08-11 00:43:40 +02:00
// 2.0
// Check for team respawn
//
if ( ! m_fSpawnTimeLeft ) {
if ( AllowTeamRespawn ( ) ) {
EndSpectator ( ) ;
PostEvent ( EV_Player_Respawn , 0 ) ;
}
} else {
m_bWaitingForRespawn = true ;
}
2023-08-04 00:04:29 +02:00
}
} else if ( ! IsSpectator ( ) ) {
BeginTempSpectator ( ) ;
}
}
2023-08-11 00:43:40 +02:00
if ( IsSpectator ( ) ) {
if ( ! m_bTempSpectator & & level . time > respawn_time & & ( server_new_buttons & BUTTON_ATTACKLEFT ) ) {
if ( current_team & & dm_team ! = TEAM_SPECTATOR ) {
if ( client - > pers . dm_primary [ 0 ] ) {
if ( ( g_gametype - > integer = = GT_FFA
| | ( g_gametype - > integer > = GT_TEAM & & dm_team > TEAM_FREEFORALL ) )
& & deadflag ! = DEAD_DEAD ) {
// 2.0
// Check for team respawn
//
if ( ! m_fSpawnTimeLeft ) {
if ( AllowTeamRespawn ( ) ) {
EndSpectator ( ) ;
PostEvent ( EV_Player_Respawn , 0 ) ;
}
} else {
m_bWaitingForRespawn = true ;
}
}
} else if ( m_fWeapSelectTime < level . time ) {
m_fWeapSelectTime = level . time + 1.0 ;
2023-08-15 01:27:35 +02:00
UserSelectWeapon ( false ) ;
2023-08-11 00:43:40 +02:00
}
} else if ( m_fWeapSelectTime < level . time ) {
m_fWeapSelectTime = level . time + 1.0 ;
gi . SendServerCommand ( edict - g_entities , " stufftext \" pushmenu_teamselect \" " ) ;
2023-08-04 00:04:29 +02:00
}
}
2024-09-02 01:01:55 +02:00
// Removed in 2.0
//else if (level.time > m_fWeapSelectTime + 10.0) {
// m_fWeapSelectTime = level.time;
// gi.centerprintf(edict, "\n\n\n%s", gi.LV_ConvertString("Press fire to join the battle!"));
//}
2023-08-04 00:04:29 +02:00
} else if ( ! client - > pers . dm_primary [ 0 ] ) {
Spectator ( ) ;
2023-08-11 00:43:40 +02:00
if ( m_fWeapSelectTime < level . time ) {
2024-10-23 20:15:29 +02:00
m_fWeapSelectTime = level . time + 1.0 ;
UserSelectWeapon ( false ) ;
2023-08-11 00:43:40 +02:00
}
2023-08-04 00:04:29 +02:00
}
if ( IsSpectator ( ) ) {
2023-08-10 13:31:35 +02:00
if ( g_protocol > = PROTOCOL_MOHTA_MIN ) {
if ( m_iPlayerSpectating ) {
if ( last_ucmd . upmove ) {
if ( ! m_bSpectatorSwitching ) {
m_bSpectatorSwitching = true ;
if ( last_ucmd . upmove > 0 ) {
SetPlayerSpectate ( true ) ;
} else {
SetPlayerSpectate ( false ) ;
}
}
} else {
m_bSpectatorSwitching = false ;
}
} else if ( ( server_new_buttons & BUTTON_USE ) ) {
SetPlayerSpectateRandom ( ) ;
server_new_buttons & = ~ BUTTON_USE ;
}
2023-08-10 14:18:40 +02:00
} else {
if ( ( server_new_buttons & BUTTON_USE ) ) {
2023-08-10 13:31:35 +02:00
SetPlayerSpectateRandom ( ) ;
2023-08-10 14:18:40 +02:00
}
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:43:40 +02:00
if ( g_gametype - > integer > = GT_TEAM & & g_forceteamspectate - > integer & & GetTeam ( ) > TEAM_FREEFORALL ) {
if ( ! m_iPlayerSpectating ) {
SetPlayerSpectateRandom ( ) ;
} else {
gentity_t * ent = g_entities + m_iPlayerSpectating - 1 ;
2023-11-03 21:56:31 +01:00
2023-08-11 00:43:40 +02:00
if ( ! ent - > inuse | | ! ent - > entity ) {
2023-10-13 21:15:02 +02:00
// Invalid spectate entity
2023-08-11 00:43:40 +02:00
SetPlayerSpectateRandom ( ) ;
2024-03-05 23:30:25 +01:00
} else if ( ent - > entity - > deadflag > = DEAD_DEAD | | static_cast < Player * > ( ent - > entity ) - > IsSpectator ( ) | | ! IsValidSpectatePlayer ( static_cast < Player * > ( ent - > entity ) ) ) {
2023-08-10 13:31:35 +02:00
SetPlayerSpectateRandom ( ) ;
2023-08-04 00:04:29 +02:00
}
}
} else {
2023-08-11 00:43:40 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
// Since 2.0, use = clear spectator
if ( m_iPlayerSpectating & & ( server_new_buttons & BUTTON_USE ) ) {
m_iPlayerSpectating = 0 ;
}
2023-08-04 00:04:29 +02:00
} else {
2023-08-11 00:43:40 +02:00
// On 1.11 and below, up = clear spectator
if ( last_ucmd . upmove ) {
m_iPlayerSpectating = 0 ;
}
}
2023-08-04 00:04:29 +02:00
2023-08-11 00:43:40 +02:00
if ( m_iPlayerSpectating ) {
gentity_t * ent = g_entities + m_iPlayerSpectating - 1 ;
2023-11-03 21:56:31 +01:00
2023-08-11 00:43:40 +02:00
if ( ! ent - > inuse | | ! ent - > entity ) {
// Invalid spectate entity
2023-08-10 13:31:35 +02:00
SetPlayerSpectateRandom ( ) ;
2023-11-13 20:31:41 +01:00
} else if ( ent - > entity - > deadflag > = DEAD_DEAD | | static_cast < Player * > ( ent - > entity ) - > IsSpectator ( ) | | ! IsValidSpectatePlayer ( static_cast < Player * > ( ent - > entity ) ) ) {
2023-08-10 13:31:35 +02:00
SetPlayerSpectateRandom ( ) ;
2023-10-13 21:15:02 +02:00
} else if ( g_gametype - > integer > = GT_TEAM & & GetTeam ( ) > TEAM_FREEFORALL & & static_cast < Player * > ( ent - > entity ) - > GetTeam ( ) ! = GetTeam ( ) ) {
2023-08-10 13:31:35 +02:00
SetPlayerSpectateRandom ( ) ;
2023-08-04 00:04:29 +02:00
}
}
}
} else {
m_iPlayerSpectating = 0 ;
}
}
if ( g_logstats - > integer ) {
if ( ! logfile_started ) {
ProcessEvent ( EV_Player_LogStats ) ;
logfile_started = qtrue ;
}
}
if ( ! IsDead ( ) ) {
2023-08-11 00:43:40 +02:00
m_iClientWeaponCommand = ( server_new_buttons & WEAPON_COMMAND_MASK ) > > 7 ;
2023-08-04 00:04:29 +02:00
switch ( m_iClientWeaponCommand ) {
case 0 :
2023-08-11 00:43:40 +02:00
// No command
2023-08-04 00:04:29 +02:00
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_PISTOL :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " pistol " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_RIFLE :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " rifle " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_SMG :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " smg " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_MG :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " mg " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_GRENADE :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " grenade " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_HEAVY :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " heavy " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_ITEM1 :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_ToggleItemUse ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_ITEM2 :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " item2 " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_ITEM3 :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " item3 " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_ITEM4 :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseWeaponClass ) ;
m_pWeaponCommand - > AddString ( " item4 " ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_PREV_WEAPON :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Player_PrevWeapon ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_NEXT_WEAPON :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Player_NextWeapon ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_USE_LAST_WEAPON :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Sentient_UseLastWeapon ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_HOLSTER :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Player_Holster ) ;
break ;
2023-08-11 00:43:40 +02:00
case WEAPON_COMMAND_DROP :
2023-08-04 00:04:29 +02:00
m_pWeaponCommand = new Event ( EV_Player_DropWeapon ) ;
break ;
default :
gi . DPrintf ( " Unrecognized weapon command %d \n " , m_iClientWeaponCommand ) ;
}
if ( m_pWeaponCommand ) {
2023-08-11 00:43:40 +02:00
PostEvent ( m_pWeaponCommand , 0 ) ;
2023-08-04 00:04:29 +02:00
}
}
2023-08-11 00:43:40 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
if ( ! g_aimLagTime ) {
g_aimLagTime = gi . Cvar_Get ( " g_aimLagTime " , " 250 " , 0 ) ;
}
if ( mLastTrailTime + g_aimLagTime - > integer < level . inttime ) {
mLastTrailTime = level . inttime ;
mvTrail [ 0 ] = centroid ;
mvTrailEyes [ 0 ] = centroid ;
mvTrailEyes [ 0 ] [ 0 ] = EyePosition ( ) [ 0 ] ;
}
2023-08-04 00:04:29 +02:00
}
2023-09-03 00:07:17 +02:00
UpdateFootsteps ( ) ;
2023-08-04 00:04:29 +02:00
2023-08-11 00:43:40 +02:00
//
// Added in 2.0
// Heal rate
//
if ( m_fHealRate & & ! IsDead ( ) ) {
float newrate ;
if ( g_healrate - > value & & g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
newrate = max_health * ( g_healrate - > value / 100.f ) * level . frametime ;
if ( newrate > = m_fHealRate ) {
newrate = m_fHealRate ;
m_fHealRate = 0 ;
} else {
m_fHealRate - = newrate ;
}
} else {
2023-08-28 15:48:12 +02:00
newrate = m_fHealRate ;
2023-08-11 00:43:40 +02:00
m_fHealRate = 0 ;
}
2023-08-04 00:04:29 +02:00
2023-08-11 00:43:40 +02:00
// heal
health + = newrate ;
if ( health > max_health ) {
// make sure it doesn't go above the maximum player health
health = max_health ;
}
2023-08-04 00:04:29 +02:00
}
2023-08-11 00:43:40 +02:00
//
// Added in 2.0: talk icon
//
if ( buttons & BUTTON_TALK ) {
2024-10-02 14:09:27 +02:00
edict - > s . eFlags | = EF_PLAYER_IN_MENU ;
2023-08-11 00:43:40 +02:00
} else {
2024-10-02 14:09:27 +02:00
edict - > s . eFlags & = ~ EF_PLAYER_IN_MENU ;
2023-08-11 00:43:40 +02:00
}
2023-08-04 00:04:29 +02:00
2023-08-11 00:43:40 +02:00
if ( m_fTalkTime > level . time ) {
edict - > s . eFlags | = EF_PLAYER_TALKING ;
} else {
edict - > s . eFlags & = ~ EF_PLAYER_TALKING ;
}
//
2023-12-28 20:34:49 +01:00
// Added in OPM
2023-08-11 00:43:40 +02:00
//
2023-08-04 00:04:29 +02:00
if ( ! animDoneVM ) {
int index ;
float anim_time ;
vma_t * vma = vmalist . find ( m_sVMcurrent ) ;
index = m_fpsTiki = = NULL ? - 1 : gi . Anim_NumForName ( m_fpsTiki , m_sVMAcurrent ) ;
if ( index > = 0 ) {
anim_time = gi . Anim_Time ( m_fpsTiki , index ) ;
if ( m_fVMAtime < anim_time ) {
if ( vma ) {
m_fVMAtime + = level . frametime * vma - > speed ;
} else {
m_fVMAtime + = level . frametime ;
}
} else {
animDoneVM = true ;
m_fVMAtime = 0 ;
Notify ( " viewmodelanim_done " ) ;
}
} else {
animDoneVM = true ;
m_fVMAtime = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Notify ( " viewmodelanim_done " ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
server_new_buttons = 0 ;
2024-09-15 01:14:38 +02:00
edict - > r . svFlags & = ~ ( SVF_SINGLECLIENT | SVF_NOTSINGLECLIENT ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitLegsStateTable ( void )
{
animdone_Legs = false ;
currentState_Legs = statemap_Legs - > FindState ( " STAND " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
str legsAnim ( currentState_Legs - > getLegAnim ( * this , & legs_conditionals ) ) ;
if ( legsAnim = = " " ) {
StopPartAnimating ( legs ) ;
} else if ( legsAnim ! = " none " ) {
SetPartAnim ( legsAnim . c_str ( ) , legs ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitTorsoStateTable ( void )
{
animdone_Torso = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
currentState_Torso = statemap_Torso - > FindState ( " STAND " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
str torsoAnim ( currentState_Torso - > getActionAnim ( * this , & torso_conditionals ) ) ;
if ( torsoAnim = = " " ) {
StopPartAnimating ( torso ) ;
} else if ( torsoAnim ! = " none " ) {
SetPartAnim ( torsoAnim . c_str ( ) , torso ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : LoadStateTable ( void )
2016-03-27 11:49:47 +02:00
{
2024-10-13 22:09:38 +02:00
int i ;
Conditional * cond ;
2023-08-04 00:04:29 +02:00
statemap_Legs = NULL ;
statemap_Torso = NULL ;
2016-03-27 11:49:47 +02:00
2024-10-13 22:09:38 +02:00
//
// Free existing conditionals
//
for ( i = legs_conditionals . NumObjects ( ) ; i > 0 ; i - - ) {
cond = legs_conditionals . ObjectAt ( i ) ;
delete cond ;
}
2023-08-04 00:04:29 +02:00
legs_conditionals . FreeObjectList ( ) ;
2024-10-13 22:09:38 +02:00
for ( i = torso_conditionals . NumObjects ( ) ; i > 0 ; i - - ) {
cond = torso_conditionals . ObjectAt ( i ) ;
delete cond ;
}
2023-08-04 00:04:29 +02:00
torso_conditionals . FreeObjectList ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
statemap_Legs =
2024-11-03 20:05:44 +01:00
GetStatemap ( str ( g_statefile - > string ) + " _Legs.st " , ( Condition < Class > * ) m_conditions , & legs_conditionals , false ) ;
2023-08-04 00:04:29 +02:00
statemap_Torso =
2024-11-03 20:05:44 +01:00
GetStatemap ( str ( g_statefile - > string ) + " _Torso.st " , ( Condition < Class > * ) m_conditions , & torso_conditionals , false ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
movecontrol = MOVECONTROL_LEGS ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
InitLegsStateTable ( ) ;
InitTorsoStateTable ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
movecontrol = currentState_Legs - > getMoveType ( ) ;
if ( ! movecontrol ) {
movecontrol = MOVECONTROL_LEGS ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( int i = 1 ; i < = legs_conditionals . NumObjects ( ) ; i + + ) {
Conditional * c = legs_conditionals . ObjectAt ( i ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( Q_stricmp ( c - > getName ( ) , " PAIN " ) & & ! c - > parmList . NumObjects ( ) ) {
m_pLegsPainCond = c ;
break ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( int i = 1 ; i < = torso_conditionals . NumObjects ( ) ; i + + ) {
Conditional * c = torso_conditionals . ObjectAt ( i ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( Q_stricmp ( c - > getName ( ) , " PAIN " ) & & ! c - > parmList . NumObjects ( ) ) {
m_pTorsoPainCond = c ;
break ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ( movecontrol < ( sizeof ( MoveStartFuncs ) / sizeof ( MoveStartFuncs [ 0 ] ) ) ) & & ( MoveStartFuncs [ movecontrol ] ) ) {
( this - > * MoveStartFuncs [ movecontrol ] ) ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetViewAngles ( v_angle ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ResetState ( Event * ev )
2023-08-02 20:59:19 +02:00
{
2023-08-04 00:04:29 +02:00
movecontrol = MOVECONTROL_LEGS ;
LoadStateTable ( ) ;
2023-08-02 20:59:19 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : StartPush ( void )
2023-08-02 20:59:19 +02:00
{
2023-08-04 00:04:29 +02:00
trace_t trace ;
Vector end ( origin + yaw_forward * 64.0f ) ;
2023-08-02 20:59:19 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( origin , mins , maxs , end , this , MASK_SOLID , true , " StartPush " ) ;
if ( trace . fraction = = 1.0f ) {
return ;
}
v_angle . y = vectoyaw ( trace . plane . normal ) - 180 ;
SetViewAngles ( v_angle ) ;
setOrigin ( trace . endpos - yaw_forward * 0.4f ) ;
2023-08-02 20:59:19 +02:00
}
2023-08-09 01:31:56 +02:00
void Player : : StartClimbLadder ( void )
2023-08-02 20:59:19 +02:00
{
2023-08-04 00:04:29 +02:00
trace_t trace ;
Vector end ( origin + yaw_forward * 20.0f ) ;
2023-08-09 01:31:56 +02:00
trace = G_Trace ( origin , mins , maxs , end , this , MASK_SOLID , true , " StartClimbLadder " ) ;
2023-08-04 00:04:29 +02:00
if ( ( trace . fraction = = 1.0f ) | | ! ( trace . surfaceFlags & SURF_LADDER ) ) {
return ;
}
v_angle . y = vectoyaw ( trace . plane . normal ) - 180 ;
SetViewAngles ( v_angle ) ;
setOrigin ( trace . endpos - yaw_forward * 0.4f ) ;
2023-08-02 20:59:19 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : StartUseAnim ( void )
2023-08-02 20:59:19 +02:00
{
2023-08-04 00:04:29 +02:00
UseAnim * ua ;
Vector neworg ;
Vector newangles ;
str newanim ;
str state ;
str camera ;
trace_t trace ;
if ( toucheduseanim ) {
ua = ( UseAnim * ) ( Entity * ) toucheduseanim ;
} else if ( atobject ) {
ua = ( UseAnim * ) ( Entity * ) atobject ;
} else {
return ;
}
useitem_in_use = ua ;
toucheduseanim = NULL ;
atobject = NULL ;
if ( ua - > GetInformation ( this , & neworg , & newangles , & newanim , & useanim_numloops , & state , & camera ) ) {
trace = G_Trace ( origin , mins , maxs , neworg , this , MASK_PLAYERSOLID , true , " StartUseAnim " ) ;
if ( trace . startsolid | | ( trace . fraction < 1.0f ) ) {
gi . DPrintf ( " Move to UseAnim was blocked. \n " ) ;
}
if ( ! trace . startsolid ) {
setOrigin ( trace . endpos ) ;
}
setAngles ( newangles ) ;
v_angle . y = newangles . y ;
SetViewAngles ( v_angle ) ;
movecontrol = MOVECONTROL_ABSOLUTE ;
if ( state . length ( ) ) {
State * newState ;
newState = statemap_Torso - > FindState ( state ) ;
if ( newState ) {
EvaluateState ( newState ) ;
} else {
gi . DPrintf ( " Could not find state %s on UseAnim \n " , state . c_str ( ) ) ;
}
} else {
if ( currentState_Torso ) {
if ( camera . length ( ) ) {
currentState_Torso - > setCameraType ( camera ) ;
} else {
currentState_Torso - > setCameraType ( " behind " ) ;
}
}
SetPartAnim ( newanim , legs ) ;
}
}
2023-08-02 20:59:19 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : StartLoopUseAnim ( void )
2023-08-02 20:59:19 +02:00
{
2023-08-04 00:04:29 +02:00
useanim_numloops - - ;
2023-08-02 20:59:19 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : FinishUseAnim ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
UseAnim * ua ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! useitem_in_use ) {
return ;
}
ua = ( UseAnim * ) ( Entity * ) useitem_in_use ;
ua - > TriggerTargets ( this ) ;
useitem_in_use = NULL ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetupUseObject ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
UseObject * uo ;
Vector neworg ;
Vector newangles ;
str state ;
trace_t trace ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( atobject ) {
uo = ( UseObject * ) ( Entity * ) atobject ;
} else {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
useitem_in_use = uo ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
uo - > Setup ( this , & neworg , & newangles , & state ) ;
{
trace = G_Trace ( neworg , mins , maxs , neworg , this , MASK_PLAYERSOLID , true , " SetupUseObject - 1 " ) ;
if ( trace . startsolid | | trace . allsolid ) {
trace = G_Trace ( origin , mins , maxs , neworg , this , MASK_PLAYERSOLID , true , " SetupUseObject - 2 " ) ;
if ( trace . startsolid | | ( trace . fraction < 1.0f ) ) {
gi . DPrintf ( " Move to UseObject was blocked. \n " ) ;
}
}
if ( ! trace . startsolid ) {
setOrigin ( trace . endpos ) ;
}
setAngles ( newangles ) ;
v_angle . y = newangles . y ;
SetViewAngles ( v_angle ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
movecontrol = MOVECONTROL_ABSOLUTE ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( state . length ( ) ) {
State * newState ;
newState = statemap_Torso - > FindState ( state ) ;
if ( newState ) {
EvaluateState ( newState ) ;
} else {
gi . DPrintf ( " Could not find state %s on UseObject \n " , state . c_str ( ) ) ;
}
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : StartUseObject ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
UseObject * uo ;
if ( ! useitem_in_use ) {
return ;
}
uo = ( UseObject * ) ( Entity * ) useitem_in_use ;
uo - > Start ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : FinishUseObject ( Event * ev )
{
UseObject * uo ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! useitem_in_use ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
uo = ( UseObject * ) ( Entity * ) useitem_in_use ;
uo - > Stop ( this ) ;
useitem_in_use = NULL ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Turn ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float yaw ;
Vector oldang ( v_angle ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
yaw = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
v_angle [ YAW ] = ( int ) ( anglemod ( v_angle [ YAW ] ) / 22.5f ) * 22.5f ;
SetViewAngles ( v_angle ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! CheckMove ( vec_zero ) ) {
SetViewAngles ( oldang ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
CancelEventsOfType ( EV_Player_TurnUpdate ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev = new Event ( EV_Player_TurnUpdate ) ;
ev - > AddFloat ( yaw / 5.0f ) ;
ev - > AddFloat ( 0.5f ) ;
ProcessEvent ( ev ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : TurnUpdate ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float yaw ;
float timeleft ;
Vector oldang ( v_angle ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
yaw = ev - > GetFloat ( 1 ) ;
timeleft = ev - > GetFloat ( 2 ) ;
timeleft - = 0.1f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( timeleft > 0 ) {
ev = new Event ( EV_Player_TurnUpdate ) ;
ev - > AddFloat ( yaw ) ;
ev - > AddFloat ( timeleft ) ;
PostEvent ( ev , 0.1f ) ;
v_angle [ YAW ] + = yaw ;
SetViewAngles ( v_angle ) ;
} else {
v_angle [ YAW ] = ( int ) ( anglemod ( v_angle [ YAW ] ) / 22.5f ) * 22.5f ;
SetViewAngles ( v_angle ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! CheckMove ( vec_zero ) ) {
SetViewAngles ( oldang ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : TurnLegs ( Event * ev )
{
float yaw ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
yaw = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
angles [ YAW ] + = yaw ;
setAngles ( angles ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EvaluateState ( State * forceTorso , State * forceLegs )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
int count ;
State * laststate_Legs ;
State * laststate_Torso ;
State * startstate_Legs ;
State * startstate_Torso ;
movecontrol_t move ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( getMoveType ( ) = = MOVETYPE_NOCLIP ) {
return ;
}
2016-03-27 11:49:47 +02:00
2024-02-23 21:12:38 +01:00
if ( flags & FL_IMMOBILE ) {
// Don't evaluate state when immobile
return ;
}
2024-10-31 19:49:05 +01:00
if ( getMoveType ( ) = = MOVETYPE_PORTABLE_TURRET ) {
// Added in 2.0
// Animations are handled hardcodedly
currentState_Torso = NULL ;
currentState_Legs = NULL ;
return ;
}
2023-08-04 00:04:29 +02:00
// Evaluate the current state.
// When the state changes, we reevaluate the state so that if the
// conditions aren't met in the new state, we don't play one frame of
// the animation for that state before going to the next state.
startstate_Torso = laststate_Torso = currentState_Torso ;
count = 0 ;
do {
// since we could get into an infinite loop here, do a check
// to make sure we don't.
count + + ;
if ( count > 10 ) {
gi . DPrintf ( " Possible infinite loop in state '%s' \n " , currentState_Torso - > getName ( ) ) ;
if ( count > 20 ) {
assert ( 0 ) ;
gi . Error ( ERR_DROP , " Stopping due to possible infinite state loop \n " ) ;
break ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
laststate_Torso = currentState_Torso ;
2023-05-21 21:21:20 +02:00
2024-10-31 19:48:15 +01:00
if ( currentState_Torso ) {
laststate_Torso = currentState_Torso ;
if ( forceTorso ) {
currentState_Torso = forceTorso ;
} else {
currentState_Torso = currentState_Torso - > Evaluate ( * this , & torso_conditionals ) ;
}
2023-08-04 00:04:29 +02:00
} else {
2024-10-31 19:48:15 +01:00
// Added in 2.0
// Switch to the default torso state if it's NULL
if ( forceTorso ) {
currentState_Torso = forceTorso ;
} else {
currentState_Torso = statemap_Torso - > FindState ( " STAND " ) ;
}
laststate_Torso = NULL ;
2023-08-04 00:04:29 +02:00
}
2023-05-21 21:21:20 +02:00
2023-08-04 00:04:29 +02:00
if ( currentState_Torso ) {
2024-10-31 19:48:15 +01:00
if ( laststate_Torso ) {
// Process exit commands of the last state
laststate_Torso - > ProcessExitCommands ( this ) ;
}
2023-05-21 21:21:20 +02:00
2023-08-04 00:04:29 +02:00
// Process entry commands of the new state
currentState_Torso - > ProcessEntryCommands ( this ) ;
2023-05-21 21:21:20 +02:00
2023-08-04 00:04:29 +02:00
if ( waitForState . length ( ) & & ( ! waitForState . icmpn ( currentState_Torso - > getName ( ) , waitForState . length ( ) ) ) ) {
waitForState = " " ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
move = currentState_Torso - > getMoveType ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// use the current movecontrol
if ( move = = MOVECONTROL_NONE ) {
move = movecontrol ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
str legsAnim ;
str torsoAnim ( currentState_Torso - > getActionAnim ( * this , & torso_conditionals ) ) ;
if ( move = = MOVECONTROL_LEGS ) {
if ( ! currentState_Legs ) {
animdone_Legs = false ;
currentState_Legs = statemap_Legs - > FindState ( " STAND " ) ;
legsAnim = currentState_Legs - > getLegAnim ( * this , & legs_conditionals ) ;
if ( legsAnim = = " " ) {
StopPartAnimating ( legs ) ;
} else if ( legsAnim ! = " none " ) {
SetPartAnim ( legsAnim . c_str ( ) , legs ) ;
}
}
if ( torsoAnim = = " none " ) {
StopPartAnimating ( torso ) ;
animdone_Torso = true ;
} else if ( torsoAnim ! = " " ) {
SetPartAnim ( torsoAnim . c_str ( ) , torso ) ;
}
} else {
if ( torsoAnim = = " none " ) {
StopPartAnimating ( torso ) ;
animdone_Torso = true ;
} else if ( torsoAnim ! = " " ) {
SetPartAnim ( torsoAnim . c_str ( ) , torso ) ;
}
legsAnim = currentState_Torso - > getLegAnim ( * this , & torso_conditionals ) ;
if ( legsAnim = = " none " | | legsAnim = = " " ) {
StopPartAnimating ( legs ) ;
} else {
SetPartAnim ( legsAnim . c_str ( ) , legs ) ;
}
2024-09-16 20:20:19 +02:00
// Fixed in OPM
// Clear the legs state, so the torso state can reset it to STAND
// in subsequent iterations.
// As the legs animation is stopped, there would be no anim to wait on.
//
// This prevents the current legs state to be stuck
// when the move control is set to non-legs and then to legs
// in the same iteration before the legs state is being processed.
currentState_Legs = NULL ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( movecontrol ! = move ) {
movecontrol = move ;
if ( ( move < ( sizeof ( MoveStartFuncs ) / sizeof ( MoveStartFuncs [ 0 ] ) ) ) & & ( MoveStartFuncs [ move ] ) ) {
( this - > * MoveStartFuncs [ move ] ) ( ) ;
}
if ( movecontrol = = MOVECONTROL_CLIMBWALL ) {
edict - > s . eFlags | = EF_CLIMBWALL ;
} else {
edict - > s . eFlags & = ~ EF_CLIMBWALL ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetViewAngles ( v_angle ) ;
} else {
currentState_Torso = laststate_Torso ;
}
} while ( laststate_Torso ! = currentState_Torso ) ;
// Evaluate the current state.
// When the state changes, we reevaluate the state so that if the
// conditions aren't met in the new state, we don't play one frame of
// the animation for that state before going to the next state.
startstate_Legs = laststate_Legs = currentState_Legs ;
if ( movecontrol = = MOVECONTROL_LEGS ) {
count = 0 ;
do {
// since we could get into an infinite loop here, do a check
// to make sure we don't.
count + + ;
if ( count > 10 ) {
gi . DPrintf ( " Possible infinite loop in state '%s' \n " , currentState_Legs - > getName ( ) ) ;
if ( count > 20 ) {
assert ( 0 ) ;
gi . Error ( ERR_DROP , " Stopping due to possible infinite state loop \n " ) ;
break ;
}
}
2016-03-27 11:49:47 +02:00
2024-10-31 19:48:15 +01:00
if ( currentState_Legs ) {
laststate_Legs = currentState_Legs ;
if ( forceLegs ) {
currentState_Legs = forceLegs ;
} else {
currentState_Legs = currentState_Legs - > Evaluate ( * this , & legs_conditionals ) ;
}
} else {
// Added in 2.0
// Switch to the default legs state if it's NULL
if ( forceLegs ) {
currentState_Legs = forceLegs ;
} else if ( ( m_iMovePosFlags & MPF_POSITION_CROUCHING ) ) {
2023-08-04 00:04:29 +02:00
currentState_Legs = statemap_Legs - > FindState ( " CROUCH_IDLE " ) ;
} else {
currentState_Legs = statemap_Legs - > FindState ( " STAND " ) ;
}
2016-03-27 11:49:47 +02:00
2024-10-31 19:48:15 +01:00
laststate_Legs = NULL ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
animdone_Legs = false ;
if ( currentState_Legs ) {
2024-10-31 19:48:15 +01:00
if ( laststate_Legs ) {
// Process exit commands of the last state
laststate_Legs - > ProcessExitCommands ( this ) ;
}
2023-08-04 00:04:29 +02:00
// Process entry commands of the new state
currentState_Legs - > ProcessEntryCommands ( this ) ;
if ( waitForState . length ( )
& & ( ! waitForState . icmpn ( currentState_Legs - > getName ( ) , waitForState . length ( ) ) ) ) {
waitForState = " " ;
}
str legsAnim ( currentState_Legs - > getLegAnim ( * this , & legs_conditionals ) ) ;
if ( legsAnim = = " none " ) {
StopPartAnimating ( legs ) ;
animdone_Legs = true ;
} else if ( legsAnim ! = " " ) {
SetPartAnim ( legsAnim , legs ) ;
}
} else {
currentState_Legs = laststate_Legs ;
}
} while ( laststate_Legs ! = currentState_Legs ) ;
} else {
currentState_Legs = NULL ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_showplayeranim - > integer ) {
if ( last_leg_anim_name ! = AnimName ( legs ) ) {
gi . DPrintf ( " Legs change from %s to %s \n " , last_leg_anim_name . c_str ( ) , AnimName ( legs ) ) ;
last_leg_anim_name = AnimName ( legs ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( last_torso_anim_name ! = AnimName ( torso ) ) {
gi . DPrintf ( " Torso change from %s to %s \n " , last_torso_anim_name . c_str ( ) , AnimName ( torso ) ) ;
last_torso_anim_name = AnimName ( torso ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_showplayerstate - > integer ) {
if ( startstate_Legs ! = currentState_Legs ) {
gi . DPrintf (
" Legs change from %s to %s \n " ,
startstate_Legs ? startstate_Legs - > getName ( ) : " NULL " ,
currentState_Legs ? currentState_Legs - > getName ( ) : " NULL "
) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( startstate_Torso ! = currentState_Torso ) {
gi . DPrintf (
" Torso change from %s to %s \n " ,
startstate_Torso ? startstate_Torso - > getName ( ) : " NULL " ,
currentState_Torso ? currentState_Torso - > getName ( ) : " NULL "
) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// This is so we don't remember pain when we change to a state that has a PAIN condition
pain = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : SelectPreviousItem ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( deadflag ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
Item * item = GetActiveWeapon ( WEAPON_MAIN ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
item = PrevItem ( item ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( item ) {
2023-08-04 00:21:19 +02:00
useWeapon ( ( Weapon * ) item , WEAPON_MAIN ) ;
2023-08-04 00:04:29 +02:00
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SelectNextItem ( Event * ev )
{
if ( deadflag ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Item * item = GetActiveWeapon ( WEAPON_MAIN ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
item = NextItem ( item ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( item ) {
useWeapon ( ( Weapon * ) item , WEAPON_MAIN ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SelectPreviousWeapon ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( deadflag ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Weapon * weapon = GetActiveWeapon ( WEAPON_MAIN ) ;
Weapon * activeWeapon = weapon ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( weapon ) {
weapon = PreviousWeapon ( weapon ) ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
while ( weapon & & weapon ! = activeWeapon & & weapon - > IsSubclassOfInventoryItem ( ) ) {
2024-01-02 00:43:27 +01:00
Weapon * prev = PreviousWeapon ( weapon ) ;
2023-12-27 14:07:57 +01:00
// Added in OPM
// Fixes the bug that cause infinite loop when the last weapon has no ammo
// and the only weapon is an inventory item
if ( prev = = weapon ) {
break ;
}
weapon = prev ;
2023-08-04 00:04:29 +02:00
}
}
} else {
weapon = BestWeapon ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( weapon & & weapon ! = activeWeapon ) {
useWeapon ( weapon ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : SelectNextWeapon ( Event * ev )
2023-08-04 00:04:29 +02:00
{
if ( deadflag ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
Weapon * weapon = GetActiveWeapon ( WEAPON_MAIN ) ;
Weapon * activeWeapon = weapon ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( weapon ) {
weapon = NextWeapon ( weapon ) ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
while ( weapon & & weapon ! = activeWeapon & & weapon - > IsSubclassOfInventoryItem ( ) ) {
2024-01-02 00:43:27 +01:00
Weapon * next = NextWeapon ( weapon ) ;
2023-12-27 14:07:57 +01:00
// Added in OPM
// Fixes the bug that cause infinite loop when the last weapon has no ammo
// and the only weapon is an inventory item
if ( next = = weapon ) {
break ;
}
weapon = next ;
2023-08-04 00:04:29 +02:00
}
}
2023-08-04 00:21:19 +02:00
} else {
2023-08-04 00:04:29 +02:00
weapon = WorstWeapon ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( weapon & & weapon ! = activeWeapon ) {
useWeapon ( weapon ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : DropCurrentWeapon ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Weapon * weapon ;
Vector forward ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
weapon = GetActiveWeapon ( WEAPON_MAIN ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! weapon ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Don't drop the weapon if we're charging
if ( charge_start_time ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ( weapon - > GetWeaponClass ( ) & WEAPON_CLASS_ITEM ) ) {
SelectNextWeapon ( NULL ) ;
takeItem ( weapon - > model ) ;
} else {
if ( weapon - > GetCurrentAttachToTag ( ) ! = " tag_weapon_right " ) {
EventCorrectWeaponAttachments ( NULL ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// This check isn't in MOHAA
if ( ! weapon - > IsDroppable ( ) ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
weapon - > Drop ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AngleVectors ( m_vViewAng , forward , NULL , NULL ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// make the weapon looks like it's thrown
weapon - > velocity = forward * 200.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
edict - > s . eFlags | = EF_UNARMED ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SelectNextWeapon ( NULL ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( holsteredWeapon = = weapon ) {
holsteredWeapon = NULL ;
}
if ( lastActiveWeapon . weapon = = weapon ) {
lastActiveWeapon . weapon = NULL ;
}
}
}
void Player : : GiveWeaponCheat ( Event * ev )
{
giveItem ( ev - > GetString ( 1 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : GiveCheat ( Event * ev )
{
str name ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( deadflag ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
name = ev - > GetString ( 1 ) ;
2017-06-08 11:46:08 +02:00
2023-08-04 00:04:29 +02:00
if ( ! name . icmp ( " all " ) ) {
GiveAllCheat ( ev ) ;
return ;
}
EventGiveItem ( ev ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GiveAllCheat ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
char * buffer ;
char * buf ;
char com_token [ MAX_STRING_CHARS ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( deadflag ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( gi . FS_ReadFile ( " global/giveall.scr " , ( void * * ) & buf , true ) ! = - 1 ) {
buffer = buf ;
while ( 1 ) {
2024-09-20 21:53:48 +02:00
Q_strncpyz ( com_token , COM_ParseExt ( & buffer , qtrue ) , sizeof ( com_token ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! com_token [ 0 ] ) {
break ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Create the event
ev = new Event ( com_token ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// get the rest of the line
while ( 1 ) {
2024-09-20 21:53:48 +02:00
Q_strncpyz ( com_token , COM_ParseExt ( & buffer , qfalse ) , sizeof ( com_token ) ) ;
2023-08-04 00:04:29 +02:00
if ( ! com_token [ 0 ] ) {
break ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddToken ( com_token ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
this - > ProcessEvent ( ev ) ;
}
gi . FS_FreeFile ( buf ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-10 18:43:21 +02:00
void Player : : GiveNewWeaponsCheat ( Event * ev )
2023-08-10 03:46:28 +02:00
{
2023-08-10 18:43:21 +02:00
char * buffer ;
char * current ;
const char * token ;
2023-08-10 13:31:35 +02:00
if ( deadflag ! = DEAD_NO ) {
return ;
}
2023-08-11 00:43:40 +02:00
if ( gi . FS_ReadFile ( " global/givenewweapons.scr " , ( void * * ) & buffer , qtrue ) ! = - 1 ) {
2023-08-10 13:31:35 +02:00
return ;
}
current = buffer ;
2023-08-10 18:43:21 +02:00
for ( ; ; ) {
Event * event ;
2023-08-10 13:31:35 +02:00
token = COM_ParseExt ( & current , qtrue ) ;
if ( ! token [ 0 ] ) {
break ;
}
event = new Event ( token ) ;
2023-08-10 18:43:21 +02:00
for ( ; ; ) {
2023-08-10 14:18:40 +02:00
token = COM_ParseExt ( & current , qfalse ) ;
if ( ! token [ 0 ] ) {
break ;
}
2023-08-10 13:31:35 +02:00
event - > AddToken ( token ) ;
}
ProcessEvent ( event ) ;
}
gi . FS_FreeFile ( buffer ) ;
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GodCheat ( Event * ev )
{
const char * msg ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 0 ) {
if ( ev - > GetInteger ( 1 ) ) {
flags | = FL_GODMODE ;
2023-08-11 00:48:09 +02:00
// Also enable the god mode for the vehicle
2023-08-11 01:58:15 +02:00
if ( m_pVehicle ) {
m_pVehicle - > flags | = FL_GODMODE ;
}
2023-08-04 00:04:29 +02:00
} else {
2023-08-11 01:58:15 +02:00
flags & = ~ FL_GODMODE ;
// Also disable the god mode for the vehicle
if ( m_pVehicle ) {
m_pVehicle - > flags & = ~ FL_GODMODE ;
}
2023-08-04 00:04:29 +02:00
}
} else {
2023-08-11 00:48:09 +02:00
if ( flags & FL_GODMODE ) {
2023-08-11 01:58:15 +02:00
flags & = ~ FL_GODMODE ;
if ( m_pVehicle ) {
m_pVehicle - > flags & = ~ FL_GODMODE ;
}
2023-08-11 00:48:09 +02:00
} else {
flags | = FL_GODMODE ;
2023-08-11 01:58:15 +02:00
if ( m_pVehicle ) {
m_pVehicle - > flags | = FL_GODMODE ;
}
2023-08-11 00:48:09 +02:00
}
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-11 00:48:09 +02:00
if ( ev - > isSubclassOf ( ConsoleEvent ) ) {
2023-08-04 00:04:29 +02:00
if ( ! ( flags & FL_GODMODE ) ) {
2023-08-11 00:48:09 +02:00
msg = " CHEAT: godmode OFF \n " ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-11 00:48:09 +02:00
msg = " CHEAT: godmode ON \n " ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
gi . SendServerCommand ( edict - g_entities , " print \" %s \" " , msg ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : Kill ( Event * ev )
{
if ( ( level . time - respawn_time ) < 5 ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
flags & = ~ FL_GODMODE ;
health = 1 ;
Damage ( this , this , 10 , origin , vec_zero , vec_zero , 0 , DAMAGE_NO_PROTECTION , MOD_SUICIDE ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : NoTargetCheat ( Event * ev )
{
const char * msg ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
flags ^ = FL_NOTARGET ;
if ( ! ( flags & FL_NOTARGET ) ) {
msg = " notarget OFF \n " ;
} else {
msg = " notarget ON \n " ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
gi . SendServerCommand ( edict - g_entities , " print \" %s \" " , msg ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : NoclipCheat ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
const char * msg ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_pVehicle ) {
msg = " Must exit vehicle first \n " ;
} else if ( m_pTurret ) {
msg = " Must exit turret first \n " ;
} else if ( getMoveType ( ) = = MOVETYPE_NOCLIP ) {
setMoveType ( MOVETYPE_WALK ) ;
msg = " noclip OFF \n " ;
// reset the state machine so that his animations are correct
ResetState ( NULL ) ;
2024-10-20 22:42:05 +02:00
charge_start_time = 0 ;
2023-08-04 00:04:29 +02:00
} else {
client - > ps . feetfalling = false ;
movecontrol = MOVECONTROL_LEGS ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
setMoveType ( MOVETYPE_NOCLIP ) ;
msg = " noclip ON \n " ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
gi . SendServerCommand ( edict - g_entities , " print \" %s \" " , msg ) ;
}
void Player : : GameVersion ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
gi . SendServerCommand ( edict - g_entities , " print \" %s : %s \n \" " , GAMEVERSION , __DATE__ ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetFov ( float newFov )
{
fov = newFov ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( fov < 1 ) {
fov = 80 ;
} else if ( fov > 160 ) {
fov = 160 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : EventSetSelectedFov ( Event * ev )
{
2024-10-26 22:29:27 +02:00
float fOldSelectedFov ;
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) < 1 ) {
gi . SendServerCommand ( edict - g_entities , " print \" Fov = %d \n \" " , ( unsigned int ) fov ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2024-10-26 22:29:27 +02:00
fOldSelectedFov = selectedfov ;
2023-08-04 00:04:29 +02:00
SetSelectedFov ( ev - > GetFloat ( 1 ) ) ;
2024-10-26 22:29:27 +02:00
if ( fov = = fOldSelectedFov ) {
SetFov ( selectedfov ) ;
}
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SetSelectedFov ( float newFov )
{
selectedfov = newFov ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( selectedfov < 1 ) {
selectedfov = 80 ;
} else if ( selectedfov > 160 ) {
selectedfov = 160 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/*
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & ! developer - > integer )
2023-08-10 14:18:40 +02:00
{
if ( selectedfov < 80 )
{
selectedfov = 80 ;
}
else if ( selectedfov > 80 )
{
selectedfov = 80 ;
}
}
*/
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = = = =
CalcRoll
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
= = = = = = = = = = = = = = =
*/
float Player : : CalcRoll ( void )
{
float sign ;
float side ;
float value ;
Vector l ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
angles . AngleVectors ( NULL , & l , NULL ) ;
side = velocity * l ;
sign = side < 0 ? 4 : - 4 ;
side = fabs ( side ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
value = sv_rollangle - > value ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( side < sv_rollspeed - > value ) {
side = side * value / sv_rollspeed - > value ;
} else {
side = value ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return side * sign ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// PMove Events
//
void Player : : ProcessPmoveEvents ( int event )
{
float damage ;
switch ( event ) {
case EV_NONE :
break ;
case EV_FALL_SHORT :
case EV_FALL_MEDIUM :
case EV_FALL_FAR :
case EV_FALL_FATAL :
if ( event = = EV_FALL_FATAL ) {
2023-08-11 01:58:15 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
damage = 101 ;
2023-08-11 00:53:21 +02:00
} else {
damage = max_health + 1.0f ;
}
2023-08-04 00:04:29 +02:00
} else if ( event = = EV_FALL_FAR ) {
2023-08-11 01:58:15 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
damage = 25 ;
2023-08-11 00:53:21 +02:00
} else {
damage = 20 ;
}
2023-08-04 00:04:29 +02:00
} else if ( event = = EV_FALL_MEDIUM ) {
2023-08-11 01:58:15 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
damage = 15 ;
2023-08-11 00:53:21 +02:00
} else {
damage = 10 ;
}
2023-08-04 00:04:29 +02:00
} else {
damage = 5 ;
}
2023-08-28 15:49:28 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
// since 2.0, remove a percentage of the health
damage = damage * ( max_health / 100.0 ) ;
}
if ( g_gametype - > integer = = GT_SINGLE_PLAYER | | ! DM_FLAG ( DF_NO_FALLING ) ) {
Damage ( this , this , ( int ) damage , origin , vec_zero , vec_zero , 0 , DAMAGE_NO_ARMOR , MOD_FALLING ) ;
2023-08-04 00:04:29 +02:00
}
break ;
case EV_TERMINAL_VELOCITY :
Sound ( " snd_fall " , CHAN_VOICE ) ;
break ;
case EV_WATER_LEAVE : // foot leaves
Sound ( " impact_playerleavewater " , CHAN_AUTO ) ;
break ;
case EV_WATER_UNDER : // head touches
Sound ( " impact_playersubmerge " , CHAN_AUTO ) ;
break ;
case EV_WATER_CLEAR : // head leaves
Sound ( " snd_gasp " , CHAN_LOCAL ) ;
break ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = =
WorldEffects
= = = = = = = = = = = = =
*/
void Player : : WorldEffects ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-11 00:53:21 +02:00
if ( deadflag = = DEAD_DEAD | | getMoveType ( ) = = MOVETYPE_NOCLIP ) {
// if we are dead or no-cliping, no world effects
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// check for on fire
//
if ( on_fire ) {
if ( next_painsound_time < level . time ) {
next_painsound_time = level . time + 4 ;
Sound ( " snd_onfire " , CHAN_LOCAL ) ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = =
AddBlend
= = = = = = = = = = = = =
*/
void Player : : AddBlend ( float r , float g , float b , float a )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float a2 ;
float a3 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( a < = 0 ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// new total alpha
a2 = blend [ 3 ] + ( 1 - blend [ 3 ] ) * a ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// fraction of color from old
a3 = blend [ 3 ] / a2 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
blend [ 0 ] = blend [ 0 ] * a3 + r * ( 1 - a3 ) ;
blend [ 1 ] = blend [ 1 ] * a3 + g * ( 1 - a3 ) ;
blend [ 2 ] = blend [ 2 ] * a3 + b * ( 1 - a3 ) ;
blend [ 3 ] = a2 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = =
CalcBlend
= = = = = = = = = = = = =
*/
void Player : : CalcBlend ( void )
{
int contents ;
Vector vieworg ;
client - > ps . stats [ STAT_ADDFADE ] = 0 ;
blend [ 0 ] = blend [ 1 ] = blend [ 2 ] = blend [ 3 ] = 0 ;
// add for contents
vieworg = m_vViewPos ;
2023-08-15 01:27:35 +02:00
contents = gi . pointcontents ( vieworg , 0 ) ;
2023-08-04 00:04:29 +02:00
if ( contents & CONTENTS_SOLID ) {
// Outside of world
//AddBlend( 0.8, 0.5, 0.0, 0.2 );
} else if ( contents & CONTENTS_LAVA ) {
AddBlend ( level . lava_color [ 0 ] , level . lava_color [ 1 ] , level . lava_color [ 2 ] , level . lava_alpha ) ;
} else if ( contents & CONTENTS_WATER ) {
AddBlend ( level . water_color [ 0 ] , level . water_color [ 1 ] , level . water_color [ 2 ] , level . water_alpha ) ;
}
// add for damage
if ( damage_alpha > 0 ) {
AddBlend ( damage_blend [ 0 ] , damage_blend [ 1 ] , damage_blend [ 2 ] , damage_alpha ) ;
// drop the damage value
damage_alpha - = 0.06f ;
if ( damage_alpha < 0 ) {
damage_alpha = 0 ;
}
client - > ps . blend [ 0 ] = blend [ 0 ] ;
client - > ps . blend [ 1 ] = blend [ 1 ] ;
client - > ps . blend [ 2 ] = blend [ 2 ] ;
client - > ps . blend [ 3 ] = blend [ 3 ] ;
}
// Do the cinematic fading
float alpha = 1 ;
level . m_fade_time - = level . frametime ;
// Return if we are completely faded in
if ( ( level . m_fade_time < = 0 ) & & ( level . m_fade_type = = fadein ) ) {
client - > ps . blend [ 3 ] = 0 + damage_alpha ;
return ;
}
// If we are faded out, and another fade out is coming in, then don't bother
if ( ( level . m_fade_time_start > 0 ) & & ( level . m_fade_type = = fadeout ) ) {
if ( client - > ps . blend [ 3 ] > = 1 ) {
return ;
}
}
if ( level . m_fade_time_start > 0 ) {
alpha = level . m_fade_time / level . m_fade_time_start ;
}
if ( level . m_fade_type = = fadeout ) {
alpha = 1.0f - alpha ;
}
if ( alpha < 0 ) {
alpha = 0 ;
}
if ( alpha > 1 ) {
alpha = 1 ;
}
if ( level . m_fade_style = = additive ) {
client - > ps . blend [ 0 ] = level . m_fade_color [ 0 ] * level . m_fade_alpha * alpha ;
client - > ps . blend [ 1 ] = level . m_fade_color [ 1 ] * level . m_fade_alpha * alpha ;
client - > ps . blend [ 2 ] = level . m_fade_color [ 2 ] * level . m_fade_alpha * alpha ;
client - > ps . blend [ 3 ] = level . m_fade_alpha * alpha ;
client - > ps . stats [ STAT_ADDFADE ] = 1 ;
} else {
client - > ps . blend [ 0 ] = level . m_fade_color [ 0 ] ;
client - > ps . blend [ 1 ] = level . m_fade_color [ 1 ] ;
client - > ps . blend [ 2 ] = level . m_fade_color [ 2 ] ;
client - > ps . blend [ 3 ] = level . m_fade_alpha * alpha ;
client - > ps . stats [ STAT_ADDFADE ] = 0 ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = = = =
P_DamageFeedback
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Handles color blends and view kicks
= = = = = = = = = = = = = = =
*/
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : DamageFeedback ( void )
{
2023-08-11 01:58:15 +02:00
float realcount ;
float count ;
vec3_t vDir ;
str painAnim ;
int animnum ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// if we are dead, don't setup any feedback
2023-08-11 01:21:50 +02:00
if ( IsDead ( ) ) {
2023-08-04 00:04:29 +02:00
damage_count = 0 ;
damage_blood = 0 ;
damage_alpha = 0 ;
VectorClear ( damage_angles ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-11 01:58:15 +02:00
if ( damage_count ) {
// decay damage_count over time
2023-08-11 01:21:50 +02:00
damage_count * = 0.8f ;
damage_from * = 0.8f ;
damage_angles * = 0.8f ;
if ( damage_count < 0.1f ) {
2023-08-11 01:58:15 +02:00
damage_count = 0 ;
damage_from = Vector ( 0 , 0 , 0 ) ;
2023-08-04 00:04:29 +02:00
}
2023-08-11 01:58:15 +02:00
}
2023-08-04 00:04:29 +02:00
2023-08-11 01:58:15 +02:00
// total points of damage shot at the player this frame
if ( ! damage_blood ) {
// didn't take any damage
return ;
}
2023-08-04 00:04:29 +02:00
2023-08-11 01:58:15 +02:00
VectorNormalize2 ( damage_from , vDir ) ;
2023-08-04 00:04:29 +02:00
2023-08-11 01:58:15 +02:00
damage_angles . x - =
DotProduct ( vDir , orientation [ 0 ] ) * damage_blood * g_viewkick_pitch - > value * g_viewkick_dmmult - > value ;
damage_angles . x = Q_clamp_float ( damage_angles . x , - 30 , 30 ) ;
2023-08-04 00:04:29 +02:00
2023-08-11 01:58:15 +02:00
damage_angles . y - =
DotProduct ( vDir , orientation [ 1 ] ) * damage_blood * g_viewkick_yaw - > value * g_viewkick_dmmult - > value ;
damage_angles . y = Q_clamp_float ( damage_angles . y , - 30 , 30 ) ;
2023-08-04 00:04:29 +02:00
2023-08-11 01:58:15 +02:00
damage_angles . z + =
DotProduct ( vDir , orientation [ 2 ] ) * damage_blood * g_viewkick_roll - > value * g_viewkick_dmmult - > value ;
damage_angles . z = Q_clamp_float ( damage_angles . y , - 25 , 25 ) ;
2023-08-11 01:21:50 +02:00
2023-08-11 01:58:15 +02:00
damage_count + = damage_blood ;
count = damage_blood ;
realcount = count ;
if ( count < 10 ) {
// always make a visible effect
count = 10 ;
}
2023-08-04 00:04:29 +02:00
// the total alpha of the blend is always proportional to count
if ( damage_alpha < 0 ) {
damage_alpha = 0 ;
}
damage_alpha + = count * 0.001 ;
if ( damage_alpha < 0.2f ) {
damage_alpha = 0.2f ;
}
if ( damage_alpha > 0.6f ) {
// don't go too saturated
damage_alpha = 0.6f ;
}
// the color of the blend will vary based on how much was absorbed
// by different armors
damage_blend = vec_zero ;
if ( damage_blood ) {
damage_blend + = ( damage_blood / realcount ) * bcolor ;
}
2024-02-04 15:47:48 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
//
// Since 2.0: Try to find and play pain animation
//
if ( getMoveType ( ) = = MOVETYPE_PORTABLE_TURRET ) {
// use mg42 pain animation
painAnim = " mg42_tripod_ " ;
} else {
Weapon * pWeap ;
const char * itemName ;
// try to find an animation
2023-08-11 01:58:15 +02:00
2024-02-04 15:47:48 +01:00
pWeap = GetActiveWeapon ( WEAPON_MAIN ) ;
if ( pWeap ) {
int weapon_class ;
weapon_class = pWeap - > GetWeaponClass ( ) ;
if ( weapon_class & WEAPON_CLASS_PISTOL ) {
painAnim = " pistol_ " ;
} else if ( weapon_class & WEAPON_CLASS_RIFLE ) {
painAnim = " rifle_ " ;
} else if ( weapon_class & WEAPON_CLASS_SMG ) {
// get the animation name from the item name
itemName = pWeap - > GetItemName ( ) ;
if ( ! Q_stricmp ( itemName , " MP40 " ) ) {
painAnim = " mp40_ " ;
} else if ( ! Q_stricmp ( itemName , " Sten Mark II " ) ) {
painAnim = " sten_ " ;
} else {
painAnim = " smg_ " ;
}
} else if ( weapon_class & WEAPON_CLASS_MG ) {
itemName = pWeap - > GetItemName ( ) ;
2023-08-11 01:58:15 +02:00
2024-02-04 15:47:48 +01:00
if ( ! Q_stricmp ( itemName , " StG 44 " ) ) {
painAnim = " mp44_ " ;
} else {
painAnim = " mg_ " ;
}
} else if ( weapon_class & WEAPON_CLASS_GRENADE ) {
itemName = pWeap - > GetItemName ( ) ;
// 2.30: use landmine animations
if ( ! Q_stricmp ( itemName , " Minedetector " ) ) {
painAnim = " minedetector_ " ;
} else if ( ! Q_stricmp ( itemName , " Minensuchgerat " ) ) {
painAnim = " minedetectoraxis_ " ;
} else if ( ! Q_stricmp ( itemName , " LandmineAllies " ) ) {
painAnim = " mine_ " ;
} else if ( ! Q_stricmp ( itemName , " LandmineAxis " ) ) {
painAnim = " mine_ " ;
} else if ( ! Q_stricmp ( itemName , " LandmineAxis " ) ) {
painAnim = " grenade_ " ;
}
} else if ( weapon_class & WEAPON_CLASS_HEAVY ) {
itemName = pWeap - > GetItemName ( ) ;
2023-08-11 01:58:15 +02:00
2024-02-04 15:47:48 +01:00
if ( ! Q_stricmp ( itemName , " Shotgun " ) ) {
painAnim = " shotgun_ " ;
} else {
// Defaults to bazooka
painAnim = " bazooka_ " ;
}
2023-08-11 01:58:15 +02:00
} else {
2024-02-04 15:47:48 +01:00
itemName = pWeap - > GetItemName ( ) ;
if ( ! Q_stricmp ( itemName , " Packed MG42 Turret " ) ) {
painAnim = " mg42_ " ;
} else {
// Default animation if not found
painAnim = " unarmed_ " ;
}
2023-08-11 01:58:15 +02:00
}
} else {
2024-02-04 15:47:48 +01:00
painAnim = " unarmed_ " ;
}
2023-08-11 01:58:15 +02:00
2024-02-04 15:47:48 +01:00
// use the animation based on the movement
if ( m_iMovePosFlags & MPF_POSITION_CROUCHING ) {
painAnim + = " crouch_ " ;
} else {
painAnim + = " stand_ " ;
2023-08-11 01:58:15 +02:00
}
}
2024-02-04 15:47:48 +01:00
painAnim + = " hit_ " ;
if ( pain_dir = = PAIN_REAR | | pain_location = = HITLOC_TORSO_MID | | HITLOC_TORSO_LOWER ) {
painAnim + = " back " ;
2023-08-11 01:58:15 +02:00
} else {
2024-02-04 15:47:48 +01:00
switch ( pain_location ) {
case HITLOC_HEAD :
case HITLOC_HELMET :
case HITLOC_NECK :
painAnim + = " head " ;
break ;
case HITLOC_TORSO_UPPER :
case HITLOC_TORSO_MID :
painAnim + = " uppertorso " ;
break ;
case HITLOC_TORSO_LOWER :
case HITLOC_PELVIS :
painAnim + = " lowertorso " ;
break ;
case HITLOC_R_ARM_UPPER :
case HITLOC_R_ARM_LOWER :
case HITLOC_R_HAND :
painAnim + = " rarm " ;
break ;
case HITLOC_L_ARM_UPPER :
case HITLOC_L_ARM_LOWER :
case HITLOC_L_HAND :
painAnim + = " larm " ;
break ;
case HITLOC_R_LEG_UPPER :
case HITLOC_L_LEG_UPPER :
case HITLOC_R_LEG_LOWER :
case HITLOC_L_LEG_LOWER :
case HITLOC_R_FOOT :
case HITLOC_L_FOOT :
painAnim + = " leg " ;
break ;
default :
painAnim + = " uppertorso " ;
break ;
}
2023-08-11 01:58:15 +02:00
}
2024-02-04 15:47:48 +01:00
animnum = gi . Anim_NumForName ( edict - > tiki , painAnim . c_str ( ) ) ;
if ( animnum = = - 1 ) {
gi . DPrintf ( " WARNING: Could not find player pain animation '%s' \n " , painAnim . c_str ( ) ) ;
} else {
NewAnim ( animnum , EV_Player_AnimLoop_Pain , ANIMSLOT_PAIN ) ;
RestartAnimSlot ( ANIMSLOT_PAIN ) ;
m_sPainAnim = painAnim ;
m_fPainBlend = 1.f ;
animdone_Pain = false ;
2023-08-11 01:58:15 +02:00
}
}
2023-08-04 00:04:29 +02:00
//
// clear totals
//
damage_blood = 0 ;
2023-08-11 01:58:15 +02:00
2024-07-27 19:45:11 +02:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
//
// Added in 2.0
// No more damage angles since MOHTA
//
if ( IsSubclassOfPlayer ( ) ) {
damage_count = 0 ;
damage_blood = 0 ;
damage_alpha = 0 ;
damage_angles = vec_zero ;
}
2023-08-11 01:58:15 +02:00
}
2023-08-04 00:04:29 +02:00
}
void Player : : GetPlayerView ( Vector * pos , Vector * angle )
{
if ( pos ) {
* pos = origin ;
pos - > z + = viewheight ;
}
if ( angle ) {
* angle = Vector ( client - > ps . viewangles ) ;
}
}
void Player : : SetPlayerView (
Camera * camera , Vector position , float cameraoffset , Vector ang , Vector vel , float camerablend [ 4 ] , float camerafov
)
{
2023-10-13 19:35:29 +02:00
VectorCopy ( ang , client - > ps . viewangles ) ;
2023-11-03 21:56:31 +01:00
client - > ps . viewheight = cameraoffset ;
2016-03-27 11:49:47 +02:00
2023-10-13 19:35:29 +02:00
VectorCopy ( position , client - > ps . origin ) ;
VectorCopy ( vel , client - > ps . velocity ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/*
2023-08-10 14:18:40 +02:00
client - > ps . blend [ 0 ] = camerablend [ 0 ] ;
client - > ps . blend [ 1 ] = camerablend [ 1 ] ;
client - > ps . blend [ 2 ] = camerablend [ 2 ] ;
client - > ps . blend [ 3 ] = camerablend [ 3 ] ;
*/
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . fov = camerafov ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( camera ) {
if ( camera - > IsSubclassOfCamera ( ) ) {
2023-10-13 19:35:29 +02:00
VectorCopy ( camera - > angles , client - > ps . camera_angles ) ;
VectorCopy ( camera - > origin , client - > ps . camera_origin ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Vector vOfs = camera - > GetPositionOffset ( ) ;
VectorCopy ( vOfs , client - > ps . camera_posofs ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . pm_flags | = PMF_CAMERA_VIEW ;
2016-03-27 11:49:47 +02:00
2023-10-13 19:35:29 +02:00
if ( camera - > ShowQuakes ( ) ) {
client - > ps . pm_flags | = PMF_DAMAGE_ANGLES ;
} else {
client - > ps . pm_flags & = ~ PMF_DAMAGE_ANGLES ;
}
2023-08-04 00:04:29 +02:00
//
// clear out the flags, but preserve the CF_CAMERA_CUT_BIT
//
client - > ps . camera_flags = client - > ps . camera_flags & CF_CAMERA_CUT_BIT ;
2023-10-13 19:35:29 +02:00
} else {
Vector vVec ;
if ( camera - > IsSubclassOfPlayer ( ) ) {
Vector vPos ;
2023-11-03 21:56:31 +01:00
Player * pPlayer = ( Player * ) camera ;
2016-03-27 11:49:47 +02:00
2023-10-13 19:35:29 +02:00
GetSpectateFollowOrientation ( pPlayer , vPos , vVec ) ;
2016-03-27 11:49:47 +02:00
2023-10-13 19:35:29 +02:00
VectorCopy ( vVec , client - > ps . camera_angles ) ;
VectorCopy ( vPos , client - > ps . camera_origin ) ;
2016-03-27 11:49:47 +02:00
2023-10-13 19:35:29 +02:00
SetViewAngles ( vVec ) ;
2023-08-04 00:04:29 +02:00
2023-10-13 19:35:29 +02:00
vPos [ 2 ] - = viewheight ;
setOrigin ( vPos ) ;
vVec . setXYZ ( 0 , 0 , 0 ) ;
} else {
VectorCopy ( ang , client - > ps . camera_angles ) ;
VectorCopy ( position , client - > ps . camera_angles ) ;
vVec . setXYZ ( 0 , 0 , 0 ) ;
}
VectorCopy ( vVec , client - > ps . camera_posofs ) ;
2023-08-04 00:04:29 +02:00
client - > ps . pm_flags | = PMF_CAMERA_VIEW ;
2023-08-10 13:31:35 +02:00
client - > ps . camera_flags = client - > ps . camera_flags & CF_CAMERA_CUT_BIT ;
2023-08-04 00:04:29 +02:00
}
} else {
client - > ps . pm_flags & = ~ PMF_CAMERA_VIEW ;
//
// make sure the third person camera is setup correctly.
//
if ( getMoveType ( ) ! = MOVETYPE_NOCLIP ) {
qboolean do_cut ;
int camera_type ;
2023-10-13 19:35:29 +02:00
if ( currentState_Torso ) {
camera_type = currentState_Torso - > getCameraType ( ) ;
} else {
camera_type = CAMERA_BEHIND ;
}
2023-08-04 00:04:29 +02:00
if ( last_camera_type ! = camera_type ) {
//
// clear out the flags, but preserve the CF_CAMERA_CUT_BIT
//
client - > ps . camera_flags = client - > ps . camera_flags & CF_CAMERA_CUT_BIT ;
do_cut = qtrue ;
switch ( camera_type ) {
case CAMERA_TOPDOWN :
client - > ps . camera_flags | = CF_CAMERA_ANGLES_IGNORE_PITCH ;
client - > ps . camera_offset [ PITCH ] = - 75 ;
client - > ps . camera_flags | = CF_CAMERA_ANGLES_ALLOWOFFSET ;
do_cut = qfalse ;
break ;
case CAMERA_FRONT :
client - > ps . camera_flags | = CF_CAMERA_ANGLES_IGNORE_PITCH ;
client - > ps . camera_flags | = CF_CAMERA_ANGLES_ALLOWOFFSET ;
client - > ps . camera_offset [ YAW ] = 180 ;
client - > ps . camera_offset [ PITCH ] = 0 ;
break ;
case CAMERA_SIDE :
client - > ps . camera_flags | = CF_CAMERA_ANGLES_IGNORE_PITCH ;
client - > ps . camera_flags | = CF_CAMERA_ANGLES_ALLOWOFFSET ;
// randomly invert the YAW
if ( G_Random ( 1 ) > 0.5f ) {
client - > ps . camera_offset [ YAW ] = - 90 ;
} else {
client - > ps . camera_offset [ YAW ] = 90 ;
}
client - > ps . camera_offset [ PITCH ] = 0 ;
break ;
case CAMERA_SIDE_LEFT :
client - > ps . camera_flags | = CF_CAMERA_ANGLES_IGNORE_PITCH ;
client - > ps . camera_flags | = CF_CAMERA_ANGLES_ALLOWOFFSET ;
client - > ps . camera_offset [ YAW ] = 90 ;
client - > ps . camera_offset [ PITCH ] = 0 ;
break ;
case CAMERA_SIDE_RIGHT :
client - > ps . camera_flags | = CF_CAMERA_ANGLES_IGNORE_PITCH ;
client - > ps . camera_flags | = CF_CAMERA_ANGLES_ALLOWOFFSET ;
client - > ps . camera_offset [ YAW ] = - 90 ;
client - > ps . camera_offset [ PITCH ] = 0 ;
break ;
case CAMERA_BEHIND_FIXED :
do_cut = qfalse ;
client - > ps . camera_offset [ YAW ] = 0 ;
client - > ps . camera_offset [ PITCH ] = 0 ;
client - > ps . camera_flags | = CF_CAMERA_ANGLES_ALLOWOFFSET ;
break ;
case CAMERA_BEHIND_NOPITCH :
do_cut = qfalse ;
client - > ps . camera_flags | = CF_CAMERA_ANGLES_IGNORE_PITCH ;
client - > ps . camera_offset [ YAW ] = 0 ;
client - > ps . camera_offset [ PITCH ] = 0 ;
break ;
case CAMERA_BEHIND :
do_cut = qfalse ;
client - > ps . camera_offset [ YAW ] = 0 ;
client - > ps . camera_offset [ PITCH ] = 0 ;
break ;
default :
do_cut = qfalse ;
client - > ps . camera_offset [ YAW ] = 0 ;
client - > ps . camera_offset [ PITCH ] = 0 ;
break ;
}
last_camera_type = camera_type ;
if ( do_cut ) {
CameraCut ( ) ;
}
}
2023-10-13 19:35:29 +02:00
} else {
client - > ps . camera_flags = client - > ps . camera_flags & CF_CAMERA_CUT_BIT ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// these are explicitly not cleared so that when the client lerps it still has the last
// camera position for reference. Additionally this causes no extra hits to the network
// traffic.
//
//VectorClear( client->ps.camera_angles );
//VectorClear( client->ps.camera_origin );
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
# define EARTHQUAKE_SCREENSHAKE_PITCH 2
# define EARTHQUAKE_SCREENSHAKE_YAW 2
# define EARTHQUAKE_SCREENSHAKE_ROLL 3
2023-08-11 03:13:36 +02:00
if ( level . earthquake_magnitude ! = 0.0f ) {
2023-08-04 00:04:29 +02:00
client - > ps . damage_angles [ PITCH ] = G_CRandom ( ) * level . earthquake_magnitude * EARTHQUAKE_SCREENSHAKE_PITCH ;
client - > ps . damage_angles [ YAW ] = G_CRandom ( ) * level . earthquake_magnitude * EARTHQUAKE_SCREENSHAKE_YAW ;
client - > ps . damage_angles [ ROLL ] = G_CRandom ( ) * level . earthquake_magnitude * EARTHQUAKE_SCREENSHAKE_ROLL ;
} else if ( damage_count ) {
2023-08-11 03:13:36 +02:00
client - > ps . damage_angles [ PITCH ] = damage_angles [ PITCH ] ;
client - > ps . damage_angles [ YAW ] = damage_angles [ YAW ] ;
2023-08-13 16:11:25 +02:00
client - > ps . damage_angles [ ROLL ] = damage_angles [ ROLL ] ;
2023-08-04 00:04:29 +02:00
} else {
VectorClear ( client - > ps . damage_angles ) ;
}
if ( m_vViewVariation ! = vec_zero ) {
for ( int i = 0 ; i < 3 ; i + + ) {
if ( m_vViewVariation [ i ] = = 0.0f ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
client - > ps . damage_angles [ i ] + = G_CRandom ( ) * m_vViewVariation [ i ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_vViewVariation [ i ] = m_vViewVariation [ i ] - m_vViewVariation [ i ] * level . frametime * 8.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_vViewVariation [ i ] < 0.01f ) {
m_vViewVariation [ i ] = 0.0f ;
}
}
}
}
void Player : : SetupView ( void )
{
// if we currently are not in a camera or the camera we are looking through is automatic, evaluate our camera choices
if ( actor_to_watch | | actor_camera ) {
Vector dir ;
Vector watch_angles ;
float dist = 0 ;
Vector focal_point ;
Vector left ;
trace_t trace ;
qboolean delete_actor_camera = false ;
Vector camera_mins ;
Vector camera_maxs ;
if ( actor_to_watch ) {
dir = actor_to_watch - > origin - origin ;
dist = dir . length ( ) ;
}
// See if we still want to watch this actor
if ( ! actor_to_watch | | dist > 150 | | actor_to_watch - > deadflag ) {
delete_actor_camera = true ;
} else {
// Create the camera if we don't have one yet
if ( ! actor_camera ) {
actor_camera = new Camera ( ) ;
if ( G_Random ( ) < .5 ) {
actor_camera_right = true ;
starting_actor_camera_right = true ;
} else {
actor_camera_right = false ;
starting_actor_camera_right = false ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Setup the new position of the actor camera
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Go a little above the view height
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
actor_camera - > origin = origin ;
actor_camera - > origin [ 2 ] + = DEFAULT_VIEWHEIGHT + 10 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Find the focal point ( either the actor's watch offset or top of the bounding box)
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( actor_to_watch - > watch_offset ! = vec_zero ) {
MatrixTransformVector ( actor_to_watch - > watch_offset , actor_to_watch - > orientation , focal_point ) ;
focal_point + = actor_to_watch - > origin ;
} else {
focal_point = actor_to_watch - > origin ;
focal_point [ 2 ] = actor_to_watch - > maxs [ 2 ] ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Shift the camera back just a little
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
dir = focal_point - actor_camera - > origin ;
dir . normalize ( ) ;
actor_camera - > origin - = dir * 15 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Shift the camera a little to the left or right
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
watch_angles = dir . toAngles ( ) ;
watch_angles . AngleVectors ( NULL , & left ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( actor_camera_right ) {
actor_camera - > origin - = left * 15 ;
} else {
actor_camera - > origin + = left * 15 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Make sure this camera position is ok
camera_mins = " -5 -5 -5 " ;
camera_maxs = " 5 5 5 " ;
trace = G_Trace (
actor_camera - > origin ,
camera_mins ,
camera_maxs ,
actor_camera - > origin ,
actor_camera ,
MASK_DEADSOLID ,
false ,
" SetupView "
) ;
if ( trace . startsolid ) {
// Try other side
if ( actor_camera_right = = starting_actor_camera_right ) {
if ( actor_camera_right ) {
actor_camera - > origin + = left * 30 ;
} else {
actor_camera - > origin - = left * 30 ;
}
actor_camera_right = ! actor_camera_right ;
trace = G_Trace (
actor_camera - > origin ,
camera_mins ,
camera_maxs ,
actor_camera - > origin ,
actor_camera ,
MASK_DEADSOLID ,
false ,
" SetupView2 "
) ;
if ( trace . startsolid ) {
// Both spots have failed stop doing actor camera
delete_actor_camera = true ;
}
} else {
// Both spots have failed stop doing actor camera
delete_actor_camera = true ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! delete_actor_camera ) {
// Set the camera's position
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
actor_camera - > setOrigin ( actor_camera - > origin ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Set the camera's angles
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
dir = focal_point - actor_camera - > origin ;
watch_angles = dir . toAngles ( ) ;
actor_camera - > setAngles ( watch_angles ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Set this as our camera
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetCamera ( actor_camera , .5 ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( delete_actor_camera ) {
// Get rid of this camera
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
actor_to_watch = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( actor_camera ) {
delete actor_camera ;
actor_camera = NULL ;
SetCamera ( NULL , .5 ) ;
}
}
} else if ( ( level . automatic_cameras . NumObjects ( ) > 0 ) & & ( ! camera | | camera - > IsAutomatic ( ) ) ) {
int i ;
float score , bestScore ;
Camera * cam , * bestCamera ;
bestScore = 999 ;
bestCamera = NULL ;
for ( i = 1 ; i < = level . automatic_cameras . NumObjects ( ) ; i + + ) {
cam = level . automatic_cameras . ObjectAt ( i ) ;
score = cam - > CalculateScore ( this , currentState_Torso - > getName ( ) ) ;
// if this is our current camera, scale down the score a bit to favor it.
if ( cam = = camera ) {
score * = 0.9f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( score < bestScore ) {
bestScore = score ;
bestCamera = cam ;
}
}
if ( bestScore < = 1.0f ) {
// we have a camera to switch to
if ( bestCamera ! = camera ) {
float time ;
if ( camera ) {
camera - > AutomaticStop ( this ) ;
}
time = bestCamera - > AutomaticStart ( this ) ;
SetCamera ( bestCamera , time ) ;
}
} else {
// we don't have a camera to switch to
if ( camera ) {
float time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
time = camera - > AutomaticStop ( this ) ;
SetCamera ( NULL , time ) ;
}
}
}
2023-08-13 16:11:25 +02:00
2023-08-04 00:04:29 +02:00
// If there is no camera, use the player's view
2023-08-13 16:11:25 +02:00
if ( ! camera ) {
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & IsSpectator ( ) & & m_iPlayerSpectating ! = 0 ) {
gentity_t * ent = g_entities + m_iPlayerSpectating - 1 ;
if ( ent - > inuse & & ent - > entity & & ent - > entity - > deadflag < = DEAD_DYING ) {
Player * m_player = ( Player * ) ent - > entity ;
Vector vAngles ;
m_player - > GetPlayerView ( NULL , & vAngles ) ;
SetPlayerView (
( Camera * ) m_player ,
m_player - > origin ,
m_player - > viewheight ,
vAngles ,
m_player - > velocity ,
blend ,
m_player - > fov
) ;
} else {
2023-08-11 03:13:36 +02:00
SetPlayerView ( NULL , origin , viewheight , v_angle , velocity , blend , fov ) ;
}
2023-08-13 16:11:25 +02:00
} else {
2023-08-11 03:13:36 +02:00
SetPlayerView ( NULL , origin , viewheight , v_angle , velocity , blend , fov ) ;
}
2023-08-04 00:04:29 +02:00
} else {
SetPlayerView ( camera , origin , viewheight , v_angle , velocity , blend , camera - > Fov ( ) ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
Vector Player : : GetAngleToTarget ( Entity * ent , str tag , float yawclamp , float pitchclamp , Vector baseangles )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
assert ( ent ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ent ) {
Vector delta , angs ;
orientation_t tag_or ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
int tagnum = gi . Tag_NumForName ( edict - > tiki , tag . c_str ( ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( tagnum < 0 ) {
return Vector ( 0 , 0 , 0 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
GetTagPositionAndOrientation ( tagnum , & tag_or ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
delta = ent - > centroid - tag_or . origin ;
delta . normalize ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
angs = delta . toAngles ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AnglesSubtract ( angs , baseangles , angs ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
angs [ PITCH ] = AngleNormalize180 ( angs [ PITCH ] ) ;
angs [ YAW ] = AngleNormalize180 ( angs [ YAW ] ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( angs [ PITCH ] > pitchclamp ) {
angs [ PITCH ] = pitchclamp ;
} else if ( angs [ PITCH ] < - pitchclamp ) {
angs [ PITCH ] = - pitchclamp ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( angs [ YAW ] > yawclamp ) {
angs [ YAW ] = yawclamp ;
} else if ( angs [ YAW ] < - yawclamp ) {
angs [ YAW ] = - yawclamp ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return angs ;
} else {
return Vector ( 0 , 0 , 0 ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : DebugWeaponTags ( int controller_tag , Weapon * weapon , str weapon_tagname )
{
int i ;
orientation_t bone_or , tag_weapon_or , barrel_or , final_barrel_or ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
GetTagPositionAndOrientation ( edict - > s . bone_tag [ controller_tag ] , & bone_or ) ;
//G_DrawCoordSystem( Vector( bone_or.origin ), Vector( bone_or.axis[0] ), Vector( bone_or.axis[1] ), Vector( bone_or.axis[2] ), 20 );
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
GetTagPositionAndOrientation ( gi . Tag_NumForName ( edict - > tiki , weapon_tagname ) , & tag_weapon_or ) ;
//G_DrawCoordSystem( Vector( tag_weapon_or.origin ), Vector( tag_weapon_or.axis[0] ), Vector( tag_weapon_or.axis[1] ), Vector( tag_weapon_or.axis[2] ), 40 );
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
weapon - > GetRawTag ( " tag_barrel " , & barrel_or ) ;
VectorCopy ( tag_weapon_or . origin , final_barrel_or . origin ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( i = 0 ; i < 3 ; i + + ) {
VectorMA ( final_barrel_or . origin , barrel_or . origin [ i ] , tag_weapon_or . axis [ i ] , final_barrel_or . origin ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
MatrixMultiply ( barrel_or . axis , tag_weapon_or . axis , final_barrel_or . axis ) ;
//G_DrawCoordSystem( Vector( final_barrel_or.origin ), Vector( final_barrel_or.axis[0] ), Vector( final_barrel_or.axis[1] ), Vector( final_barrel_or.axis[2] ), 80 );
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
#if 0
if ( g_crosshair - > integer )
{
trace_t trace ;
Vector start , end , ang , dir , delta ;
vec3_t mat [ 3 ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AnglesToAxis ( v_angle , mat ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
dir = mat [ 0 ] ;
start = final_barrel_or . origin ;
end = start + ( dir * MAX_MAP_BOUNDS ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
G_DrawCoordSystem ( start , Vector ( mat [ 0 ] ) , Vector ( mat [ 1 ] ) , Vector ( mat [ 2 ] ) , 80 ) ;
trace = G_Trace ( start , vec_zero , vec_zero , end , this , MASK_PROJECTILE | MASK_WATER , qfalse , " Crosshair " ) ;
crosshair - > setOrigin ( trace . endpos ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
delta = trace . endpos - start ;
float length = delta . length ( ) ;
float scale = g_crosshair_maxscale - > value * length / MAX_MAP_BOUNDS ;
if ( scale < 1 )
scale = 1 ;
crosshair - > setScale ( scale ) ;
if ( trace . ent )
{
vectoangles ( trace . plane . normal , ang ) ;
}
else
{
vectoangles ( dir , ang ) ;
}
crosshair - > setAngles ( ang ) ;
}
# endif
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : AcquireTarget ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : RemoveTarget ( Entity * ent_to_remove ) { }
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : AutoAim ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = = = =
PlayerAngles
= = = = = = = = = = = = = = =
*/
void Player : : PlayerAngles ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-13 16:11:25 +02:00
if ( getMoveType ( ) = = MOVETYPE_PORTABLE_TURRET ) {
2023-11-03 21:56:31 +01:00
PortableTurret * portableTurret = static_cast < PortableTurret * > ( m_pTurret . Pointer ( ) ) ;
angles [ 0 ] = portableTurret - > GetGroundPitch ( ) ;
angles [ 1 ] = portableTurret - > GetStartYaw ( ) ;
2023-08-11 03:13:36 +02:00
}
2023-08-04 00:04:29 +02:00
PmoveAdjustAngleSettings ( v_angle , angles , & client - > ps , & edict - > s ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetViewAngles ( v_angle ) ;
setAngles ( angles ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : FinishMove ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
//
// If the origin or velocity have changed since ClientThink(),
// update the pmove values. This will happen when the client
// is pushed by a bmodel or kicked by an explosion.
//
// If it wasn't updated here, the view position would lag a frame
// behind the body position when pushed -- "sinking into plats",
//
if ( ! ( client - > ps . pm_flags & PMF_FROZEN ) & & ! ( client - > ps . pm_flags & PMF_NO_MOVE ) ) {
origin . copyTo ( client - > ps . origin ) ;
velocity . copyTo ( client - > ps . velocity ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// This check is in mohaa but the animation will look bad
if ( ! ( client - > ps . pm_flags & PMF_FROZEN ) ) {
PlayerAngles ( ) ;
AdjustAnimBlends ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// burn from lava, etc
WorldEffects ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// determine the view offsets
DamageFeedback ( ) ;
CalcBlend ( ) ;
2016-03-27 11:49:47 +02:00
2024-10-07 00:51:01 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & g_smoothClients - > integer ) {
2023-08-04 00:04:29 +02:00
VectorCopy ( client - > ps . velocity , edict - > s . pos . trDelta ) ;
edict - > s . pos . trTime = client - > ps . commandTime ;
} else {
VectorClear ( edict - > s . pos . trDelta ) ;
edict - > s . pos . trTime = 0 ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : CopyStats ( Player * player )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
gentity_t * ent ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
origin = player - > origin ;
SetViewAngles ( player - > GetViewAngles ( ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . bobCycle = player - > client - > ps . bobCycle ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . pm_flags | =
player - > client - > ps . pm_flags & ( PMF_DUCKED | PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START | PMF_VIEW_PRONE ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
memcpy ( & client - > ps . stats , & player - > client - > ps . stats , sizeof ( client - > ps . stats ) ) ;
memcpy ( & client - > ps . activeItems , & player - > client - > ps . activeItems , sizeof ( client - > ps . activeItems ) ) ;
memcpy ( & client - > ps . ammo_name_index , & player - > client - > ps . ammo_name_index , sizeof ( client - > ps . ammo_name_index ) ) ;
memcpy ( & client - > ps . ammo_amount , & player - > client - > ps . ammo_amount , sizeof ( client - > ps . ammo_amount ) ) ;
memcpy ( & client - > ps . max_ammo_amount , & player - > client - > ps . max_ammo_amount , sizeof ( client - > ps . max_ammo_amount ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
VectorCopy ( player - > client - > ps . origin , client - > ps . origin ) ;
VectorCopy ( player - > client - > ps . velocity , client - > ps . velocity ) ;
2016-03-27 11:49:47 +02:00
2024-09-15 01:14:38 +02:00
client - > ps . iViewModelAnim = player - > client - > ps . iViewModelAnim ;
client - > ps . iViewModelAnimChanged = player - > client - > ps . iViewModelAnimChanged ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . gravity = player - > client - > ps . gravity ;
client - > ps . speed = player - > client - > ps . speed ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// copy angles
memcpy ( & client - > ps . delta_angles , & player - > client - > ps . delta_angles , sizeof ( client - > ps . delta_angles ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
memcpy ( & client - > ps . blend , & player - > client - > ps . blend , sizeof ( client - > ps . blend ) ) ;
memcpy ( & client - > ps . damage_angles , & player - > client - > ps . damage_angles , sizeof ( client - > ps . damage_angles ) ) ;
memcpy ( & client - > ps . viewangles , & player - > client - > ps . viewangles , sizeof ( client - > ps . delta_angles ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// copy camera stuff
//memcpy( &client->ps.camera_origin, &player->client->ps.camera_origin, sizeof( client->ps.camera_origin ) );
//memcpy( &client->ps.camera_angles, &player->client->ps.camera_angles, sizeof( client->ps.camera_angles ) );
//memcpy( &client->ps.camera_offset, &player->client->ps.camera_offset, sizeof( client->ps.camera_offset ) );
//memcpy( &client->ps.camera_posofs, &player->client->ps.camera_posofs, sizeof( client->ps.camera_posofs ) );
//client->ps.camera_time = player->client->ps.camera_time;
//client->ps.camera_flags = player->client->ps.camera_flags;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . fLeanAngle = player - > client - > ps . fLeanAngle ;
client - > ps . fov = player - > client - > ps . fov ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . viewheight = player - > client - > ps . viewheight ;
client - > ps . walking = player - > client - > ps . walking ;
client - > ps . groundPlane = player - > client - > ps . groundPlane ;
client - > ps . groundEntityNum = player - > client - > ps . groundEntityNum ;
memcpy ( & client - > ps . groundTrace , & player - > client - > ps . groundTrace , sizeof ( trace_t ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
edict - > s . eFlags & = ~ EF_UNARMED ;
edict - > r . svFlags & = ~ SVF_NOCLIENT ;
edict - > s . renderfx & = ~ RF_DONTDRAW ;
2016-03-27 11:49:47 +02:00
2024-09-15 01:14:38 +02:00
player - > edict - > r . svFlags | = SVF_NOTSINGLECLIENT ;
2023-08-04 00:04:29 +02:00
player - > edict - > r . singleClient = client - > ps . clientNum ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
edict - > r . svFlags | = SVF_SINGLECLIENT ;
edict - > r . singleClient = client - > ps . clientNum ;
client - > ps . pm_flags | = PMF_FROZEN | PMF_NO_MOVE | PMF_NO_PREDICTION ;
memcpy ( & edict - > s . frameInfo , & player - > edict - > s . frameInfo , sizeof ( edict - > s . frameInfo ) ) ;
2023-08-09 23:09:14 +02:00
DetachAllChildren ( NULL ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( i = 0 ; i < MAX_MODEL_CHILDREN ; i + + ) {
Entity * dest ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( player - > children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ent = g_entities + player - > children [ i ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
dest = new Entity ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
CloneEntity ( dest , ent - > entity ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
dest - > edict - > s . modelindex = ent - > entity - > edict - > s . modelindex ;
dest - > edict - > tiki = ent - > entity - > edict - > tiki ;
dest - > edict - > s . actionWeight = ent - > entity - > edict - > s . actionWeight ;
memcpy ( & dest - > edict - > s . frameInfo , & ent - > entity - > edict - > s . frameInfo , sizeof ( dest - > edict - > s . frameInfo ) ) ;
dest - > CancelPendingEvents ( ) ;
dest - > attach ( entnum , ent - > entity - > edict - > s . tag_num ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
dest - > PostEvent ( EV_DetachAllChildren , level . frametime ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : UpdateStats ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
int i , count ;
Vector vObjectiveLocation ;
2023-08-13 16:11:25 +02:00
float healthfrac ;
float healfrac ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// Health
//
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_spectatefollow_firstperson - > integer & & IsSpectator ( ) & & m_iPlayerSpectating ! = 0 ) {
2023-08-11 03:13:36 +02:00
//
2023-12-28 20:34:49 +01:00
// Added in OPM
// First-person spectate
2023-08-11 03:13:36 +02:00
//
2023-08-04 00:04:29 +02:00
gentity_t * ent = g_entities + ( m_iPlayerSpectating - 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ent - > inuse & & ent - > entity & & ent - > entity - > deadflag < = DEAD_DYING ) {
CopyStats ( ( Player * ) ent - > entity ) ;
return ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_TEAM ] = TEAM_ALLIES ;
client - > ps . stats [ STAT_KILLS ] = 0 ;
client - > ps . stats [ STAT_DEATHS ] = 0 ;
client - > ps . stats [ STAT_HIGHEST_SCORE ] = 0 ;
client - > ps . stats [ STAT_ATTACKERCLIENT ] = - 1 ;
client - > ps . stats [ STAT_INFOCLIENT ] = - 1 ;
client - > ps . stats [ STAT_INFOCLIENT_HEALTH ] = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
vObjectiveLocation = level . m_vObjectiveLocation ;
} else {
client - > ps . stats [ STAT_TEAM ] = dm_team ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( g_gametype - > integer > = GT_TEAM & & current_team ! = NULL ) {
client - > ps . stats [ STAT_KILLS ] = current_team - > m_teamwins ;
client - > ps . stats [ STAT_DEATHS ] = current_team - > m_iDeaths ;
} else {
client - > ps . stats [ STAT_KILLS ] = num_kills ;
client - > ps . stats [ STAT_DEATHS ] = num_deaths ;
}
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
if ( g_gametype - > integer < GT_TEAM ) {
2023-08-04 00:04:29 +02:00
gentity_t * ent ;
int i ;
int bestKills = - 9999 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Get the best player
for ( i = 0 , ent = g_entities ; i < game . maxclients ; i + + , ent + + ) {
if ( ! ent - > inuse | | ! ent - > client | | ! ent - > entity ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Player * p = ( Player * ) ent - > entity ;
if ( p - > GetNumKills ( ) > bestKills ) {
bestKills = p - > GetNumKills ( ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_HIGHEST_SCORE ] = bestKills ;
} else {
if ( dmManager . GetTeamAxis ( ) - > m_teamwins > dmManager . GetTeamAllies ( ) - > m_teamwins ) {
client - > ps . stats [ STAT_HIGHEST_SCORE ] = dmManager . GetTeamAxis ( ) - > m_teamwins ;
} else {
client - > ps . stats [ STAT_HIGHEST_SCORE ] = dmManager . GetTeamAllies ( ) - > m_teamwins ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! pAttackerDistPointer ) {
client - > ps . stats [ STAT_ATTACKERCLIENT ] = - 1 ;
2023-08-11 03:13:36 +02:00
} else if ( fAttackerDispTime < = level . time & & deadflag = = DEAD_NO ) {
2023-08-04 00:04:29 +02:00
pAttackerDistPointer = NULL ;
client - > ps . stats [ STAT_ATTACKERCLIENT ] = - 1 ;
} else {
client - > ps . stats [ STAT_ATTACKERCLIENT ] = pAttackerDistPointer - > edict - g_entities ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_INFOCLIENT ] = - 1 ;
client - > ps . stats [ STAT_INFOCLIENT_HEALTH ] = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
if ( IsSpectator ( ) | | g_gametype - > integer > = GT_TEAM ) {
if ( m_iPlayerSpectating & & IsSpectator ( ) ) {
2023-08-04 00:04:29 +02:00
gentity_t * ent = g_entities + ( m_iPlayerSpectating - 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
if ( ent - > inuse & & ent - > entity & & deadflag < DEAD_DEAD ) {
2023-08-04 00:04:29 +02:00
m_iInfoClient = ent - g_entities ;
m_iInfoClientHealth = ent - > entity - > health ;
m_fInfoClientTime = level . time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
float percent = ent - > entity - > health / ent - > entity - > max_health * 100.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( percent > 0.0f & & percent < 1.0f ) {
percent = 1.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_INFOCLIENT_HEALTH ] = percent ;
}
} else {
Vector vForward ;
trace_t trace ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AngleVectors ( m_vViewAng , vForward , NULL , NULL ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Vector vEnd = m_vViewPos + vForward * 2048.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( m_vViewPos , vec_zero , vec_zero , vEnd , this , MASK_BEAM , qfalse , " infoclientcheck " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( trace . ent & & trace . ent - > entity - > IsSubclassOfPlayer ( ) ) {
2023-08-13 16:11:25 +02:00
Player * p = static_cast < Player * > ( trace . ent - > entity ) ;
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
if ( IsSpectator ( ) | | p - > GetTeam ( ) = = GetTeam ( ) ) {
2023-08-04 00:04:29 +02:00
m_iInfoClient = trace . ent - g_entities ;
m_iInfoClientHealth = p - > health ;
m_fInfoClientTime = level . time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
float percent = trace . ent - > entity - > health / trace . ent - > entity - > max_health * 100.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( percent > 0.0f & & percent < 1.0f ) {
percent = 1.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_INFOCLIENT_HEALTH ] = percent ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_iInfoClient ! = - 1 ) {
if ( level . time < = m_fInfoClientTime + 1.5f ) {
client - > ps . stats [ STAT_INFOCLIENT ] = m_iInfoClient ;
client - > ps . stats [ STAT_INFOCLIENT_HEALTH ] = m_iInfoClientHealth ;
} else {
m_iInfoClient = - 1 ;
}
}
}
2024-01-02 00:43:27 +01:00
if ( g_gametype - > integer > = GT_TOW | | level . m_bForceTeamObjectiveLocation ) {
2023-08-11 03:13:36 +02:00
if ( GetTeam ( ) = = TEAM_AXIS ) {
vObjectiveLocation = level . m_vAxisObjectiveLocation ;
2023-08-13 16:11:25 +02:00
} else if ( GetTeam ( ) = = TEAM_ALLIES ) {
2023-08-11 03:13:36 +02:00
vObjectiveLocation = level . m_vAlliedObjectiveLocation ;
}
2024-01-02 00:43:27 +01:00
} else {
vObjectiveLocation = level . m_vObjectiveLocation ;
2023-08-11 03:13:36 +02:00
}
2023-08-04 00:04:29 +02:00
2023-08-11 03:13:36 +02:00
if ( g_protocol < protocol_e : : PROTOCOL_MOHTA_MIN & & vObjectiveLocation = = vec_zero ) {
//
// try to use the nearest teammate instead.
// the reason is that mohaa 1.11 and below doesn't have a radar
// for teammates
//
if ( g_gametype - > integer > GT_FFA & & ! IsDead ( ) & & ! IsSpectator ( ) ) {
2023-08-13 16:11:25 +02:00
gentity_t * ent ;
2023-08-11 03:13:36 +02:00
int i ;
2023-08-13 16:11:25 +02:00
Player * p ;
2023-08-11 03:13:36 +02:00
float fNearest = 9999.0f ;
float fLength ;
// match the compass direction to the nearest player
for ( i = 0 , ent = g_entities ; i < game . maxclients ; i + + , ent + + ) {
if ( ! ent - > inuse | | ! ent - > client | | ! ent - > entity | | ent - > entity = = this ) {
continue ;
}
2023-08-04 00:04:29 +02:00
2023-08-13 16:11:25 +02:00
p = ( Player * ) ent - > entity ;
2023-08-11 03:13:36 +02:00
if ( p - > IsDead ( ) | | p - > IsSpectator ( ) | | p - > dm_team ! = dm_team ) {
continue ;
}
2023-08-04 00:04:29 +02:00
2023-08-11 03:13:36 +02:00
fLength = ( p - > centroid - centroid ) . length ( ) ;
2023-08-04 00:04:29 +02:00
2023-08-11 03:13:36 +02:00
if ( fLength < fNearest ) {
2023-08-13 16:11:25 +02:00
fNearest = fLength ;
2023-08-11 03:13:36 +02:00
vObjectiveLocation = p - > centroid ;
}
2023-08-04 00:04:29 +02:00
}
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
if ( m_pVehicle & & ! m_pTurret ) {
2023-08-13 16:11:25 +02:00
client - > ps . stats [ STAT_VEHICLE_HEALTH ] = m_pVehicle - > health ;
2023-08-11 03:13:36 +02:00
client - > ps . stats [ STAT_VEHICLE_MAX_HEALTH ] = m_pVehicle - > max_health ;
2023-08-13 16:11:25 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-11 03:13:36 +02:00
//
// Health fraction
//
2023-08-13 16:11:25 +02:00
healthfrac = ( health / max_health * 100.0f ) ;
2023-08-04 00:04:29 +02:00
2023-08-13 16:11:25 +02:00
if ( m_pVehicle & & ! m_pTurret ) {
2024-02-08 20:41:33 +01:00
if ( ! m_pVehicle - > isSubclassOf ( FixedTurret ) ) {
2023-08-13 16:11:25 +02:00
healthfrac = ( m_pVehicle - > health / m_pVehicle - > max_health * 100.f ) ;
}
}
2023-08-11 03:13:36 +02:00
2023-08-13 16:11:25 +02:00
if ( healthfrac < 1 & & healthfrac > 0 ) {
healthfrac = 1 ;
}
if ( healthfrac < 0 ) {
healthfrac = 0 ;
}
2023-08-11 03:13:36 +02:00
client - > ps . stats [ STAT_HEALTH ] = healthfrac ;
//
// Healing
//
if ( m_fHealRate & & ( ! m_pVehicle | | m_pTurret | | m_pVehicle - > isSubclassOf ( FixedTurret ) ) ) {
2023-08-16 19:14:05 +02:00
healfrac = ( health + m_fHealRate ) / max_health * 100.f ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-11 03:13:36 +02:00
healfrac = 0 ;
2023-08-13 16:11:25 +02:00
}
if ( healfrac < 1 & & healfrac > 0 ) {
healfrac = 1 ;
}
if ( healfrac < 0 ) {
healfrac = 0 ;
}
2023-08-04 00:04:29 +02:00
2023-08-13 16:11:25 +02:00
client - > ps . stats [ STAT_NEXTHEALTH ] = healfrac ;
client - > ps . stats [ STAT_MAXHEALTH ] = 100 ;
2023-08-04 00:04:29 +02:00
Weapon * activeweap = GetActiveWeapon ( WEAPON_MAIN ) ;
client - > ps . stats [ STAT_WEAPONS ] = 0 ;
client - > ps . stats [ STAT_EQUIPPED_WEAPON ] = 0 ;
client - > ps . stats [ STAT_AMMO ] = 0 ;
client - > ps . stats [ STAT_MAXAMMO ] = 0 ;
client - > ps . stats [ STAT_CLIPAMMO ] = 0 ;
client - > ps . stats [ STAT_MAXCLIPAMMO ] = 0 ;
client - > ps . activeItems [ ITEM_AMMO ] = - 1 ;
client - > ps . activeItems [ ITEM_WEAPON ] = - 1 ;
client - > ps . activeItems [ 2 ] = - 1 ;
client - > ps . activeItems [ 3 ] = - 1 ;
client - > ps . activeItems [ 4 ] = - 1 ;
client - > ps . activeItems [ 5 ] = - 1 ;
2023-08-11 03:13:36 +02:00
if ( m_pTurret ) {
client - > ps . activeItems [ ITEM_WEAPON ] = m_pTurret - > getIndex ( ) ;
if ( getMoveType ( ) = = MOVETYPE_PORTABLE_TURRET | | getMoveType ( ) = = MOVETYPE_TURRET ) {
// Use the turret's ammo
2023-08-13 16:11:25 +02:00
client - > ps . stats [ STAT_CLIPAMMO ] = m_pTurret - > ammo_in_clip [ FIRE_PRIMARY ] ;
2023-08-11 03:13:36 +02:00
client - > ps . stats [ STAT_MAXCLIPAMMO ] = m_pTurret - > ammo_clip_size [ FIRE_PRIMARY ] ;
}
2023-08-04 00:04:29 +02:00
} else if ( activeweap ) {
2023-08-11 03:13:36 +02:00
if ( activeweap - > m_bSecondaryAmmoInHud ) {
2023-08-13 16:11:25 +02:00
client - > ps . stats [ STAT_AMMO ] = AmmoCount ( activeweap - > GetAmmoType ( FIRE_SECONDARY ) ) ;
client - > ps . stats [ STAT_MAXAMMO ] = MaxAmmoCount ( activeweap - > GetAmmoType ( FIRE_SECONDARY ) ) ;
2023-08-11 03:13:36 +02:00
client - > ps . stats [ STAT_SECONDARY_AMMO ] = AmmoCount ( activeweap - > GetAmmoType ( FIRE_PRIMARY ) ) ;
} else {
2023-08-13 16:11:25 +02:00
client - > ps . stats [ STAT_AMMO ] = AmmoCount ( activeweap - > GetAmmoType ( FIRE_PRIMARY ) ) ;
2023-08-11 03:13:36 +02:00
client - > ps . stats [ STAT_MAXAMMO ] = MaxAmmoCount ( activeweap - > GetAmmoType ( FIRE_PRIMARY ) ) ;
}
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_CLIPAMMO ] = activeweap - > ClipAmmo ( FIRE_PRIMARY ) ;
client - > ps . stats [ STAT_MAXCLIPAMMO ] = activeweap - > GetClipSize ( FIRE_PRIMARY ) ;
client - > ps . activeItems [ ITEM_AMMO ] = AmmoIndex ( activeweap - > GetAmmoType ( FIRE_PRIMARY ) ) ;
// grenade and rockets must match the number of ammo
if ( client - > ps . stats [ STAT_MAXCLIPAMMO ] = = 1 ) {
client - > ps . stats [ STAT_MAXAMMO ] + + ;
client - > ps . stats [ STAT_AMMO ] + = client - > ps . stats [ STAT_CLIPAMMO ] ;
}
if ( ! activeweap - > IsSubclassOfInventoryItem ( ) ) {
client - > ps . stats [ STAT_EQUIPPED_WEAPON ] = activeweap - > GetWeaponClass ( ) ;
}
client - > ps . activeItems [ ITEM_WEAPON ] = activeweap - > getIndex ( ) ;
2023-08-11 03:13:36 +02:00
} else if ( m_pVehicle ) {
2023-08-13 16:11:25 +02:00
Entity * pEnt = m_pVehicle - > QueryTurretSlotEntity ( 0 ) ;
2023-08-11 03:13:36 +02:00
if ( pEnt & & pEnt - > IsSubclassOfVehicleTurretGun ( ) ) {
2023-08-13 16:11:25 +02:00
VehicleTurretGun * vt = static_cast < VehicleTurretGun * > ( pEnt ) ;
2023-08-11 03:13:36 +02:00
2023-08-13 16:11:25 +02:00
client - > ps . activeItems [ ITEM_WEAPON ] = vt - > getIndex ( ) ;
client - > ps . stats [ STAT_CLIPAMMO ] = vt - > ammo_in_clip [ FIRE_PRIMARY ] ;
client - > ps . stats [ STAT_MAXCLIPAMMO ] = vt - > ammo_clip_size [ FIRE_PRIMARY ] ;
2023-08-11 03:13:36 +02:00
client - > ps . stats [ STAT_SECONDARY_AMMO ] = vt - > GetWarmupFraction ( ) * 100.f ;
}
2023-08-04 00:04:29 +02:00
}
//
// set boss health
//
client - > ps . stats [ STAT_BOSSHEALTH ] = bosshealth - > value * 100.0f ;
if ( bosshealth - > value * 100.0f > 0 & & client - > ps . stats [ STAT_BOSSHEALTH ] = = 0 ) {
client - > ps . stats [ STAT_BOSSHEALTH ] = 1 ;
}
// Set cinematic stuff
client - > ps . stats [ STAT_CINEMATIC ] = 0 ;
if ( level . cinematic ) {
client - > ps . stats [ STAT_CINEMATIC ] = ( 1 < < 0 ) ;
}
if ( actor_camera ) {
client - > ps . stats [ STAT_CINEMATIC ] + = ( 1 < < 1 ) ;
}
count = inventory . NumObjects ( ) ;
int iItem = 0 ;
for ( i = 1 ; i < = count ; i + + ) {
int entnum = inventory . ObjectAt ( i ) ;
Weapon * weapon = ( Weapon * ) G_GetEntity ( entnum ) ;
int weapon_class ;
if ( weapon - > IsSubclassOfWeapon ( ) ) {
if ( weapon - > IsSubclassOfInventoryItem ( ) ) {
2023-09-19 20:18:27 +02:00
if ( iItem > 3 ) {
weapon - > SetItemSlot ( 0 ) ;
} else {
2023-08-04 00:04:29 +02:00
client - > ps . activeItems [ iItem + 2 ] = weapon - > getIndex ( ) ;
2023-11-15 19:36:29 +01:00
weapon - > SetItemSlot ( WEAPON_CLASS_ITEM1 < < iItem ) ;
2023-08-04 00:04:29 +02:00
if ( activeweap & & weapon = = activeweap ) {
2023-11-15 19:36:29 +01:00
client - > ps . stats [ STAT_EQUIPPED_WEAPON ] = WEAPON_CLASS_ITEM1 < < iItem ;
2023-08-04 00:04:29 +02:00
}
iItem + + ;
}
} else {
weapon_class = weapon - > GetWeaponClass ( ) ;
if ( weapon_class & WEAPON_CLASS_GRENADE ) {
if ( weapon - > HasAmmo ( FIRE_PRIMARY ) ) {
client - > ps . stats [ STAT_WEAPONS ] | = weapon_class ;
}
} else {
client - > ps . stats [ STAT_WEAPONS ] | = weapon_class ;
}
}
}
}
// Go through all the player's ammo and send over the names/amounts
memset ( client - > ps . ammo_amount , 0 , sizeof ( client - > ps . ammo_amount ) ) ;
memset ( client - > ps . ammo_name_index , 0 , sizeof ( client - > ps . ammo_name_index ) ) ;
memset ( client - > ps . max_ammo_amount , 0 , sizeof ( client - > ps . max_ammo_amount ) ) ;
count = ammo_inventory . NumObjects ( ) ;
for ( i = 1 ; i < = count ; i + + ) {
Ammo * ammo = ammo_inventory . ObjectAt ( i ) ;
if ( ammo ) {
client - > ps . ammo_amount [ i - 1 ] = ammo - > getAmount ( ) ;
client - > ps . max_ammo_amount [ i - 1 ] = ammo - > getMaxAmount ( ) ;
client - > ps . ammo_name_index [ i - 1 ] = ammo - > getIndex ( ) ;
}
}
if ( m_iInZoomMode = = - 1 ) {
client - > ps . stats [ STAT_INZOOM ] = fov ;
} else {
client - > ps . stats [ STAT_INZOOM ] = 0 ;
}
client - > ps . stats [ STAT_CROSSHAIR ] =
( ( ! client - > ps . stats [ STAT_INZOOM ] | | client - > ps . stats [ STAT_INZOOM ] > 30 )
2023-08-11 03:13:36 +02:00
& & ( activeweap & & ! activeweap - > IsSubclassOfInventoryItem ( ) & & activeweap - > GetUseCrosshair ( ) ) )
| | m_pTurret | | ( m_pVehicle & & m_pVehicle - > IsSubclassOfVehicleTank ( ) ) ;
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_COMPASSNORTH ] = ANGLE2SHORT ( world - > m_fNorth ) ;
if ( VectorCompare ( vObjectiveLocation , vec_zero ) ) {
client - > ps . stats [ STAT_OBJECTIVELEFT ] = 1730 ;
client - > ps . stats [ STAT_OBJECTIVERIGHT ] = 1870 ;
client - > ps . stats [ STAT_OBJECTIVECENTER ] = 1800 ;
} else {
Vector vDelta ;
float yaw ;
float fOffset ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
vDelta = vObjectiveLocation - centroid ;
yaw = AngleSubtract ( v_angle [ 1 ] , vDelta . toYaw ( ) ) + 180.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
vDelta = yaw_left * 300.0f + yaw_forward * vDelta . length ( ) + centroid - centroid ;
fOffset = AngleSubtract ( vDelta . toYaw ( ) , v_angle [ 1 ] ) ;
if ( fOffset < 0.0f ) {
fOffset = - fOffset ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
fOffset = 53.0f - fOffset + 7.0f ;
if ( fOffset < 7.0f ) {
fOffset = 7.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_OBJECTIVELEFT ] = anglemod ( yaw - fOffset ) * 10.0f ;
if ( client - > ps . stats [ STAT_OBJECTIVELEFT ] < = 0 ) {
client - > ps . stats [ STAT_OBJECTIVELEFT ] = 1 ;
} else if ( client - > ps . stats [ STAT_OBJECTIVELEFT ] > 3599 ) {
client - > ps . stats [ STAT_OBJECTIVELEFT ] = 3599 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_OBJECTIVERIGHT ] = anglemod ( yaw + fOffset ) * 10.0f ;
if ( client - > ps . stats [ STAT_OBJECTIVERIGHT ] < = 0 ) {
client - > ps . stats [ STAT_OBJECTIVERIGHT ] = 1 ;
} else if ( client - > ps . stats [ STAT_OBJECTIVERIGHT ] > 3599 ) {
client - > ps . stats [ STAT_OBJECTIVERIGHT ] = 3599 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_OBJECTIVECENTER ] = anglemod ( yaw ) * 10.0f ;
if ( client - > ps . stats [ STAT_OBJECTIVECENTER ] < = 0 ) {
client - > ps . stats [ STAT_OBJECTIVECENTER ] = 1 ;
} else if ( client - > ps . stats [ STAT_OBJECTIVECENTER ] > 3599 ) {
client - > ps . stats [ STAT_OBJECTIVECENTER ] = 3599 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_DAMAGEDIR ] = damage_yaw ;
if ( client - > ps . stats [ STAT_DAMAGEDIR ] < 0 ) {
client - > ps . stats [ STAT_DAMAGEDIR ] = 0 ;
} else if ( client - > ps . stats [ STAT_DAMAGEDIR ] > 3600 ) {
client - > ps . stats [ STAT_DAMAGEDIR ] = 3600 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Do letterbox
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Check for letterbox fully out
if ( ( level . m_letterbox_time < = 0 ) & & ( level . m_letterbox_dir = = letterbox_in ) ) {
client - > ps . stats [ STAT_LETTERBOX ] = level . m_letterbox_fraction * MAX_LETTERBOX_SIZE ;
return ;
} else if ( ( level . m_letterbox_time < = 0 ) & & ( level . m_letterbox_dir = = letterbox_out ) ) {
client - > ps . stats [ STAT_LETTERBOX ] = 0 ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
float frac ;
2016-03-27 11:49:47 +02:00
2024-09-27 19:35:14 +02:00
level . m_letterbox_time - = level . frametime ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
frac = level . m_letterbox_time / level . m_letterbox_time_start ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( frac > 1 ) {
frac = 1 ;
}
if ( frac < 0 ) {
frac = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( level . m_letterbox_dir = = letterbox_in ) {
frac = 1.0f - frac ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . stats [ STAT_LETTERBOX ] = ( frac * level . m_letterbox_fraction ) * MAX_LETTERBOX_SIZE ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : UpdateMusic ( void )
{
if ( music_forced ) {
client - > ps . current_music_mood = music_current_mood ;
client - > ps . fallback_music_mood = music_fallback_mood ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Copy music volume and fade time to player state
client - > ps . music_volume = music_current_volume ;
client - > ps . music_volume_fade_time = music_volume_fade_time ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SetReverb ( int type , float level )
{
reverb_type = type ;
reverb_level = level ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SetReverb ( str type , float level )
{
reverb_type = EAXMode_NameToNum ( type ) ;
reverb_level = level ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SetReverb ( Event * ev )
{
if ( ev - > NumArgs ( ) < 2 ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetReverb ( ev - > GetInteger ( 1 ) , ev - > GetFloat ( 2 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : UpdateReverb ( void )
{
client - > ps . reverb_type = reverb_type ;
client - > ps . reverb_level = reverb_level ;
}
2023-08-04 00:21:19 +02:00
2023-08-04 00:04:29 +02:00
void Player : : UpdateMisc ( void )
{
//
// clear out the level exit flag
//
client - > ps . pm_flags & = ~ PMF_LEVELEXIT ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// see if our camera is the level exit camera
//
if ( camera & & camera - > IsLevelExit ( ) ) {
client - > ps . pm_flags | = PMF_LEVELEXIT ;
} else if ( level . near_exit ) {
client - > ps . pm_flags | = PMF_LEVELEXIT ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// do anything special for respawns
//
if ( client - > ps . pm_flags & PMF_RESPAWNED ) {
//
// change music
//
if ( music_current_mood ! = mood_success ) {
ChangeMusic ( " success " , " normal " , false ) ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/*
= = = = = = = = = = = = = = = = =
EndFrame
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Called for each player at the end of the server frame
and right after spawning
= = = = = = = = = = = = = = = = =
*/
void Player : : EndFrame ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
FinishMove ( ) ;
UpdateStats ( ) ;
UpdateMusic ( ) ;
UpdateReverb ( ) ;
UpdateMisc ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! g_spectatefollow_firstperson - > integer | | ! IsSpectator ( ) | | ! m_iPlayerSpectating ) {
SetupView ( ) ;
} else {
gentity_t * ent = g_entities + m_iPlayerSpectating - 1 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! ent - > inuse | | ! ent - > entity | | ent - > entity - > deadflag > = DEAD_DEAD ) {
SetupView ( ) ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : GotKill ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
/*
2023-08-10 14:18:40 +02:00
Entity * victim ;
2016-03-27 11:49:47 +02:00
Entity * inflictor ;
float damage ;
int meansofdeath ;
qboolean gibbed ;
if ( deathmatch - > integer )
2023-08-10 14:18:40 +02:00
{
2016-03-27 11:49:47 +02:00
return ;
2023-08-10 14:18:40 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-10 14:18:40 +02:00
victim = ev - > GetEntity ( 1 ) ;
damage = ev - > GetInteger ( 2 ) ;
inflictor = ev - > GetEntity ( 3 ) ;
meansofdeath = ev - > GetInteger ( 4 ) ;
gibbed = ev - > GetInteger ( 5 ) ;
2016-03-27 11:49:47 +02:00
*/
}
2023-08-04 00:04:29 +02:00
void Player : : SetPowerupTimer ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Event * event ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
poweruptimer = ev - > GetInteger ( 1 ) ;
poweruptype = ev - > GetInteger ( 2 ) ;
event = new Event ( EV_Player_UpdatePowerupTimer ) ;
PostEvent ( event , 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : UpdatePowerupTimer ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
poweruptimer - = 1 ;
if ( poweruptimer > 0 ) {
PostEvent ( ev , 1 ) ;
} else {
poweruptype = 0 ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ChangeMusic ( const char * current , const char * fallback , qboolean force )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
int current_mood_num ;
int fallback_mood_num ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
music_forced = force ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( current ) {
current_mood_num = MusicMood_NameToNum ( current ) ;
if ( current_mood_num < 0 ) {
gi . DPrintf ( " current music mood %s not found " , current ) ;
} else {
music_current_mood = current_mood_num ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( fallback ) {
fallback_mood_num = MusicMood_NameToNum ( fallback ) ;
if ( fallback_mood_num < 0 ) {
gi . DPrintf ( " fallback music mood %s not found " , fallback ) ;
fallback = NULL ;
} else {
music_fallback_mood = fallback_mood_num ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ChangeMusicVolume ( float volume , float fade_time )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
music_volume_fade_time = fade_time ;
music_saved_volume = music_current_volume ;
music_current_volume = volume ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : RestoreMusicVolume ( float fade_time )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
music_volume_fade_time = fade_time ;
music_current_volume = music_saved_volume ;
music_saved_volume = - 1.0 ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : addOrigin ( Vector org )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
setLocalOrigin ( localorigin + org ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
animspeed = org . x * ( 1.f / level . frametime ) ;
airspeed = org . y * ( 1.f / level . frametime ) ;
2023-08-04 00:04:29 +02:00
m_vPushVelocity . x = org . z * ( 1.f / level . frametime ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Jump ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float maxheight ;
2016-03-27 11:49:47 +02:00
2024-11-03 20:30:37 +01:00
if ( m_pTurret | | m_pVehicle ) {
// Don't jump when inside a vehicle or turret
return ;
}
2024-11-03 20:32:17 +01:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
// Added in 2.0
// Don't jump when on top of another sentient
if ( groundentity & & groundentity - > entity & & groundentity - > entity - > IsSubclassOfSentient ( ) ) {
return ;
}
}
2023-08-04 00:04:29 +02:00
maxheight = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( maxheight > 16 ) {
// v^2 = 2ad
velocity [ 2 ] + = sqrt ( 2 * sv_gravity - > integer * maxheight ) ;
2016-03-27 11:49:47 +02:00
2024-11-03 20:32:45 +01:00
if ( client - > ps . groundEntityNum ! = ENTITYNUM_NONE ) {
velocity + = m_vPushVelocity ;
}
2023-08-04 00:04:29 +02:00
// make sure the player leaves the ground
client - > ps . walking = qfalse ;
2024-11-03 20:01:21 +01:00
// Added in 2.0
m_bHasJumped = true ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : JumpXY ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float forwardmove ;
float sidemove ;
float distance ;
float time ;
float speed ;
2016-03-27 11:49:47 +02:00
2024-11-03 20:30:37 +01:00
if ( m_pTurret | | m_pVehicle ) {
// Don't jump when inside a vehicle or turret
return ;
}
2023-08-04 00:04:29 +02:00
forwardmove = ev - > GetFloat ( 1 ) ;
sidemove = ev - > GetFloat ( 2 ) ;
speed = ev - > GetFloat ( 3 ) ;
2023-01-29 22:58:04 +01:00
2023-08-04 00:04:29 +02:00
velocity = yaw_forward * forwardmove - yaw_left * sidemove ;
distance = velocity . length ( ) ;
velocity * = speed / distance ;
time = distance / speed ;
velocity [ 2 ] = sv_gravity - > integer * time * 0.5f ;
2016-03-27 11:49:47 +02:00
2024-11-03 20:32:45 +01:00
if ( client - > ps . groundEntityNum ! = ENTITYNUM_NONE ) {
velocity + = G_GetEntity ( client - > ps . groundEntityNum ) - > velocity ;
}
2023-08-04 00:04:29 +02:00
airspeed = distance ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// make sure the player leaves the ground
client - > ps . walking = qfalse ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetViewAngles ( Vector newViewangles )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
// set the delta angle
client - > ps . delta_angles [ 0 ] = ANGLE2SHORT ( newViewangles . x - client - > cmd_angles [ 0 ] ) ;
client - > ps . delta_angles [ 1 ] = ANGLE2SHORT ( newViewangles . y - client - > cmd_angles [ 1 ] ) ;
client - > ps . delta_angles [ 2 ] = ANGLE2SHORT ( newViewangles . z - client - > cmd_angles [ 2 ] ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
v_angle = newViewangles ;
2024-08-27 15:24:31 +02:00
// Fixed in OPM
// Normalize angles to the range (-180, +180)
// so interpolation is done properly client-side
v_angle . EulerNormalize ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// get the pitch and roll from our leg angles
newViewangles . x = angles . x ;
newViewangles . z = angles . z ;
AnglesToMat ( newViewangles , orientation ) ;
yaw_forward = orientation [ 0 ] ;
yaw_left = orientation [ 1 ] ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 01:31:56 +02:00
void Player : : SetTargetViewAngles ( Vector angles )
2016-03-27 11:49:47 +02:00
{
2023-08-09 01:31:56 +02:00
v_angle = angles ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : DumpState ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
gi . DPrintf (
" Legs: %s Torso: %s \n " , currentState_Legs ? currentState_Legs - > getName ( ) : " NULL " , currentState_Torso - > getName ( )
) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : ForceTorsoState ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:21:19 +02:00
State * ts = statemap_Torso - > FindState ( ev - > GetString ( 1 ) ) ;
2023-08-04 00:04:29 +02:00
EvaluateState ( ts ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ForceLegsState ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
State * ls = statemap_Legs - > FindState ( ev - > GetString ( 1 ) ) ;
EvaluateState ( NULL , ls ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : TouchedUseAnim ( Entity * ent )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
toucheduseanim = ent ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : NextPainTime ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float time = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
nextpaintime = level . time + time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( time > = 0.0f ) {
2023-08-04 00:21:19 +02:00
pain = 0.0f ;
pain_type = MOD_NONE ;
2023-08-11 01:33:49 +02:00
pain_location = HITLOC_MISS ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_pLegsPainCond - > clearCheck ( ) ;
m_pTorsoPainCond - > clearCheck ( ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : EnterVehicle ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:21:19 +02:00
Entity * ent ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ent = ev - > GetEntity ( 1 ) ;
if ( ent & & ent - > IsSubclassOfVehicle ( ) ) {
flags | = FL_PARTIAL_IMMOBILE ;
viewheight = STAND_EYE_HEIGHT ;
2023-08-04 00:21:19 +02:00
velocity = vec_zero ;
m_pVehicle = ( Vehicle * ) ent ;
2023-08-04 00:04:29 +02:00
if ( m_pVehicle - > IsDrivable ( ) ) {
setMoveType ( MOVETYPE_VEHICLE ) ;
2023-08-04 00:21:19 +02:00
} else {
2023-08-04 00:04:29 +02:00
setMoveType ( MOVETYPE_NOCLIP ) ;
}
2023-08-02 20:59:19 +02:00
2023-08-04 00:04:29 +02:00
SafeHolster ( true ) ;
}
2023-08-02 20:59:19 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : ExitVehicle ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
flags & = ~ FL_PARTIAL_IMMOBILE ;
setMoveType ( MOVETYPE_WALK ) ;
m_pVehicle = NULL ;
2023-09-17 19:54:45 +02:00
if ( camera ) {
SetCamera ( NULL , 0.5f ) ;
ZoomOff ( ) ;
}
SafeHolster ( false ) ;
takedamage = DAMAGE_YES ;
setSolidType ( SOLID_BBOX ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : EnterTurret ( TurretGun * ent )
2016-03-27 11:49:47 +02:00
{
2023-11-03 21:56:31 +01:00
flags | = FL_PARTIAL_IMMOBILE ;
viewheight = DEFAULT_VIEWHEIGHT ;
velocity = vec_zero ;
m_pTurret = ent ;
2023-09-17 19:54:45 +02:00
if ( ent - > inheritsFrom ( PortableTurret : : classinfostatic ( ) ) ) {
// carryable turret
setMoveType ( MOVETYPE_PORTABLE_TURRET ) ;
StopPartAnimating ( torso ) ;
SetPartAnim ( " mg42tripod_aim_straight_straight " ) ;
} else {
// standard turret
setMoveType ( MOVETYPE_TURRET ) ;
}
2023-08-04 00:04:29 +02:00
SafeHolster ( true ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : EnterTurret ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:21:19 +02:00
TurretGun * ent = ( TurretGun * ) ev - > GetEntity ( 1 ) ;
2023-08-04 00:04:29 +02:00
if ( ! ent ) {
return ;
}
2023-09-17 19:54:45 +02:00
if ( ! ent - > inheritsFrom ( TurretGun : : classinfostatic ( ) ) ) {
2023-08-04 00:04:29 +02:00
return ;
}
EnterTurret ( ent ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ExitTurret ( void )
2016-03-27 11:49:47 +02:00
{
2023-09-17 19:54:45 +02:00
if ( m_pTurret - > inheritsFrom ( PortableTurret : : classinfostatic ( ) ) ) {
StopPartAnimating ( torso ) ;
SetPartAnim ( " mg42tripod_aim_straight_straight " ) ;
}
2023-08-04 00:04:29 +02:00
flags & = ~ FL_PARTIAL_IMMOBILE ;
setMoveType ( MOVETYPE_WALK ) ;
m_pTurret = NULL ;
SafeHolster ( qfalse ) ;
2023-09-17 19:54:45 +02:00
2023-11-03 21:56:31 +01:00
new_buttons = 0 ;
2023-09-17 19:54:45 +02:00
server_new_buttons = 0 ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : ExitTurret ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ExitTurret ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
2023-08-04 00:04:29 +02:00
void Player : : HolsterToggle ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( deadflag ) {
return ;
}
if ( WeaponsOut ( ) ) {
// fucking compiler bug
// it won't call the parent's override function
( ( Sentient * ) this ) - > Holster ( qtrue ) ;
} else {
( ( Sentient * ) this ) - > Holster ( qfalse ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Holster ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
SafeHolster ( ev - > GetBoolean ( 1 ) ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : WatchActor ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( camera | | currentState_Torso - > getCameraType ( ) ! = CAMERA_BEHIND ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
actor_to_watch = ( Actor * ) ev - > GetEntity ( 1 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : StopWatchingActor ( Event * ev )
{
Actor * old_actor ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
old_actor = ( Actor * ) ev - > GetEntity ( 1 ) ;
if ( old_actor = = actor_to_watch ) {
actor_to_watch = NULL ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : setAngles ( Vector ang )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
// set the angles normally
if ( bindmaster ) {
ang - = bindmaster - > angles ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Entity : : setAngles ( ang ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
painDirection_t Player : : Pain_string_to_int ( str pain )
{
if ( ! pain . icmp ( pain , " Front " ) ) {
return PAIN_FRONT ;
} else if ( ! pain . icmp ( pain , " Left " ) ) {
return PAIN_LEFT ;
} else if ( ! pain . icmp ( pain , " Right " ) ) {
return PAIN_RIGHT ;
} else if ( ! pain . icmp ( pain , " Rear " ) ) {
return PAIN_REAR ;
} else {
return PAIN_NONE ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ArchivePersistantData ( Archiver & arc )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str model_name ;
2024-03-06 19:29:07 +01:00
str name ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Sentient : : ArchivePersistantData ( arc ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
model_name = g_playermodel - > string ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
arc . ArchiveString ( & model_name ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( arc . Loading ( ) ) {
// set the cvar
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_playermodel " , model_name . c_str ( ) ) ;
2016-03-27 11:49:47 +02:00
2024-03-06 19:29:07 +01:00
setModel ( " models/player/ " + model_name + " .tik " ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( arc . Saving ( ) ) {
if ( holsteredWeapon ) {
name = holsteredWeapon - > getName ( ) ;
} else {
name = " none " ;
}
}
2024-03-06 19:29:07 +01:00
2023-08-04 00:04:29 +02:00
arc . ArchiveString ( & name ) ;
2024-03-06 19:29:07 +01:00
if ( arc . Loading ( ) & & name ! = " none " ) {
holsteredWeapon = ( Weapon * ) FindItem ( name ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
UpdateWeapons ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Force a re-evaluation of the player's state
LoadStateTable ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : VelocityModified ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
int Player : : GetKnockback ( int original_knockback , qboolean blocked )
{
int new_knockback ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
new_knockback = original_knockback - 50 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// See if we still have enough knockback to knock the player down
if ( new_knockback > = 200 & & take_pain ) {
knockdown = true ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( blocked ) {
float damage ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
damage = new_knockback / 50 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( damage > 10 ) {
damage = 10 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Damage ( world , world , damage , origin , vec_zero , vec_zero , 0 , DAMAGE_NO_ARMOR , MOD_CRUSH ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Make sure knockback is still at least 0
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( new_knockback < 0 ) {
new_knockback = 0 ;
}
return new_knockback ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ResetHaveItem ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str fullname ;
ScriptVariable * var ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
fullname = str ( " playeritem_ " ) + ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
var = game . vars - > GetVariable ( fullname . c_str ( ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( var ) {
var - > setIntValue ( 0 ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : ReceivedItem ( Item * item ) { }
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : RemovedItem ( Item * item ) { }
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : AmmoAmountChanged ( Ammo * ammo , int ammo_in_clip )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str fullname ;
ScriptVariable * var ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
//
// set our level variables
//
fullname = str ( " playerammo_ " ) + ammo - > getName ( ) ;
var = level . vars - > GetVariable ( fullname . c_str ( ) ) ;
if ( ! var ) {
level . vars - > SetVariable ( fullname . c_str ( ) , ammo - > getAmount ( ) + ammo_in_clip ) ;
} else {
var - > setIntValue ( ammo - > getAmount ( ) + ammo_in_clip ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : WaitForState ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
waitForState = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetDamageMultiplier ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
damage_multiplier = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetTakePain ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
take_pain = ev - > GetBoolean ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Loaded ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
UpdateWeapons ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : PlayerShowModel ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Entity : : showModel ( ) ;
UpdateWeapons ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : showModel ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Entity : : showModel ( ) ;
UpdateWeapons ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
Vector Player : : EyePosition ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
return m_vViewPos ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
2023-08-04 00:04:29 +02:00
void Player : : ModifyHeight ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str height = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! height . icmp ( " stand " ) ) {
2023-08-13 17:59:41 +02:00
viewheight = DEFAULT_VIEWHEIGHT ;
maxs . z = 94.0f ;
m_bHasJumped = false ;
2023-08-04 00:04:29 +02:00
} else if ( ! height . icmp ( " jumpstart " ) ) {
2024-01-02 23:32:06 +01:00
if ( g_protocol < protocol_e : : PROTOCOL_MOHTA_MIN ) {
viewheight = JUMP_START_VIEWHEIGHT ;
}
2023-11-03 21:56:31 +01:00
maxs . z = 94.0f ;
2023-08-04 00:04:29 +02:00
} else if ( ! height . icmp ( " duck " ) ) {
viewheight = CROUCH_VIEWHEIGHT ;
maxs . z = 54.0f ;
} else if ( ! height . icmp ( " duckrun " ) ) {
viewheight = CROUCH_RUN_VIEWHEIGHT ;
maxs . z = 60.0f ;
} else if ( ! height . icmp ( " prone " ) ) {
2023-08-13 17:59:41 +02:00
//
2023-12-28 20:34:49 +01:00
// Added in OPM
// (prone)
2023-08-04 00:04:29 +02:00
viewheight = PRONE_VIEWHEIGHT ;
maxs . z = 20.0f ;
} else {
gi . Printf ( " Unknown modheight '%s' defaulting to stand \n " , height . c_str ( ) ) ;
viewheight = DEFAULT_VIEWHEIGHT ;
maxs . z = 94.0f ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-10 03:46:28 +02:00
// Specify the view height of the player and the height of his bounding box
void Player : : ModifyHeightFloat ( Event * ev )
{
// params
int height ;
float max_z ;
height = ev - > GetInteger ( 1 ) ;
max_z = ev - > GetFloat ( 2 ) ;
viewheight = height ;
if ( max_z > = 94.0 ) {
max_z = 94.0 ;
} else if ( max_z > = 74.0 & & max_z < 94.0 ) {
max_z = 54.0 ;
} else if ( max_z > = 30.0 & & max_z < 54.0 ) {
max_z = 20.0 ;
} else if ( max_z < = 20.0 ) {
max_z = 20.0 ;
}
maxs . z = max_z ;
client - > ps . pm_flags & = ~ ( PMF_DUCKED | PMF_VIEW_PRONE | PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START ) ;
// FIXME...
/*
2023-08-10 14:18:40 +02:00
gi . MSG_SetClient ( edict - g_entities ) ;
2023-08-10 03:46:28 +02:00
2023-08-10 14:18:40 +02:00
gi . MSG_StartCGM ( CGM_MODHEIGHTFLOAT ) ;
gi . MSG_WriteLong ( height ) ;
gi . MSG_WriteFloat ( max_z ) ;
gi . MSG_EndCGM ( ) ;
*/
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetMovePosFlags ( Event * ev )
{
str sParm ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) < = 0 ) {
Com_Printf ( " moveposflags command without any parameters \n " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
sParm = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! sParm . icmp ( " crouching " ) ) {
m_iMovePosFlags = MPF_POSITION_CROUCHING ;
} else if ( ! sParm . icmp ( " prone " ) ) {
m_iMovePosFlags = MPF_POSITION_PRONE ;
} else if ( ! sParm . icmp ( " offground " ) ) {
m_iMovePosFlags = MPF_POSITION_OFFGROUND ;
} else {
m_iMovePosFlags = MPF_POSITION_STANDING ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
sParm = ev - > GetString ( 2 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! sParm . icmp ( " walking " ) | | ! sParm . icmp ( " walking \" " ) // there is a mistake in WALK_FORWARD
) {
m_iMovePosFlags | = MPF_MOVEMENT_WALKING ;
} else if ( ! sParm . icmp ( " running " ) ) {
m_iMovePosFlags | = MPF_MOVEMENT_RUNNING ;
} else if ( ! sParm . icmp ( " falling " ) ) {
m_iMovePosFlags | = MPF_MOVEMENT_FALLING ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : GetPositionForScript ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( m_iMovePosFlags & MPF_POSITION_CROUCHING ) {
ev - > AddConstString ( STRING_CROUCHING ) ;
} else if ( m_iMovePosFlags & MPF_POSITION_PRONE ) {
ev - > AddConstString ( STRING_PRONE ) ;
} else if ( m_iMovePosFlags & MPF_POSITION_OFFGROUND ) {
ev - > AddConstString ( STRING_OFFGROUND ) ;
} else {
ev - > AddConstString ( STRING_STANDING ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetMovementForScript ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( m_iMovePosFlags & MPF_MOVEMENT_WALKING ) {
ev - > AddConstString ( STRING_WALKING ) ;
} else if ( m_iMovePosFlags & MPF_MOVEMENT_RUNNING ) {
ev - > AddConstString ( STRING_RUNNING ) ;
} else if ( m_iMovePosFlags & MPF_MOVEMENT_FALLING ) {
ev - > AddConstString ( STRING_FALLING ) ;
} else {
ev - > AddConstString ( STRING_STANDING ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ToggleZoom ( int iZoom )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( iZoom & & m_iInZoomMode = = - 1 ) {
SetFov ( selectedfov ) ;
m_iInZoomMode = 0 ;
} else {
SetFov ( iZoom ) ;
m_iInZoomMode = - 1 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : ZoomOff ( void )
{
SetFov ( selectedfov ) ;
m_iInZoomMode = 0 ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ZoomOffEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ZoomOff ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
qboolean Player : : IsZoomed ( void )
{
return m_iInZoomMode = = - 1 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SafeZoomed ( Event * ev )
{
if ( ev - > GetInteger ( 1 ) ) {
if ( m_iInZoomMode > 0 ) {
SetFov ( m_iInZoomMode ) ;
m_iInZoomMode = - 1 ;
}
} else {
if ( m_iInZoomMode = = - 1 ) {
m_iInZoomMode = fov ;
SetFov ( selectedfov ) ;
}
}
2023-08-04 00:21:19 +02:00
}
void Player : : AttachToLadder ( Event * ev )
2023-08-04 00:04:29 +02:00
{
Vector vStart , vEnd , vOffset ;
trace_t trace ;
FuncLadder * pLadder ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( deadflag ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AngleVectors ( m_vViewAng , vOffset , NULL , NULL ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
vStart = m_vViewPos - vOffset * 12.0f ;
vEnd = m_vViewPos + vOffset * 128.0f ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
trace = G_Trace ( vStart , vec_zero , vec_zero , vEnd , this , MASK_LADDER , qfalse , " Player::AttachToLadder " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( trace . fraction = = 1.0f | | ! trace . ent | | ! trace . ent - > entity | | ! trace . ent - > entity - > isSubclassOf ( FuncLadder ) ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pLadder = ( FuncLadder * ) trace . ent - > entity ;
m_pLadder = pLadder ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pLadder - > PositionOnLadder ( this ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetViewAngles ( Vector ( v_angle [ 0 ] , angles [ 1 ] , v_angle [ 2 ] ) ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : UnattachFromLadder ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
m_pLadder = NULL ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : TweakLadderPos ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
FuncLadder * pLadder = ( FuncLadder * ) m_pLadder . Pointer ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( pLadder ) {
pLadder - > AdjustPositionOnLadder ( this ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : EnsureOverLadder ( Event * ev )
{
FuncLadder * pLadder = ( FuncLadder * ) m_pLadder . Pointer ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( pLadder ) {
pLadder - > EnsureOverLadder ( this ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : EnsureForwardOffLadder ( Event * ev )
{
FuncLadder * pLadder = ( FuncLadder * ) m_pLadder . Pointer ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( pLadder ) {
pLadder - > EnsureForwardOffLadder ( this ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : EventForceLandmineMeasure ( Event * ev )
2023-08-10 03:46:28 +02:00
{
2023-08-10 14:18:40 +02:00
MeasureLandmineDistances ( ) ;
2023-08-10 03:46:28 +02:00
}
str Player : : GetCurrentDMWeaponType ( ) const
{
2023-08-10 14:18:40 +02:00
return m_sDmPrimary ;
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : Score ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-10 19:14:33 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
// Of course useless in single-player mode
return ;
}
2023-08-04 00:04:29 +02:00
dmManager . Score ( this ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-10 19:14:33 +02:00
// Was between 2.0 and 2.15
2023-08-10 03:46:28 +02:00
/*
nationality_t GetAlliedType ( const char * name )
{
if ( ! Q_stricmpn ( name , " american " , 8 ) ) {
return NA_AMERICAN ;
} else if ( ! Q_stricmpn ( name , " allied_russian " , 14 ) ) {
return NA_RUSSIAN ;
} else if ( ! Q_stricmpn ( name , " allied_british " , 14 ) ) {
return NA_BRITISH ;
} else if ( ! Q_stricmpn ( name , " allied " , 6 ) ) {
return NA_AMERICAN ;
} else {
return NA_NONE ;
}
}
*/
2023-11-14 00:49:32 +01:00
// Commented out in OPM. See the other comment below.
/*
2023-08-10 18:43:21 +02:00
nationality_t GetPlayerTeamType ( const char * name )
2023-08-10 03:46:28 +02:00
{
if ( ! Q_stricmpn ( name , " american " , 8 ) ) {
return NA_AMERICAN ;
} else if ( ! Q_stricmpn ( name , " allied_russian " , 14 ) ) {
return NA_RUSSIAN ;
} else if ( ! Q_stricmpn ( name , " allied_british " , 14 ) ) {
return NA_BRITISH ;
} else if ( ! Q_stricmpn ( name , " allied_sas " , 10 ) ) {
return NA_BRITISH ;
} else if ( ! Q_stricmpn ( name , " allied " , 6 ) ) {
return NA_AMERICAN ;
} else if ( ! Q_stricmpn ( name , " german " , 6 ) ) {
return NA_GERMAN ;
} else if ( ! Q_stricmpn ( name , " it " , 2 ) ) {
return NA_ITALIAN ;
} else if ( ! Q_stricmpn ( name , " sc " , 2 ) ) {
return NA_ITALIAN ;
} else {
return NA_NONE ;
}
}
2023-11-14 00:49:32 +01:00
*/
// Fixed in OPM.
// This fixes the issue where the player can equip weapons
// from the other team
nationality_t GetPlayerAxisTeamType ( const char * name )
{
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTA ) {
// Only american and german are supported on older versions of the game
return NA_GERMAN ;
}
2023-11-14 00:49:32 +01:00
if ( ! Q_stricmpn ( name , " german " , 6 ) ) {
return NA_GERMAN ;
2024-01-02 18:38:21 +01:00
}
if ( g_target_game < target_game_e : : TG_MOHTT ) {
// Italian skins are supported only in mohaab
return NA_GERMAN ;
}
if ( ! Q_stricmpn ( name , " it " , 2 ) ) {
2023-11-14 00:49:32 +01:00
return NA_ITALIAN ;
} else if ( ! Q_stricmpn ( name , " sc " , 2 ) ) {
return NA_ITALIAN ;
}
2024-01-02 18:38:21 +01:00
// fallback to german
return NA_GERMAN ;
2023-11-14 00:49:32 +01:00
}
nationality_t GetPlayerAlliedTeamType ( const char * name )
{
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTA ) {
// Only american and german are supported on older versions of the game
return NA_AMERICAN ;
}
2023-11-14 00:49:32 +01:00
if ( ! Q_stricmpn ( name , " american " , 8 ) ) {
return NA_AMERICAN ;
} else if ( ! Q_stricmpn ( name , " allied_russian " , 14 ) ) {
return NA_RUSSIAN ;
} else if ( ! Q_stricmpn ( name , " allied_british " , 14 ) ) {
return NA_BRITISH ;
} else if ( ! Q_stricmpn ( name , " allied_sas " , 10 ) ) {
return NA_BRITISH ;
} else if ( ! Q_stricmpn ( name , " allied " , 6 ) ) {
return NA_AMERICAN ;
}
2024-01-02 18:38:21 +01:00
// fallback to american
return NA_AMERICAN ;
2023-11-14 00:49:32 +01:00
}
2023-08-10 03:46:28 +02:00
2023-08-04 00:04:29 +02:00
void Player : : InitDeathmatch ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
fAttackerDispTime = 0.0f ;
pAttackerDistPointer = nullptr ;
m_iInfoClient = - 1 ;
m_fWeapSelectTime = level . time - 9.0f ;
2016-03-27 11:49:47 +02:00
2023-08-10 19:14:33 +02:00
if ( ! g_realismmode - > integer ) {
2023-08-11 01:33:49 +02:00
m_fDamageMultipliers [ HITLOC_HEAD ] = 2.0f ;
m_fDamageMultipliers [ HITLOC_HELMET ] = 2.0f ;
m_fDamageMultipliers [ HITLOC_NECK ] = 2.0f ;
m_fDamageMultipliers [ HITLOC_TORSO_UPPER ] = 1.0f ;
m_fDamageMultipliers [ HITLOC_TORSO_MID ] = 0.95f ;
m_fDamageMultipliers [ HITLOC_TORSO_LOWER ] = 0.90f ;
m_fDamageMultipliers [ HITLOC_PELVIS ] = 0.85f ;
m_fDamageMultipliers [ HITLOC_R_ARM_UPPER ] = 0.80f ;
m_fDamageMultipliers [ HITLOC_L_ARM_UPPER ] = 0.80f ;
m_fDamageMultipliers [ HITLOC_R_LEG_UPPER ] = 0.80f ;
m_fDamageMultipliers [ HITLOC_L_LEG_UPPER ] = 0.80f ;
m_fDamageMultipliers [ HITLOC_R_ARM_LOWER ] = 0.60f ;
m_fDamageMultipliers [ HITLOC_L_ARM_LOWER ] = 0.60f ;
m_fDamageMultipliers [ HITLOC_R_LEG_LOWER ] = 0.60f ;
m_fDamageMultipliers [ HITLOC_L_LEG_LOWER ] = 0.60f ;
m_fDamageMultipliers [ HITLOC_R_HAND ] = 0.50f ;
m_fDamageMultipliers [ HITLOC_L_HAND ] = 0.50f ;
m_fDamageMultipliers [ HITLOC_R_FOOT ] = 0.50f ;
m_fDamageMultipliers [ HITLOC_L_FOOT ] = 0.50f ;
2023-08-10 19:14:33 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( current_team ) {
2023-08-10 18:43:21 +02:00
if ( AllowTeamRespawn ( ) ) {
EndSpectator ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 18:43:21 +02:00
if ( dmManager . GetMatchStartTime ( ) > 0.0f & & ! dmManager . AllowRespawn ( ) & & g_allowjointime - > value > 0.0f
& & ( level . time - dmManager . GetMatchStartTime ( ) ) > g_allowjointime - > value ) {
m_bTempSpectator = true ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-10 19:14:33 +02:00
switch ( g_gametype - > integer ) {
case GT_TEAM_ROUNDS :
case GT_OBJECTIVE :
case GT_TOW :
case GT_LIBERATION :
if ( ! m_bTempSpectator ) {
BeginFight ( ) ;
} else {
Spectator ( ) ;
}
break ;
default :
2023-08-10 18:43:21 +02:00
BeginFight ( ) ;
2023-08-10 19:14:33 +02:00
break ;
2023-08-10 18:43:21 +02:00
}
2023-08-04 00:04:29 +02:00
}
} else {
2023-08-10 18:49:57 +02:00
if ( client - > pers . teamnum ) {
SetTeam ( client - > pers . teamnum ) ;
2023-08-04 00:04:29 +02:00
} else {
SetTeam ( TEAM_SPECTATOR ) ;
}
}
edict - > s . eFlags & = ~ ( TEAM_ALLIES | TEAM_AXIS ) ;
if ( GetTeam ( ) = = TEAM_ALLIES ) {
edict - > s . eFlags | = TEAM_ALLIES ;
} else if ( GetTeam ( ) = = TEAM_AXIS ) {
edict - > s . eFlags | = TEAM_AXIS ;
}
2023-08-10 18:43:21 +02:00
G_SetClientConfigString ( edict ) ;
2023-08-04 00:04:29 +02:00
if ( g_gametype - > integer > = GT_TEAM_ROUNDS ) {
2023-08-10 13:34:04 +02:00
if ( client - > pers . round_kills ) {
num_deaths = client - > pers . round_kills ;
client - > pers . round_kills = 0 ;
2023-08-04 00:04:29 +02:00
}
}
ChooseSpawnPoint ( ) ;
2023-08-10 18:43:21 +02:00
EquipWeapons ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( current_team ) {
current_team - > m_bHasSpawnedPlayers = qtrue ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
bool Player : : QueryLandminesAllowed ( ) const
2023-08-10 03:46:28 +02:00
{
2023-08-10 18:43:21 +02:00
const char * mapname ;
2023-08-10 03:46:28 +02:00
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTT ) {
return false ;
}
2023-08-10 14:18:40 +02:00
if ( dmflags - > integer & DF_WEAPON_NO_LANDMINE ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
2023-08-10 03:46:28 +02:00
2023-08-10 14:18:40 +02:00
if ( dmflags - > integer & DF_WEAPON_LANDMINE_ALWAYS ) {
2024-01-02 18:38:21 +01:00
return true ;
2023-08-10 14:18:40 +02:00
}
2023-08-10 03:46:28 +02:00
mapname = level . mapname . c_str ( ) ;
2023-08-10 14:18:40 +02:00
if ( ! Q_stricmpn ( mapname , " obj/obj_ " , 8u ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmpn ( mapname , " dm/mohdm " , 8u ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Bahnhof_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " obj/MP_Ardennes_TOW " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Bazaar_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " obj/MP_Berlin_TOW " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Brest_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " obj/MP_Druckkammern_TOW " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Gewitter_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " obj/MP_Flughafen_TOW " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Holland_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Malta_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Stadt_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Unterseite_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " DM/MP_Verschneit_DM " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
if ( ! Q_stricmp ( mapname , " lib/mp_ship_lib " ) ) {
2024-01-02 18:38:21 +01:00
return false ;
2023-08-10 14:18:40 +02:00
}
2024-01-02 18:38:21 +01:00
return true ;
2023-08-10 03:46:28 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : EnsurePlayerHasAllowedWeapons ( )
{
int i ;
//if (client != (gclient_t*)-2190)
if ( ! client ) {
return ;
}
if ( ! client - > pers . dm_primary [ 0 ] ) {
return ;
}
for ( i = 0 ; i < 7 ; i + + ) {
if ( ! Q_stricmp ( client - > pers . dm_primary , " sniper " ) ) {
if ( ! ( dmflags - > integer & DF_WEAPON_NO_SNIPER ) ) {
return ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " rifle " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " rifle " ) ) {
if ( ! ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ) {
return ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " smg " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " smg " ) ) {
if ( ! ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ) {
return ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " mg " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " mg " ) ) {
if ( ! ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ) {
return ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " shotgun " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " shotgun " ) ) {
if ( ! ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ) {
return ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " heavy " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " heavy " ) ) {
if ( ! ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ) {
return ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " landmine " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " landmine " ) ) {
if ( QueryLandminesAllowed ( ) ) {
return ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " sniper " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
}
}
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " dmflags " , va ( " %i " , dmflags - > integer & ~ DF_WEAPON_NO_RIFLE ) ) ;
2023-08-10 18:43:21 +02:00
Com_Printf ( " No valid weapons -- re-allowing the rifle \n " ) ;
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " rifle " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
}
void Player : : EquipWeapons ( )
{
Event * event ;
nationality_t nationality ;
if ( IsSpectator ( ) ) {
FreeInventory ( ) ;
return ;
}
2024-01-02 18:38:21 +01:00
// Fixed in OPM
// Old behavior was calling GetPlayerTeamType() regardless of the team
2023-08-10 18:43:21 +02:00
if ( GetTeam ( ) = = TEAM_AXIS ) {
2023-11-14 00:49:32 +01:00
nationality = GetPlayerAxisTeamType ( client - > pers . dm_playergermanmodel ) ;
2023-08-10 18:43:21 +02:00
} else {
2023-11-14 00:49:32 +01:00
nationality = GetPlayerAlliedTeamType ( client - > pers . dm_playermodel ) ;
2023-08-10 18:43:21 +02:00
}
2023-08-13 16:11:25 +02:00
event = new Event ( EV_Sentient_UseItem ) ;
2023-08-10 18:43:21 +02:00
if ( ! m_sDmPrimary . length ( ) ) {
// Set the primary weapon
m_sDmPrimary = client - > pers . dm_primary ;
}
EnsurePlayerHasAllowedWeapons ( ) ;
if ( ! Q_stricmp ( client - > pers . dm_primary , " sniper " ) & & ! ( dmflags - > integer & DF_WEAPON_NO_SNIPER ) ) {
switch ( nationality ) {
case NA_BRITISH :
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTT ) {
giveItem ( " weapons/springfield.tik " ) ;
event - > AddString ( " Springfield '03 Sniper " ) ;
} else {
giveItem ( " weapons/Uk_W_L42A1.tik " ) ;
event - > AddString ( " Enfield L42A1 " ) ;
}
2023-08-10 18:43:21 +02:00
break ;
case NA_RUSSIAN :
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTA | | dmflags - > integer & DF_OLD_SNIPER ) {
// Old snipers are forced older versions of the game
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/springfield.tik " ) ;
event - > AddString ( " Springfield '03 Sniper " ) ;
} else {
giveItem ( " weapons/svt_rifle.tik " ) ;
event - > AddString ( " SVT 40 " ) ;
}
break ;
case NA_GERMAN :
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTA | | dmflags - > integer & DF_OLD_SNIPER ) {
// Old snipers are forced older versions of the game
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/kar98sniper.tik " ) ;
event - > AddString ( " KAR98 - Sniper " ) ;
} else {
giveItem ( " weapons/g43.tik " ) ;
event - > AddString ( " G 43 " ) ;
}
break ;
case NA_ITALIAN :
giveItem ( " weapons/kar98sniper.tik " ) ;
event - > AddString ( " KAR98 - Sniper " ) ;
break ;
2024-01-02 18:38:21 +01:00
case NA_AMERICAN :
2023-08-10 18:43:21 +02:00
default :
2024-01-02 18:38:21 +01:00
giveItem ( " weapons/springfield.tik " ) ;
event - > AddString ( " Springfield '03 Sniper " ) ;
2023-08-10 18:43:21 +02:00
break ;
}
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " smg " ) & & ! ( dmflags - > integer & DF_WEAPON_NO_SMG ) ) {
switch ( nationality ) {
case NA_BRITISH :
giveItem ( " weapons/sten.tik " ) ;
event - > AddString ( " Sten Mark II " ) ;
break ;
case NA_RUSSIAN :
giveItem ( " weapons/ppsh_smg.tik " ) ;
event - > AddString ( " PPSH SMG " ) ;
break ;
case NA_GERMAN :
giveItem ( " weapons/mp40.tik " ) ;
event - > AddString ( " MP40 " ) ;
break ;
case NA_ITALIAN :
giveItem ( " weapons/it_w_moschetto.tik " ) ;
event - > AddString ( " Moschetto " ) ;
break ;
2024-01-02 18:38:21 +01:00
case NA_AMERICAN :
2023-08-10 18:43:21 +02:00
default :
giveItem ( " weapons/thompsonsmg.tik " ) ;
event - > AddString ( " Thompson " ) ;
break ;
}
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " mg " ) & & ! ( dmflags - > integer & DF_WEAPON_NO_MG ) ) {
switch ( nationality ) {
case NA_BRITISH :
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTT ) {
giveItem ( " weapons/bar.tik " ) ;
event - > AddString ( " BAR " ) ;
break ;
} else {
giveItem ( " weapons/Uk_W_Vickers.tik " ) ;
event - > AddString ( " Vickers-Berthier " ) ;
}
2023-08-10 18:43:21 +02:00
break ;
case NA_GERMAN :
giveItem ( " weapons/mp44.tik " ) ;
event - > AddString ( " StG 44 " ) ;
break ;
case NA_ITALIAN :
giveItem ( " weapons/It_W_Breda.tik " ) ;
2023-11-14 00:50:14 +01:00
event - > AddString ( " Breda " ) ;
2023-08-10 18:43:21 +02:00
break ;
2024-01-02 18:38:21 +01:00
case NA_AMERICAN :
2023-08-10 18:43:21 +02:00
default :
giveItem ( " weapons/bar.tik " ) ;
event - > AddString ( " BAR " ) ;
break ;
}
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " heavy " ) & & ! ( dmflags - > integer & DF_WEAPON_NO_ROCKET ) ) {
switch ( nationality ) {
case NA_GERMAN :
case NA_ITALIAN :
giveItem ( " weapons/panzerschreck.tik " ) ;
event - > AddString ( " Panzerschreck " ) ;
break ;
case NA_BRITISH :
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTT ) {
giveItem ( " weapons/bazooka.tik " ) ;
event - > AddString ( " Bazooka " ) ;
} else {
giveItem ( " weapons/Uk_W_Piat.tik " ) ;
event - > AddString ( " PIAT " ) ;
}
2023-08-10 18:43:21 +02:00
break ;
2024-01-02 18:38:21 +01:00
case NA_AMERICAN :
2023-08-10 18:43:21 +02:00
default :
giveItem ( " weapons/bazooka.tik " ) ;
event - > AddString ( " Bazooka " ) ;
break ;
}
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " shotgun " ) & & ! ( dmflags - > integer & DF_WEAPON_NO_SHOTGUN ) ) {
switch ( nationality ) {
case NA_BRITISH :
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTT ) {
giveItem ( " weapons/shotgun.tik " ) ;
event - > AddString ( " Shotgun " ) ;
} else {
giveItem ( " weapons/DeLisle.tik " ) ;
event - > AddString ( " DeLisle " ) ;
}
2023-08-10 18:43:21 +02:00
break ;
case NA_GERMAN :
2024-01-02 18:38:21 +01:00
if ( g_target_game < target_game_e : : TG_MOHTA | | dmflags - > integer & DF_DISALLOW_KAR98_MORTAR ) {
2023-08-10 18:43:21 +02:00
// Fallback to shotgun
2024-01-02 18:38:21 +01:00
// The shotgun is forced on older versions of the game
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/shotgun.tik " ) ;
event - > AddString ( " Shotgun " ) ;
} else {
giveItem ( " weapons/kar98_mortar.tik " ) ;
event - > AddString ( " Gewehrgranate " ) ;
}
break ;
2024-01-02 18:38:21 +01:00
case NA_AMERICAN :
2023-08-10 18:43:21 +02:00
default :
giveItem ( " weapons/shotgun.tik " ) ;
event - > AddString ( " Shotgun " ) ;
break ;
}
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " landmine " ) & & QueryLandminesAllowed ( ) ) {
//gi.Cvar_Get("g_rifles_for_sweepers", "0", 0);
switch ( nationality ) {
case NA_BRITISH :
giveItem ( " weapons/US_W_Minedetector.tik " ) ;
event - > AddString ( " Minedetector " ) ;
if ( g_rifles_for_sweepers - > integer ) {
// Give a lite version of the rifle
giveItem ( " weapons/enfield_lite.tik " ) ;
} else {
// Just give some ammo for the pistol
GiveAmmo ( " pistol " , 12 ) ;
}
break ;
case NA_RUSSIAN :
giveItem ( " weapons/US_W_Minedetector.tik " ) ;
event - > AddString ( " Minedetector " ) ;
if ( g_rifles_for_sweepers - > integer ) {
// Give a lite version of the rifle
giveItem ( " weapons/Mosin_Nagant_Rifle_lite.tik " ) ;
} else {
// Just give some ammo for the pistol
GiveAmmo ( " pistol " , 14 ) ;
}
break ;
case NA_GERMAN :
giveItem ( " weapons/Gr_W_Minedetector.tik " ) ;
event - > AddString ( " Minensuchgerat " ) ;
if ( g_rifles_for_sweepers - > integer ) {
// Give a lite version of the rifle
giveItem ( " weapons/kar98_lite.tik " ) ;
} else {
// Just give some ammo for the pistol
GiveAmmo ( " pistol " , 16 ) ;
}
break ;
2024-01-02 18:38:21 +01:00
case NA_AMERICAN :
2023-08-10 18:43:21 +02:00
default :
giveItem ( " weapons/US_W_Minedetector.tik " ) ;
event - > AddString ( " Minedetector " ) ;
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
if ( g_rifles_for_sweepers - > integer ) {
// Give a lite version of the rifle
giveItem ( " weapons/m1_garand_lite.tik " ) ;
} else {
// Just give some ammo for the pistol
GiveAmmo ( " pistol " , 14 ) ;
}
break ;
}
} else if ( ! ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ) {
switch ( nationality ) {
case NA_BRITISH :
giveItem ( " weapons/enfield.tik " ) ;
event - > AddString ( " Lee-Enfield " ) ;
break ;
case NA_RUSSIAN :
giveItem ( " weapons/Mosin_Nagant_Rifle.tik " ) ;
event - > AddString ( " Mosin Nagant Rifle " ) ;
break ;
case NA_GERMAN :
giveItem ( " weapons/kar98.tik " ) ;
event - > AddString ( " Mauser KAR 98K " ) ;
break ;
case NA_ITALIAN :
giveItem ( " weapons/it_w_carcano.tik " ) ;
event - > AddString ( " Carcano " ) ;
break ;
2024-01-02 18:38:21 +01:00
case NA_AMERICAN :
2023-08-10 18:43:21 +02:00
default :
giveItem ( " weapons/m1_garand.tik " ) ;
event - > AddString ( " M1 Garand " ) ;
break ;
}
2023-08-10 13:31:35 +02:00
}
2023-08-10 18:43:21 +02:00
// Make the player switch to the weapon some time after spawning
2023-08-13 16:11:25 +02:00
PostEvent ( event , 0.3f ) ;
2023-08-10 18:43:21 +02:00
//
// Pistols and grenades
//
switch ( nationality ) {
case NA_BRITISH :
giveItem ( " weapons/mills_grenade.tik " ) ;
2024-02-03 21:19:04 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
giveItem ( " weapons/M18_smoke_grenade.tik " ) ;
}
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/Webley_Revolver.tik " ) ;
break ;
case NA_RUSSIAN :
giveItem ( " weapons/Russian_F1_grenade.tik " ) ;
2024-02-03 21:19:04 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
giveItem ( " weapons/RDG-1_Smoke_grenade.tik " ) ;
}
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/Nagant_revolver.tik " ) ;
break ;
case NA_GERMAN :
giveItem ( " weapons/steilhandgranate.tik " ) ;
2024-02-03 21:19:04 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
giveItem ( " weapons/nebelhandgranate.tik " ) ;
}
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/p38.tik " ) ;
break ;
case NA_ITALIAN :
giveItem ( " weapons/it_w_bomba.tik " ) ;
2024-02-03 21:19:04 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
giveItem ( " weapons/it_w_bombabreda.tik " ) ;
}
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/it_w_beretta.tik " ) ;
break ;
default :
giveItem ( " weapons/m2frag_grenade.tik " ) ;
2024-02-03 21:19:04 +01:00
if ( g_target_game > = target_game_e : : TG_MOHTA ) {
giveItem ( " weapons/M18_smoke_grenade.tik " ) ;
}
2023-08-10 18:43:21 +02:00
giveItem ( " weapons/colt45.tik " ) ;
break ;
2023-08-10 13:31:35 +02:00
}
2023-08-10 18:43:21 +02:00
}
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
void Player : : EquipWeapons_ver8 ( )
{
// spectators should not have weapons
if ( IsSpectator ( ) ) {
FreeInventory ( ) ;
} else {
Event * ev = new Event ( " use " ) ;
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
if ( ! Q_stricmp ( client - > pers . dm_primary , " rifle " ) ) {
if ( dm_team = = TEAM_ALLIES ) {
giveItem ( " models/weapons/m1_garand.tik " ) ;
ev - > AddString ( " models/weapons/m1_garand.tik " ) ;
} else {
giveItem ( " models/weapons/kar98.tik " ) ;
ev - > AddString ( " models/weapons/kar98.tik " ) ;
2023-08-10 13:31:35 +02:00
}
2023-08-10 18:43:21 +02:00
GiveAmmo ( " rifle " , 100 ) ;
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " sniper " ) ) {
if ( dm_team = = TEAM_ALLIES ) {
giveItem ( " models/weapons/springfield.tik " ) ;
ev - > AddString ( " models/weapons/springfield.tik " ) ;
} else {
giveItem ( " models/weapons/kar98sniper.tik " ) ;
ev - > AddString ( " models/weapons/kar98sniper.tik " ) ;
}
2023-08-10 13:31:35 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " smg " ) ) {
2023-08-10 18:43:21 +02:00
if ( dm_team = = TEAM_ALLIES ) {
giveItem ( " models/weapons/thompsonsmg.tik " ) ;
ev - > AddString ( " models/weapons/thompsonsmg.tik " ) ;
} else {
giveItem ( " models/weapons/mp40.tik " ) ;
ev - > AddString ( " models/weapons/mp40.tik " ) ;
2023-08-10 13:31:35 +02:00
}
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " mg " ) ) {
2023-08-10 18:43:21 +02:00
if ( dm_team = = TEAM_ALLIES ) {
giveItem ( " models/weapons/bar.tik " ) ;
ev - > AddString ( " models/weapons/bar.tik " ) ;
} else {
giveItem ( " models/weapons/mp44.tik " ) ;
ev - > AddString ( " models/weapons/mp44.tik " ) ;
2023-08-10 13:31:35 +02:00
}
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " heavy " ) ) {
2023-08-10 18:43:21 +02:00
if ( dm_team = = TEAM_ALLIES ) {
giveItem ( " models/weapons/bazooka.tik " ) ;
ev - > AddString ( " models/weapons/bazooka.tik " ) ;
} else {
giveItem ( " models/weapons/panzerschreck.tik " ) ;
ev - > AddString ( " models/weapons/panzerschreck.tik " ) ;
2023-08-10 13:31:35 +02:00
}
2023-08-10 18:43:21 +02:00
} else if ( ! Q_stricmp ( client - > pers . dm_primary , " shotgun " ) ) {
giveItem ( " models/weapons/shotgun.tik " ) ;
ev - > AddString ( " models/weapons/shotgun.tik " ) ;
}
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
PostEvent ( ev , 0.3f ) ;
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
if ( dm_team = = TEAM_ALLIES ) {
giveItem ( " models/weapons/colt45.tik " ) ;
giveItem ( " models/weapons/m2frag_grenade.tik " ) ;
} else {
giveItem ( " models/weapons/p38.tik " ) ;
giveItem ( " models/weapons/steilhandgranate.tik " ) ;
2023-08-10 13:31:35 +02:00
}
2023-08-10 03:46:28 +02:00
2023-08-10 18:43:21 +02:00
giveItem ( " models/items/binoculars.tik " ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Spectator ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( ! IsSpectator ( ) ) {
respawn_time = level . time + 1.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
RemoveFromVehiclesAndTurrets ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 13:31:35 +02:00
m_bSpectator = ! m_bTempSpectator ;
2023-08-04 00:04:29 +02:00
m_iPlayerSpectating = 0 ;
2023-08-10 13:31:35 +02:00
takedamage = DAMAGE_NO ;
deadflag = DEAD_NO ;
2023-08-04 00:04:29 +02:00
health = max_health ;
2016-03-27 11:49:47 +02:00
2023-08-10 14:18:40 +02:00
client - > ps . feetfalling = 0 ;
2023-08-10 18:43:21 +02:00
movecontrol = MOVECONTROL_USER ;
2023-08-04 00:04:29 +02:00
client - > ps . pm_flags | = PMF_SPECTATING ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
EvaluateState ( statemap_Torso - > FindState ( " STAND " ) , statemap_Legs - > FindState ( " STAND " ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
setSolidType ( SOLID_NOT ) ;
setMoveType ( MOVETYPE_NOCLIP ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
FreeInventory ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
hideModel ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 13:31:35 +02:00
SetPlayerSpectateRandom ( ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
bool Player : : IsValidSpectatePlayer ( Player * pPlayer )
{
if ( g_gametype - > integer < = GT_FFA ) {
return true ;
}
2016-03-27 11:49:47 +02:00
2023-10-13 21:15:02 +02:00
if ( GetTeam ( ) < = TEAM_FREEFORALL ) {
2023-08-04 00:04:29 +02:00
return true ;
2023-10-13 21:15:02 +02:00
}
if ( g_forceteamspectate - > integer ) {
if ( ! GetDM_Team ( ) - > NumLivePlayers ( ) ) {
return true ;
}
if ( pPlayer - > GetTeam ( ) = = GetTeam ( ) ) {
return true ;
}
2023-08-04 00:04:29 +02:00
return false ;
}
2023-10-13 21:15:02 +02:00
return true ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-10 13:31:35 +02:00
void Player : : SetPlayerSpectate ( bool bNext )
2023-08-04 00:04:29 +02:00
{
int i ;
2023-08-10 13:31:35 +02:00
int dir ;
int num ;
2023-08-04 00:04:29 +02:00
gentity_t * ent ;
Player * pPlayer ;
2023-08-10 18:43:21 +02:00
if ( bNext ) {
2023-08-10 13:31:35 +02:00
dir = 1 ;
num = m_iPlayerSpectating ;
2023-08-10 18:43:21 +02:00
} else {
2023-08-10 13:31:35 +02:00
dir = - 1 ;
if ( m_iPlayerSpectating ) {
num = m_iPlayerSpectating - 2 ;
} else {
num = game . maxclients - 1 ;
}
}
2023-11-03 21:56:31 +01:00
for ( i = num ; i < game . maxclients & & i > = 0 ; i + = dir ) {
2023-08-10 13:31:35 +02:00
ent = & g_entities [ i ] ;
2023-08-10 14:18:40 +02:00
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2023-08-04 00:04:29 +02:00
2023-08-10 18:43:21 +02:00
pPlayer = ( Player * ) ent - > entity ;
2016-03-27 11:49:47 +02:00
2023-08-10 14:18:40 +02:00
if ( ! pPlayer - > IsDead ( ) & & ! pPlayer - > IsSpectator ( ) & & IsValidSpectatePlayer ( pPlayer ) ) {
m_iPlayerSpectating = i + 1 ;
client - > ps . camera_flags & = ~ CF_CAMERA_CUT_BIT ;
client - > ps . camera_flags | = ( client - > ps . camera_flags & CF_CAMERA_CUT_BIT ) ^ CF_CAMERA_CUT_BIT ;
return ;
}
}
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
if ( m_iPlayerSpectating ) {
2023-08-10 14:18:40 +02:00
m_iPlayerSpectating = 0 ;
SetPlayerSpectate ( bNext ) ;
}
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-10 03:46:28 +02:00
void Player : : SetPlayerSpectateRandom ( void )
{
2023-08-10 18:43:21 +02:00
Player * pPlayer ;
int i ;
int numvalid ;
int iRandom ;
2023-08-10 13:31:35 +02:00
numvalid = 0 ;
for ( i = 0 ; i < game . maxclients ; i + + ) {
2023-08-10 18:43:21 +02:00
gentity_t * ent = & g_entities [ i ] ;
2023-08-10 13:31:35 +02:00
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2023-08-10 18:43:21 +02:00
pPlayer = static_cast < Player * > ( ent - > entity ) ;
2023-08-10 13:31:35 +02:00
if ( ! pPlayer - > IsDead ( ) & & ! pPlayer - > IsSpectator ( ) & & IsValidSpectatePlayer ( pPlayer ) ) {
numvalid + + ;
}
}
2023-08-10 18:43:21 +02:00
if ( ! numvalid ) {
2023-08-10 13:31:35 +02:00
// There is no valid player to spectate
2023-10-13 21:15:02 +02:00
// Added in OPM.
// Clear the player spectating value
m_iPlayerSpectating = 0 ;
2023-08-10 13:31:35 +02:00
return ;
}
iRandom = ( int ) ( random ( ) * numvalid ) ;
2023-08-10 14:18:40 +02:00
for ( i = 0 ; i < game . maxclients ; i + + ) {
2023-08-10 18:43:21 +02:00
gentity_t * ent = & g_entities [ i ] ;
2023-08-10 14:18:40 +02:00
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
pPlayer = static_cast < Player * > ( ent - > entity ) ;
2023-08-10 14:18:40 +02:00
if ( ! pPlayer - > IsDead ( ) & & ! pPlayer - > IsSpectator ( ) & & IsValidSpectatePlayer ( pPlayer ) ) {
2023-08-10 13:31:35 +02:00
if ( ! iRandom ) {
m_iPlayerSpectating = i + 1 ;
2023-08-10 14:18:40 +02:00
client - > ps . camera_flags & = ~ CF_CAMERA_CUT_BIT ;
client - > ps . camera_flags | = ( client - > ps . camera_flags & CF_CAMERA_CUT_BIT ) ^ CF_CAMERA_CUT_BIT ;
2023-08-10 13:31:35 +02:00
break ;
}
iRandom - - ;
2023-08-10 14:18:40 +02:00
}
}
2023-08-10 03:46:28 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : GetSpectateFollowOrientation ( Player * pPlayer , Vector & vPos , Vector & vAng )
2023-08-10 03:46:28 +02:00
{
2023-08-10 14:18:40 +02:00
Vector forward , right , up ;
Vector vCamOfs ;
Vector start ;
trace_t trace ;
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
if ( ! g_spectatefollow_firstperson - > integer ) {
// spectating a player
vAng = pPlayer - > GetVAngles ( ) ;
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
AngleVectors ( vAng , forward , right , up ) ;
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
vCamOfs = pPlayer - > origin ;
vCamOfs [ 2 ] + = pPlayer - > viewheight ;
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
vCamOfs + = forward * g_spectatefollow_forward - > value ;
vCamOfs + = right * g_spectatefollow_right - > value ;
vCamOfs + = up * g_spectatefollow_up - > value ;
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
if ( pPlayer - > client - > ps . fLeanAngle ! = 0.0f ) {
2023-10-13 19:35:29 +02:00
vCamOfs + = pPlayer - > client - > ps . fLeanAngle * 0.65f * right ;
2023-08-10 14:18:40 +02:00
}
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
start = pPlayer - > origin ;
start [ 2 ] + = pPlayer - > maxs [ 2 ] - 2.0 ;
2023-08-10 13:31:35 +02:00
2023-08-10 14:18:40 +02:00
Vector vMins = Vector ( - 2 , - 2 , 2 ) ;
Vector vMaxs = Vector ( 2 , 2 , 2 ) ;
2023-08-10 13:31:35 +02:00
2023-08-10 18:43:21 +02:00
trace =
G_Trace ( start , vMins , vMaxs , vCamOfs , pPlayer , MASK_SHOT , false , " Player::GetSpectateFollowOrientation " ) ;
2023-08-10 13:31:35 +02:00
vAng [ 0 ] + = g_spectatefollow_pitch - > value * trace . fraction ;
vPos = trace . endpos ;
2023-08-10 14:18:40 +02:00
} else {
2023-08-10 13:31:35 +02:00
vAng = pPlayer - > angles ;
vPos = pPlayer - > origin ;
2023-08-10 14:18:40 +02:00
}
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : Spectator ( Event * ev )
2023-08-04 00:04:29 +02:00
{
client - > pers . dm_primary [ 0 ] = 0 ;
SetTeam ( TEAM_SPECTATOR ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : Leave_DM_Team ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-12-27 15:14:08 +01:00
// Fixed in OPM
// FIXME: should it be permanently disabled ?
2016-03-27 11:49:47 +02:00
#if 0
2023-08-04 00:04:29 +02:00
if ( current_team )
{
dmManager . LeaveTeam ( this ) ;
}
else
{
gi . centerprintf ( edict , gi . LV_ConvertString ( " You are not on a team " ) ) ;
}
2016-03-27 11:49:47 +02:00
# endif
}
2023-08-04 00:04:29 +02:00
void Player : : Join_DM_Team ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
teamtype_t team ;
str teamname ;
const char * join_message ;
2023-08-13 16:11:25 +02:00
Entity * ent ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
if ( ev - > isSubclassOf ( ConsoleEvent ) & & disable_team_change ) {
2024-09-29 18:49:24 +02:00
// Added in OPM
2024-09-22 19:59:10 +02:00
return ;
}
2023-08-04 00:04:29 +02:00
teamname = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! teamname . icmp ( " allies " ) ) {
team = TEAM_ALLIES ;
} else if ( ! teamname . icmp ( " axis " ) | | ! teamname . icmp ( " german " ) | | ! teamname . icmp ( " nazi " ) ) {
team = TEAM_AXIS ;
} else {
team = TEAM_AXIS ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( current_team & & current_team - > m_teamnumber = = team ) {
2023-08-13 16:11:25 +02:00
//
// don't switch if on same team
//
return ;
}
if ( deadflag & & deadflag ! = DEAD_DEAD ) {
// ignore team switching if the player is dying and not dead
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2024-09-29 18:49:24 +02:00
if ( ev - > isSubclassOf ( ConsoleEvent ) & & ! CheckCanSwitchTeam ( team ) ) {
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_fTeamSelectTime = level . time ;
SetTeam ( team ) ;
2023-08-13 16:11:25 +02:00
// Make sure to remove player from turret
RemoveFromVehiclesAndTurrets ( ) ;
//
// Since 2.0: Remove projectiles the player shot
//
for ( ent = G_NextEntity ( NULL ) ; ent ; ent = G_NextEntity ( ent ) ) {
if ( ent - > IsSubclassOfProjectile ( ) & & ent - > edict - > r . ownerNum = = edict - > r . ownerNum ) {
ent - > PostEvent ( EV_Remove , 0 ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( client - > pers . dm_primary [ 0 ] ) {
if ( IsSpectator ( ) ) {
2023-08-13 16:11:25 +02:00
if ( m_fSpawnTimeLeft ) {
m_bWaitingForRespawn = true ;
} else if ( AllowTeamRespawn ( ) ) {
EndSpectator ( ) ;
if ( deadflag ) {
deadflag = DEAD_DEAD ;
}
PostEvent ( EV_Player_Respawn , 0 ) ;
gi . centerprintf ( edict , " " ) ;
}
} else if ( g_gametype - > integer > = GT_TEAM ) {
client - > pers . dm_primary [ 0 ] = 0 ;
UserSelectWeapon ( false ) ;
Spectator ( ) ;
2023-08-04 00:04:29 +02:00
} else {
PostEvent ( EV_Player_Respawn , 0 ) ;
}
2023-08-13 16:11:25 +02:00
} else if ( IsSpectator ( ) ) {
UserSelectWeapon ( true ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-13 16:11:25 +02:00
if ( g_gametype - > integer > = GT_TEAM ) {
//
// in team game modes, display a message to indicate
// a player joined a team
//
2023-08-04 00:04:29 +02:00
if ( GetTeam ( ) = = TEAM_ALLIES ) {
join_message = " has joined the Allies " ;
} else if ( GetTeam ( ) = = TEAM_AXIS ) {
join_message = " has joined the Axis " ;
} else {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-14 20:44:28 +02:00
G_PrintToAllClients ( va ( " %s %s \n " , client - > pers . netname , gi . LV_ConvertString ( join_message ) ) , 2 ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Auto_Join_DM_Team ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Event * event = new Event ( EV_Player_JoinDMTeam ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( dmManager . GetAutoJoinTeam ( ) = = TEAM_AXIS ) {
event - > AddString ( " axis " ) ;
} else {
event - > AddString ( " allies " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ProcessEvent ( event ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 14:18:40 +02:00
teamtype_t Player : : GetTeam ( ) const
2023-08-04 00:04:29 +02:00
{
return dm_team ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : SetTeam ( teamtype_t team )
{
dmManager . JoinTeam ( this , team ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( dm_team = = TEAM_SPECTATOR ) {
Spectator ( ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetDM_Team ( DM_Team * team )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
current_team = team ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// clear the player's team
edict - > s . eFlags & = ~ EF_ANY_TEAM ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( team ) {
2023-08-10 03:46:28 +02:00
dm_team = static_cast < teamtype_t > ( team - > getNumber ( ) ) ;
2023-08-04 00:04:29 +02:00
if ( dm_team = = TEAM_ALLIES ) {
edict - > s . eFlags | = EF_ALLIES ;
} else if ( dm_team = = TEAM_AXIS ) {
edict - > s . eFlags | = EF_AXIS ;
}
} else {
dm_team = TEAM_NONE ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 18:49:57 +02:00
client - > pers . teamnum = dm_team ;
2023-08-10 03:46:28 +02:00
G_SetClientConfigString ( edict ) ;
2023-08-04 00:04:29 +02:00
if ( m_fTeamSelectTime ! = level . time & & ( edict - > s . eFlags & ( EF_ANY_TEAM ) ) ) {
InitModel ( ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
DM_Team * Player : : GetDM_Team ( )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
return current_team ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
bool Player : : IsSpectator ( void )
{
return ( m_bSpectator | | m_bTempSpectator ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : BeginFight ( void )
{
m_bAllowFighting = true ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : EndFight ( void )
{
m_bAllowFighting = false ;
2016-03-27 11:49:47 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : WarpToPoint ( Entity * spawnpoint )
2023-08-09 23:49:38 +02:00
{
2023-08-10 18:43:21 +02:00
if ( spawnpoint ) {
2023-08-09 23:49:38 +02:00
setOrigin ( spawnpoint - > origin + Vector ( 0 , 0 , 1 ) ) ;
setAngles ( spawnpoint - > angles ) ;
2023-08-10 14:18:40 +02:00
SetViewAngles ( angles ) ;
client - > ps . camera_flags & = ~ CF_CAMERA_CUT_BIT ;
client - > ps . camera_flags | = ( client - > ps . camera_flags & CF_CAMERA_CUT_BIT ) ^ CF_CAMERA_CUT_BIT ;
2023-08-09 23:49:38 +02:00
}
}
2023-08-04 00:04:29 +02:00
void Player : : UpdateStatus ( const char * s )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
gi . SendServerCommand ( edict - g_entities , " status \" %s \" " , s ) ;
}
2023-08-04 00:21:19 +02:00
void Player : : HUDPrint ( const char * s )
2023-08-04 00:04:29 +02:00
{
gi . SendServerCommand ( edict - g_entities , " hudprint \" %s \" \n " , s ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 18:43:21 +02:00
void Player : : GibEvent ( Event * ev )
2023-08-09 23:49:38 +02:00
{
2023-08-10 14:18:40 +02:00
qboolean hidemodel ;
2023-08-09 23:49:38 +02:00
2023-08-10 14:18:40 +02:00
hidemodel = ! ev - > GetInteger ( 1 ) ;
2023-08-09 23:49:38 +02:00
2023-08-10 14:18:40 +02:00
if ( com_blood - > integer ) {
if ( hidemodel ) {
2023-08-10 18:43:21 +02:00
gibbed = true ;
2023-08-10 14:18:40 +02:00
takedamage = DAMAGE_NO ;
setSolidType ( SOLID_NOT ) ;
hideModel ( ) ;
}
2023-08-09 23:49:38 +02:00
2023-08-10 14:18:40 +02:00
CreateGibs ( this , health , 0.75f , 3 ) ;
}
2023-08-09 23:49:38 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : ArmorDamage ( Event * ev )
2023-08-04 00:04:29 +02:00
{
int mod = ev - > GetInteger ( 9 ) ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
// players that are not allowed fighting mustn't take damage
if ( ! m_bAllowFighting & & mod ! = MOD_TELEFRAG ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
Player * attacker = ( Player * ) ev - > GetEntity ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( attacker & & attacker - > IsSubclassOfPlayer ( ) ) {
if ( attacker ! = this ) {
2024-10-02 17:02:48 +02:00
if ( g_gametype - > integer > = GT_TEAM & & ! g_teamdamage - > integer ) {
2023-08-04 00:04:29 +02:00
// check for team damage
if ( attacker - > GetDM_Team ( ) = = GetDM_Team ( ) & & mod ! = MOD_TELEFRAG ) {
return ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
pAttackerDistPointer = attacker ;
2023-08-04 00:21:19 +02:00
fAttackerDispTime = g_drawattackertime - > value + level . time ;
2023-08-04 00:04:29 +02:00
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_iNumHitsTaken + + ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
Sentient : : ArmorDamage ( ev ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
Event * event = new Event ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
event - > AddEntity ( ev - > GetEntity ( 1 ) ) ;
event - > AddFloat ( ev - > GetFloat ( 2 ) ) ;
event - > AddEntity ( ev - > GetEntity ( 3 ) ) ;
event - > AddVector ( ev - > GetVector ( 4 ) ) ;
event - > AddVector ( ev - > GetVector ( 5 ) ) ;
event - > AddVector ( ev - > GetVector ( 6 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 7 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 8 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 9 ) ) ;
event - > AddInteger ( ev - > GetInteger ( 10 ) ) ;
event - > AddEntity ( this ) ;
scriptedEvents [ SE_DAMAGE ] . Trigger ( event ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Disconnect ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:21:19 +02:00
Event * ev = new Event ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddListener ( this ) ;
scriptedEvents [ SE_DISCONNECTED ] . Trigger ( ev ) ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
dmManager . RemovePlayer ( this ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
void Player : : CallVote ( Event * ev )
2023-08-04 00:04:29 +02:00
{
str arg1 ;
str arg2 ;
2023-09-11 20:45:30 +02:00
int numVoters ;
2016-03-27 11:49:47 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! g_allowvote - > integer ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Voting not allowed here. " ) ) ) ;
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( level . m_voteTime ! = 0.0f ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " A vote is already in progress. " ) ) ) ;
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( votecount > = MAX_VOTE_COUNT ) {
2023-09-11 20:45:30 +02:00
if ( m_fLastVoteTime ) {
while ( m_fLastVoteTime < level . time & & votecount > 0 ) {
m_fLastVoteTime + = 60 ;
votecount - - ;
}
}
if ( votecount > = MAX_VOTE_COUNT ) {
2023-11-03 21:56:31 +01:00
HUDPrint (
va ( " %s %d %s. \n " ,
gi . LV_ConvertString ( " You cannot call another vote for " ) ,
( unsigned int ) ( m_fLastVoteTime - level . time + 1 ) ,
gi . LV_ConvertString ( " seconds " ) )
) ;
2023-09-11 20:45:30 +02:00
return ;
}
}
if ( IsSpectator ( ) | | IsDead ( ) ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " You are not allowed to call a vote as a spectator. " ) ) ) ;
2023-08-04 00:04:29 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
arg1 = ev - > GetString ( 1 ) ;
2023-09-11 20:45:30 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
arg2 = ev - > GetString ( 2 ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-09-11 20:45:30 +02:00
if ( ! atoi ( arg1 . c_str ( ) ) ) {
if ( strchr ( arg1 . c_str ( ) , ' ; ' ) | | strchr ( arg2 . c_str ( ) , ' ; ' ) ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid vote string. " ) ) ) ;
2023-09-11 20:45:30 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-09-11 20:45:30 +02:00
if ( Q_stricmp ( arg1 . c_str ( ) , " restart " ) & & Q_stricmp ( arg1 . c_str ( ) , " nextmap " ) & & Q_stricmp ( arg1 . c_str ( ) , " map " )
& & Q_stricmp ( arg1 . c_str ( ) , " g_gametype " ) & & Q_stricmp ( arg1 . c_str ( ) , " kick " )
& & Q_stricmp ( arg1 . c_str ( ) , " clientkick " ) & & Q_stricmp ( arg1 . c_str ( ) , " fraglimit " ) ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid vote string. " ) ) ) ;
2023-11-03 21:56:31 +01:00
HUDPrint ( va (
" %s restart, nextmap, map <mapname>, g_gametype <n>, fraglimit <n>, timelimit <n>, kick <player>, and "
2023-12-27 15:38:17 +01:00
" clientkick <player #>. \n " ,
2023-11-03 21:56:31 +01:00
gi . LV_ConvertString ( " Vote commands are: " )
) ) ;
2016-03-27 11:49:47 +02:00
2023-09-11 20:45:30 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-09-11 20:45:30 +02:00
if ( ! Q_stricmp ( arg1 . c_str ( ) , " kick " ) ) {
//
// check for a valid player
//
2023-11-03 21:56:31 +01:00
gentity_t * ent ;
2023-09-11 20:45:30 +02:00
int i ;
2016-03-27 11:49:47 +02:00
2023-09-11 20:45:30 +02:00
for ( i = 0 ; i < game . maxclients ; i + + ) {
ent = & g_entities [ i ] ;
2016-03-27 11:49:47 +02:00
2023-09-11 20:45:30 +02:00
if ( ! ent - > inuse | | ! ent - > client | | ! ent - > entity ) {
continue ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-09-11 20:45:30 +02:00
if ( ! Q_stricmp ( ent - > client - > pers . netname , arg2 . c_str ( ) ) ) {
// Prevent the player from kicking himself out
if ( ent - > entity = = this ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " You are not allowed to kick yourself. " ) ) ) ;
2023-09-11 20:45:30 +02:00
return ;
}
break ;
}
}
if ( i = = game . maxclients ) {
2024-01-02 00:43:27 +01:00
HUDPrint ( va ( " %s %s \n " , arg2 . c_str ( ) , gi . LV_ConvertString ( " is not a valid player name to kick. " ) ) ) ;
2023-12-27 15:14:08 +01:00
return ;
2023-09-11 20:45:30 +02:00
}
2023-11-03 21:56:31 +01:00
} else if ( ! Q_stricmp ( arg1 . c_str ( ) , " map " ) & & * sv_nextmap - > string ) {
2023-09-11 20:45:30 +02:00
level . m_voteString = va ( " %s %s; set next map \" %s \" " , arg1 . c_str ( ) , arg2 . c_str ( ) , arg2 . c_str ( ) ) ;
2023-11-03 21:56:31 +01:00
} else {
2023-09-11 20:45:30 +02:00
level . m_voteString = va ( " %s %s " , arg1 . c_str ( ) , arg2 . c_str ( ) ) ;
}
2023-09-12 20:08:19 +02:00
if ( level . m_nextVoteTime ) {
level . m_nextVoteTime = 0 ;
2023-09-11 20:45:30 +02:00
gi . SendConsoleCommand ( va ( " %s " , level . m_voteString . c_str ( ) ) ) ;
}
if ( ! Q_stricmp ( arg1 . c_str ( ) , " g_gametype " ) ) {
int gametypeNum ;
// get the gametype number
gametypeNum = atoi ( arg2 . c_str ( ) ) ;
if ( gametypeNum < = GT_SINGLE_PLAYER | | gametypeNum > = GT_MAX_GAME_TYPE ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid gametype for a vote. " ) ) ) ;
2023-09-11 20:45:30 +02:00
return ;
}
level . m_voteString = va ( " %s %i " , arg1 . c_str ( ) , gametypeNum ) ;
switch ( gametypeNum ) {
case GT_FFA :
level . m_voteName = " Game Type Free-For-All " ;
break ;
case GT_TEAM :
level . m_voteName = " Game Type Match " ;
break ;
case GT_TEAM_ROUNDS :
level . m_voteName = " Game Type Round-Based-Match " ;
break ;
case GT_OBJECTIVE :
level . m_voteName = " Game Type Objective-Match " ;
break ;
case GT_TOW :
level . m_voteName = " Game Type Tug of War " ;
break ;
case GT_LIBERATION :
level . m_voteName = " Game Type Liberation " ;
2023-08-04 00:04:29 +02:00
break ;
2023-09-11 20:45:30 +02:00
default :
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s %s %d \n " , gi . LV_ConvertString ( " Game Type " ) , arg1 . c_str ( ) , gametypeNum ) ) ;
2023-09-11 20:45:30 +02:00
return ;
2023-08-04 00:04:29 +02:00
}
2023-11-03 21:56:31 +01:00
} else if ( ! Q_stricmp ( arg1 . c_str ( ) , " map " ) ) {
2023-09-11 20:45:30 +02:00
if ( * sv_nextmap - > string ) {
level . m_voteString = va ( " %s %s; set nextmap \" %s \" " , arg1 . c_str ( ) , arg2 . c_str ( ) , sv_nextmap - > string ) ;
2023-11-03 21:56:31 +01:00
} else {
2023-09-11 20:45:30 +02:00
level . m_voteString = va ( " %s %s " , arg1 . c_str ( ) , arg2 . c_str ( ) ) ;
}
2023-08-04 00:04:29 +02:00
2023-09-11 20:45:30 +02:00
level . m_voteName = va ( " Map %s " , arg2 . c_str ( ) ) ;
2023-11-03 21:56:31 +01:00
} else {
2023-09-11 20:45:30 +02:00
level . m_voteString = va ( " %s %s " , arg1 . c_str ( ) , arg2 . c_str ( ) ) ;
2023-11-03 21:56:31 +01:00
level . m_voteName = level . m_voteString ;
2023-08-04 00:04:29 +02:00
}
2023-08-04 00:21:19 +02:00
} else {
2023-11-03 21:56:31 +01:00
int voteIndex ;
int subListIndex ;
str voteOptionCommand ;
str voteOptionSubCommand ;
str voteOptionName ;
str voteOptionSubName ;
2023-09-11 20:45:30 +02:00
voteoptiontype_t optionType ;
2023-11-03 21:56:31 +01:00
2023-09-11 20:45:30 +02:00
union {
2023-11-03 21:56:31 +01:00
int optionInteger ;
2023-09-11 20:45:30 +02:00
float optionFloat ;
2023-11-03 21:56:31 +01:00
int optionClientNum ;
2023-09-11 20:45:30 +02:00
} ;
2023-11-03 21:56:31 +01:00
gentity_t * ent ;
2023-09-11 20:45:30 +02:00
char buffer [ 64 ] ;
voteIndex = atoi ( arg1 . c_str ( ) ) ;
if ( ! level . GetVoteOptionMain ( voteIndex , & voteOptionCommand , & optionType ) ) {
2023-12-27 15:38:17 +01:00
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid vote option. " ) ) ) ;
2023-09-11 20:45:30 +02:00
return ;
}
level . GetVoteOptionMainName ( voteIndex , & voteOptionName ) ;
switch ( optionType ) {
case VOTE_NO_CHOICES :
level . m_voteString = voteOptionCommand ;
2023-11-03 21:56:31 +01:00
level . m_voteName = voteOptionName ;
2023-09-11 20:45:30 +02:00
break ;
case VOTE_OPTION_LIST :
subListIndex = atoi ( arg2 . c_str ( ) ) ;
if ( ! level . GetVoteOptionSub ( voteIndex , subListIndex , & voteOptionSubCommand ) ) {
2023-11-03 21:56:31 +01:00
HUDPrint (
va ( " %s %i %s \" %s \" . \n " ,
gi . LV_ConvertString ( " Invalid vote choice " ) ,
subListIndex ,
gi . LV_ConvertString ( " for vote option " ) ,
voteOptionName . c_str ( ) )
) ;
2023-09-11 20:45:30 +02:00
return ;
}
level . m_voteString = va ( " %s %s " , voteOptionCommand . c_str ( ) , voteOptionSubCommand . c_str ( ) ) ;
// get the sub-option name
level . GetVoteOptionSubName ( voteIndex , subListIndex , & voteOptionSubName ) ;
2023-11-03 21:56:31 +01:00
level . m_voteName =
va ( " %s %s " , gi . LV_ConvertString ( voteOptionName . c_str ( ) ) , gi . LV_ConvertString ( voteOptionSubName . c_str ( ) )
) ;
2023-09-11 20:45:30 +02:00
break ;
case VOTE_OPTION_TEXT :
if ( strchr ( arg2 . c_str ( ) , ' ; ' ) ) {
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid vote text entered. " ) ) ) ;
return ;
}
level . m_voteString = va ( " %s %s " , voteOptionCommand . c_str ( ) , arg2 . c_str ( ) ) ;
2023-11-03 21:56:31 +01:00
level . m_voteName = va ( " %s %s " , gi . LV_ConvertString ( voteOptionName . c_str ( ) ) , arg2 . c_str ( ) ) ;
2023-09-11 20:45:30 +02:00
break ;
case VOTE_OPTION_INTEGER :
optionInteger = atoi ( arg2 . c_str ( ) ) ;
Com_sprintf ( buffer , sizeof ( buffer ) , " %d " , optionInteger ) ;
if ( Q_stricmp ( buffer , arg2 . c_str ( ) ) ) {
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid vote integer entered. " ) ) ) ;
return ;
}
level . m_voteString = va ( " %s %i " , voteOptionCommand . c_str ( ) , optionInteger ) ;
2023-11-03 21:56:31 +01:00
level . m_voteName = va ( " %s %i " , gi . LV_ConvertString ( voteOptionName . c_str ( ) ) , optionInteger ) ;
2023-09-11 20:45:30 +02:00
break ;
case VOTE_OPTION_FLOAT :
optionFloat = atof ( arg2 . c_str ( ) ) ;
2023-09-24 23:37:26 +02:00
Com_sprintf ( buffer , sizeof ( buffer ) , " %f " , optionFloat ) ;
2023-09-11 20:45:30 +02:00
if ( Q_stricmp ( buffer , arg2 . c_str ( ) ) ) {
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid vote float entered. " ) ) ) ;
return ;
}
level . m_voteString = va ( " %s %g " , voteOptionCommand . c_str ( ) , optionFloat ) ;
2023-11-03 21:56:31 +01:00
level . m_voteName = va ( " %s %g " , gi . LV_ConvertString ( voteOptionName . c_str ( ) ) , optionFloat ) ;
2023-09-11 20:45:30 +02:00
break ;
case VOTE_OPTION_CLIENT :
case VOTE_OPTION_CLIENT_NOT_SELF :
optionClientNum = atoi ( arg2 . c_str ( ) ) ;
if ( optionClientNum < 0 | | optionClientNum > = game . maxclients ) {
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Invalid client number for a vote. " ) ) ) ;
return ;
}
ent = & g_entities [ optionClientNum ] ;
if ( ! ent - > inuse | | ! ent - > client | | ! ent - > entity ) {
HUDPrint ( va ( " %s \n " , gi . LV_ConvertString ( " Client selected for the vote is not connected. " ) ) ) ;
return ;
}
level . m_voteString = va ( " %s %i " , voteOptionCommand . c_str ( ) , optionClientNum ) ;
2023-11-03 21:56:31 +01:00
level . m_voteName =
va ( " %s #%i: %s " , gi . LV_ConvertString ( voteOptionName . c_str ( ) ) , optionClientNum , ent - > client - > pers . netname
) ;
2023-09-11 20:45:30 +02:00
break ;
default :
level . GetVoteOptionMainName ( voteIndex , & voteOptionName ) ;
2023-11-03 21:56:31 +01:00
gi . Printf (
" ERROR: Vote option ( \" %s \" \" %s \" ) with unknown vote option type \n " ,
voteOptionName . c_str ( ) ,
voteOptionCommand . c_str ( )
) ;
2023-09-11 20:45:30 +02:00
return ;
}
2023-08-04 00:04:29 +02:00
}
2023-09-11 20:45:30 +02:00
G_PrintToAllClients ( va ( " %s %s. \n " , client - > pers . netname , gi . LV_ConvertString ( " called a vote " ) ) ) ;
2023-08-04 00:04:29 +02:00
2023-09-11 20:45:30 +02:00
level . m_voteTime = ( level . svsFloatTime - level . svsStartFloatTime ) * 1000 ;
2023-11-03 21:56:31 +01:00
level . m_voteYes = 1 ;
level . m_voteNo = 0 ;
2023-08-04 00:04:29 +02:00
// Reset all player's vote
2023-09-11 20:45:30 +02:00
numVoters = 0 ;
2023-08-04 00:04:29 +02:00
for ( int i = 0 ; i < game . maxclients ; i + + ) {
2023-11-03 21:56:31 +01:00
gentity_t * ent = & g_entities [ i ] ;
2023-08-04 00:04:29 +02:00
if ( ! ent - > client | | ! ent - > inuse ) {
continue ;
}
2023-11-03 21:56:31 +01:00
Player * p = ( Player * ) ent - > entity ;
p - > voted = false ;
2023-09-11 20:45:30 +02:00
numVoters + + ;
2023-08-04 00:04:29 +02:00
}
2023-09-11 20:45:30 +02:00
level . m_numVoters = numVoters ;
2023-11-03 21:56:31 +01:00
client - > ps . voted = true ;
voted = true ;
2023-08-04 00:04:29 +02:00
votecount + + ;
2023-09-11 20:45:30 +02:00
m_fLastVoteTime = level . time + 60 ;
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
//
// clients below version 2.0 don't support vote cs
//
gi . setConfigstring ( CS_VOTE_TIME , va ( " %i " , level . m_voteTime ) ) ;
gi . setConfigstring ( CS_VOTE_STRING , level . m_voteName . c_str ( ) ) ;
gi . setConfigstring ( CS_VOTE_YES , va ( " %i " , level . m_voteYes ) ) ;
gi . setConfigstring ( CS_VOTE_NO , va ( " %i " , level . m_voteNo ) ) ;
gi . setConfigstring ( CS_VOTE_UNDECIDED , va ( " %i " , level . m_numVoters - ( level . m_voteYes + level . m_voteNo ) ) ) ;
}
2023-08-04 00:04:29 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : Vote ( Event * ev )
2023-08-04 00:04:29 +02:00
{
2023-09-12 00:01:07 +02:00
str arg1 ;
2023-08-04 00:04:29 +02:00
if ( level . m_voteTime = = 0.0f ) {
HUDPrint ( gi . LV_ConvertString ( " No vote in progress. " ) ) ;
return ;
}
2023-09-12 00:01:07 +02:00
if ( client - > ps . voted ) {
2023-08-04 00:04:29 +02:00
HUDPrint ( gi . LV_ConvertString ( " Vote already cast. " ) ) ;
return ;
}
if ( ev - > NumArgs ( ) ! = 1 ) {
HUDPrint ( va ( " %s: vote <1|0|y|n> " , gi . LV_ConvertString ( " Usage " ) ) ) ;
return ;
}
HUDPrint ( gi . LV_ConvertString ( " Vote cast. " ) ) ;
2023-09-12 00:01:07 +02:00
client - > ps . voted = true ;
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
arg1 = ev - > GetString ( 1 ) ;
2023-09-12 00:01:07 +02:00
voted = ( arg1 [ 0 ] = = ' y ' ) | | ( arg1 [ 0 ] = = ' Y ' ) | | ( arg1 [ 0 ] = = ' 1 ' ) ;
2023-08-04 00:04:29 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : RetrieveVoteOptions ( Event * ev )
2023-08-10 03:46:28 +02:00
{
2023-08-10 18:43:21 +02:00
if ( m_fNextVoteOptionTime > level . time ) {
2023-08-10 14:18:40 +02:00
gi . SendServerCommand ( edict - g_entities , " vo0 \" \" \n " ) ;
gi . SendServerCommand ( edict - g_entities , " vo2 \" \" \n " ) ;
2023-08-10 18:43:21 +02:00
} else {
2023-08-10 14:18:40 +02:00
m_fNextVoteOptionTime = level . time + 2.0 ;
level . SendVoteOptionsFile ( edict ) ;
2023-08-10 13:31:35 +02:00
}
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : EventPrimaryDMWeapon ( Event * ev )
2023-08-04 00:04:29 +02:00
{
str dm_weapon = ev - > GetString ( 1 ) ;
2023-11-14 00:49:32 +01:00
bool bIsBanned = false ;
if ( ! dm_weapon . length ( ) ) {
// Added in OPM.
// Prevent the player from cheating by going into spectator
return ;
}
2023-08-04 00:04:29 +02:00
if ( ! str : : icmp ( dm_weapon , " shotgun " ) ) {
bIsBanned = ( dmflags - > integer & DF_WEAPON_NO_SHOTGUN ) ;
2023-08-04 00:21:19 +02:00
} else if ( ! str : : icmp ( dm_weapon , " rifle " ) ) {
2023-08-04 00:04:29 +02:00
bIsBanned = ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ;
2023-08-04 00:21:19 +02:00
} else if ( ! str : : icmp ( dm_weapon , " sniper " ) ) {
2023-08-04 00:04:29 +02:00
bIsBanned = ( dmflags - > integer & DF_WEAPON_NO_SNIPER ) ;
2023-08-04 00:21:19 +02:00
} else if ( ! str : : icmp ( dm_weapon , " smg " ) ) {
2023-08-04 00:04:29 +02:00
bIsBanned = ( dmflags - > integer & DF_WEAPON_NO_SMG ) ;
2023-08-04 00:21:19 +02:00
} else if ( ! str : : icmp ( dm_weapon , " mg " ) ) {
2023-08-04 00:04:29 +02:00
bIsBanned = ( dmflags - > integer & DF_WEAPON_NO_MG ) ;
2023-08-04 00:21:19 +02:00
} else if ( ! str : : icmp ( dm_weapon , " heavy " ) ) {
2023-08-04 00:04:29 +02:00
bIsBanned = ( dmflags - > integer & DF_WEAPON_NO_ROCKET ) ;
2023-08-04 00:21:19 +02:00
} else if ( ! str : : icmp ( dm_weapon , " landmine " ) ) {
2023-08-04 00:04:29 +02:00
bIsBanned = ( dmflags - > integer & DF_WEAPON_NO_LANDMINE ) | | ! QueryLandminesAllowed ( ) ;
2024-10-02 16:52:22 +02:00
} else if ( ! str : : icmp ( dm_weapon , " auto " ) ) {
const char * primaryList [ 7 ] ;
size_t numPrimaries = 0 ;
//
// Added in OPM
// Choose a random allowed weapon
//
if ( ! ( dmflags - > integer & DF_WEAPON_NO_SHOTGUN ) ) { primaryList [ numPrimaries + + ] = " shotgun " ; }
if ( ! ( dmflags - > integer & DF_WEAPON_NO_RIFLE ) ) { primaryList [ numPrimaries + + ] = " rifle " ; }
if ( ! ( dmflags - > integer & DF_WEAPON_NO_SNIPER ) ) { primaryList [ numPrimaries + + ] = " sniper " ; }
if ( ! ( dmflags - > integer & DF_WEAPON_NO_SMG ) ) { primaryList [ numPrimaries + + ] = " smg " ; }
if ( ! ( dmflags - > integer & DF_WEAPON_NO_MG ) ) { primaryList [ numPrimaries + + ] = " mg " ; }
if ( ! ( dmflags - > integer & DF_WEAPON_NO_ROCKET ) ) { primaryList [ numPrimaries + + ] = " heavy " ; }
if ( ! ( dmflags - > integer & DF_WEAPON_NO_LANDMINE ) & & QueryLandminesAllowed ( ) ) { primaryList [ numPrimaries + + ] = " landmine " ; }
if ( numPrimaries ) {
dm_weapon = primaryList [ rand ( ) % numPrimaries ] ;
} else {
bIsBanned = qtrue ;
}
2023-08-04 00:04:29 +02:00
}
if ( bIsBanned ) {
gi . SendServerCommand (
edict - g_entities , " print \" " HUD_MESSAGE_WHITE " %s \n \" " , " That weapon is currently banned. "
) ;
return ;
}
Q_strncpyz ( client - > pers . dm_primary , dm_weapon . c_str ( ) , sizeof ( client - > pers . dm_primary ) ) ;
if ( m_bSpectator ) {
2023-08-10 03:46:28 +02:00
if ( current_team & & ( current_team - > m_teamnumber = = TEAM_AXIS | | current_team - > m_teamnumber = = TEAM_ALLIES ) ) {
2023-08-04 00:04:29 +02:00
if ( m_fSpawnTimeLeft ) {
m_bWaitingForRespawn = true ;
2023-08-04 00:21:19 +02:00
} else if ( AllowTeamRespawn ( ) ) {
2023-08-04 00:04:29 +02:00
EndSpectator ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( deadflag ) {
deadflag = DEAD_DEAD ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
PostEvent ( EV_Player_Respawn , 0 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
gi . centerprintf ( edict , " " ) ;
}
2023-08-04 00:21:19 +02:00
} else {
2023-08-04 00:04:29 +02:00
gi . SendServerCommand ( edict - g_entities , " stufftext \" wait 250;pushmenu_teamselect \" " ) ;
}
2023-08-04 00:21:19 +02:00
} else {
2023-08-04 00:04:29 +02:00
gi . SendServerCommand (
edict - g_entities , " print \" " HUD_MESSAGE_WHITE " %s \n \" " , " Will switch to new weapon next time you respawn "
) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : DeadBody ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:14 +02:00
Body * body ;
if ( knockdown ) {
return ;
}
knockdown = true ;
body = new Body ;
body - > setModel ( model ) ;
for ( int i = 0 ; i < MAX_FRAMEINFOS ; i + + ) {
body - > edict - > s . frameInfo [ i ] = edict - > s . frameInfo [ i ] ;
}
body - > edict - > s . actionWeight = edict - > s . actionWeight ;
body - > edict - > s . scale = edict - > s . scale ;
body - > setOrigin ( origin ) ;
body - > setAngles ( angles ) ;
body - > edict - > s . eFlags & = ~ ( EF_AXIS | EF_ALLIES ) ;
if ( GetTeam ( ) = = TEAM_ALLIES ) {
edict - > s . eFlags | = EF_ALLIES ;
} else if ( GetTeam ( ) = = TEAM_AXIS ) {
edict - > s . eFlags | = EF_AXIS ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : WonMatch ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
num_won_matches + + ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : LostMatch ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
num_lost_matches + + ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 18:43:21 +02:00
void Player : : ArmWithWeapons ( Event * ev )
2023-08-10 03:46:28 +02:00
{
EquipWeapons ( ) ;
}
2023-08-10 18:43:21 +02:00
void Player : : EventGetCurrentDMWeaponType ( Event * ev )
2023-08-10 03:46:28 +02:00
{
ev - > AddString ( GetCurrentDMWeaponType ( ) ) ;
}
2023-08-04 00:21:19 +02:00
void Player : : PhysicsOff ( Event * ev )
2023-08-04 00:04:29 +02:00
{
2024-06-03 20:29:41 +02:00
if ( g_target_game > TG_MOH | | g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
// Added in 2.0
// Reset the state to STAND before disabling physics
EvaluateState ( statemap_Torso - > FindState ( " STAND " ) , statemap_Legs - > FindState ( " STAND " ) ) ;
}
2024-02-23 21:12:23 +01:00
2023-08-04 00:04:29 +02:00
flags | = FL_IMMOBILE ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : PhysicsOn ( Event * ev )
2023-08-04 00:04:29 +02:00
{
flags & = ~ FL_IMMOBILE ;
2016-03-27 11:49:47 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : GetIsSpectator ( Event * ev )
2023-08-10 03:46:28 +02:00
{
2023-08-10 14:18:40 +02:00
ev - > AddInteger ( IsSpectator ( ) ) ;
2023-08-10 03:46:28 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : EventSetInJail ( Event * ev )
2023-08-10 03:46:28 +02:00
{
m_bIsInJail = ev - > GetBoolean ( 1 ) ;
}
bool Player : : IsInJail ( ) const
{
return m_bIsInJail ;
}
2023-08-10 18:43:21 +02:00
void Player : : EventGetInJail ( Event * ev )
2023-08-10 03:46:28 +02:00
{
ev - > AddInteger ( m_bIsInJail ) ;
}
2023-08-10 18:43:21 +02:00
void Player : : GetNationalityPrefix ( Event * ev )
2023-08-10 03:46:28 +02:00
{
2023-08-10 13:31:35 +02:00
nationality_t nationality ;
2023-08-10 14:18:40 +02:00
if ( GetTeam ( ) = = TEAM_AXIS ) {
2023-11-14 00:49:32 +01:00
nationality = GetPlayerAxisTeamType ( client - > pers . dm_playergermanmodel ) ;
2023-08-10 13:31:35 +02:00
} else {
2023-11-14 00:49:32 +01:00
nationality = GetPlayerAlliedTeamType ( client - > pers . dm_playermodel ) ;
2023-08-10 13:31:35 +02:00
}
2023-08-10 18:43:21 +02:00
switch ( nationality ) {
2023-08-10 13:31:35 +02:00
case NA_RUSSIAN :
ev - > AddString ( " dfrru " ) ;
2023-08-10 14:18:40 +02:00
break ;
case NA_ITALIAN :
ev - > AddString ( " denit " ) ;
break ;
case NA_BRITISH :
ev - > AddString ( " dfruk " ) ;
break ;
case NA_AMERICAN :
ev - > AddString ( " dfr " ) ;
break ;
2023-08-10 13:31:35 +02:00
case NA_NONE :
2023-08-10 14:18:40 +02:00
default :
ev - > AddString ( " dfr " ) ;
break ;
2023-08-10 13:31:35 +02:00
}
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : GetIsDisguised ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( m_bIsDisguised ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : GetHasDisguise ( Event * ev )
2023-08-04 00:04:29 +02:00
{
ev - > AddInteger ( m_bHasDisguise ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : SetHasDisguise ( Event * ev )
2023-08-04 00:04:29 +02:00
{
m_bHasDisguise = ev - > GetBoolean ( 1 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : SetObjectiveCount ( Event * ev )
2023-08-04 00:04:29 +02:00
{
m_iObjectivesCompleted = ev - > GetInteger ( 1 ) ;
2023-08-04 00:21:19 +02:00
m_iNumObjectives = ev - > GetInteger ( 2 ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : Stats ( Event * ev )
2023-08-04 00:04:29 +02:00
{
2023-08-10 18:43:21 +02:00
char entry [ 2048 ] ;
int i ;
str szPreferredWeapon ;
str szGunneryEvaluation ;
int iNumHeadShots ;
int iNumTorsoShots ;
int iNumLeftLegShots ;
int iNumRightLegShots ;
int iNumGroinShots ;
int iNumLeftArmShots ;
int iNumRightArmShots ;
int iNumShotsFired ;
int iNumHits ;
int iBestNumHits ;
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
// Only works in singleplayer
return ;
}
szPreferredWeapon = " none " ;
szGunneryEvaluation = " none " ;
iNumHeadShots = m_iNumHeadShots ;
iNumTorsoShots = m_iNumTorsoShots ;
iNumLeftLegShots = m_iNumLeftLegShots ;
iNumRightLegShots = m_iNumRightLegShots ;
iNumGroinShots = m_iNumGroinShots ;
iNumLeftArmShots = m_iNumLeftArmShots ;
iNumRightArmShots = m_iNumRightArmShots ;
iNumShotsFired = m_iNumShotsFired ;
iNumHits = m_iNumHits ;
iBestNumHits = 0 ;
for ( i = 1 ; i < = inventory . NumObjects ( ) ; i + + ) {
Entity * pEnt = G_GetEntity ( inventory . ObjectAt ( i ) ) ;
if ( pEnt - > IsSubclassOfWeapon ( ) ) {
Weapon * pWeap = static_cast < Weapon * > ( pEnt ) ;
iNumHeadShots + = pWeap - > m_iNumHeadShots ;
iNumTorsoShots + = pWeap - > m_iNumTorsoShots ;
iNumLeftLegShots + = pWeap - > m_iNumLeftLegShots ;
iNumRightLegShots + = pWeap - > m_iNumRightLegShots ;
iNumGroinShots + = pWeap - > m_iNumGroinShots ;
iNumLeftArmShots + = pWeap - > m_iNumLeftArmShots ;
iNumRightArmShots + = pWeap - > m_iNumRightArmShots ;
iNumShotsFired + = pWeap - > m_iNumShotsFired ;
iNumHits + = pWeap - > m_iNumHits ;
if ( pWeap - > m_iNumHits > iBestNumHits ) {
szPreferredWeapon = pWeap - > item_name ;
iBestNumHits = pWeap - > m_iNumHits ;
}
}
}
2024-04-22 16:48:24 +02:00
if ( m_sPerferredWeaponOverride . length ( ) ) {
szPreferredWeapon = m_sPerferredWeaponOverride ;
}
2023-08-10 18:43:21 +02:00
if ( iNumHits ) {
Com_sprintf (
entry ,
sizeof ( entry ) ,
" %i %i %i %i %.1f \" %s \" %i %i %i \" %.1f \" \" %.1f \" \" %.1f \" \" %.1f \" \" %.1f \" \" %.1f \" \" %.1f \" \" %s \" %i "
" %i %i " ,
m_iNumObjectives ,
m_iObjectivesCompleted ,
iNumShotsFired ,
iNumHits ,
( iNumHits / iNumShotsFired * 100.f ) ,
szPreferredWeapon . c_str ( ) ,
m_iNumHitsTaken ,
m_iNumObjectsDestroyed ,
m_iNumEnemiesKilled ,
iNumHeadShots * 100.f / iNumHits ,
iNumTorsoShots * 100.f / iNumHits ,
iNumLeftLegShots * 100.f / iNumHits ,
iNumRightLegShots * 100.f / iNumHits ,
iNumGroinShots * 100.f / iNumHits ,
iNumLeftArmShots * 100.f / iNumHits ,
iNumRightArmShots * 100.f / iNumHits ,
szGunneryEvaluation . c_str ( ) ,
g_gotmedal - > integer ,
g_success - > integer ,
g_failed - > integer
) ;
} else {
Com_sprintf (
entry ,
sizeof ( entry ) ,
" %i %i %i %i %i \" %s \" %i %i %i \" %i \" \" %i \" \" %i \" \" %i \" \" %i \" \" %i \" \" %i \" \" %s \" %i %i %i " ,
m_iNumObjectives ,
m_iObjectivesCompleted ,
iNumShotsFired ,
0 ,
0 ,
szPreferredWeapon . c_str ( ) ,
m_iNumHitsTaken ,
m_iNumObjectsDestroyed ,
m_iNumEnemiesKilled ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
szGunneryEvaluation . c_str ( ) ,
g_gotmedal - > integer ,
g_success - > integer ,
g_failed - > integer
) ;
}
gi . SendServerCommand ( edict - g_entities , " stats %s " , entry ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
void Player : : EventStuffText ( Event * ev )
{
if ( level . spawning ) {
Event * event = new Event ( EV_Player_StuffText ) ;
event - > AddValue ( ev - > GetValue ( 1 ) ) ;
PostEvent ( event , level . frametime , 0 ) ;
} else {
gi . SendServerCommand ( edict - g_entities , " stufftext \" %s \" " , ev - > GetString ( 1 ) . c_str ( ) ) ;
}
}
void Player : : EventSetVoiceType ( Event * ev )
{
str sVoiceName = ev - > GetString ( 1 ) ;
2024-09-16 18:09:56 +02:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
if ( ! sVoiceName . icmp ( " american " ) ) {
m_voiceType = PVT_ALLIED_AMERICAN ;
} else if ( ! sVoiceName . icmp ( " british " ) ) {
m_voiceType = PVT_ALLIED_BRITISH ;
} else if ( ! sVoiceName . icmp ( " russian " ) ) {
m_voiceType = PVT_ALLIED_RUSSIAN ;
} else if ( ! sVoiceName . icmp ( " german " ) ) {
m_voiceType = PVT_AXIS_GERMAN ;
} else if ( ! sVoiceName . icmp ( " italian " ) ) {
m_voiceType = PVT_AXIS_ITALIAN ;
} else {
m_voiceType = PVT_NONE_SET ;
}
2023-08-04 00:04:29 +02:00
} else {
2024-09-16 18:09:56 +02:00
if ( ! sVoiceName . icmp ( " airborne " ) ) {
m_voiceType = PVT_ALLIED_AIRBORNE ;
} else if ( ! sVoiceName . icmp ( " manon " ) ) {
m_voiceType = PVT_ALLIED_MANON ;
} else if ( ! sVoiceName . icmp ( " SAS " ) ) {
m_voiceType = PVT_ALLIED_SAS ;
} else if ( ! sVoiceName . icmp ( " pilot " ) ) {
m_voiceType = PVT_ALLIED_PILOT ;
} else if ( ! sVoiceName . icmp ( " army " ) ) {
m_voiceType = PVT_ALLIED_ARMY ;
} else if ( ! sVoiceName . icmp ( " ranger " ) ) {
m_voiceType = PVT_ALLIED_RANGER ;
} else if ( ! sVoiceName . icmp ( " axis1 " ) ) {
m_voiceType = PVT_AXIS_AXIS1 ;
} else if ( ! sVoiceName . icmp ( " axis2 " ) ) {
m_voiceType = PVT_AXIS_AXIS2 ;
} else if ( ! sVoiceName . icmp ( " axis3 " ) ) {
m_voiceType = PVT_AXIS_AXIS3 ;
} else if ( ! sVoiceName . icmp ( " axis4 " ) ) {
m_voiceType = PVT_AXIS_AXIS4 ;
} else if ( ! sVoiceName . icmp ( " axis5 " ) ) {
m_voiceType = PVT_AXIS_AXIS5 ;
} else {
m_voiceType = PVT_NONE_SET ;
}
2023-08-04 00:04:29 +02:00
}
}
2023-08-10 03:46:28 +02:00
void Player : : GetTeamDialogPrefix ( str & outPrefix )
{
2023-08-10 14:18:40 +02:00
if ( GetTeam ( ) = = TEAM_AXIS ) {
outPrefix = " axis_ " ;
} else {
outPrefix = " allied_ " ;
}
2023-11-03 21:56:31 +01:00
if ( g_protocol > = protocol_e : : PROTOCOL_MOHTA_MIN ) {
switch ( m_voiceType ) {
case PVT_ALLIED_AMERICAN :
2023-08-10 14:18:40 +02:00
outPrefix + = " american_ " ;
2023-11-03 21:56:31 +01:00
break ;
case PVT_ALLIED_BRITISH :
outPrefix + = " british_ " ;
break ;
case PVT_ALLIED_RUSSIAN :
outPrefix + = " russian_ " ;
break ;
case PVT_AXIS_START :
outPrefix + = " german_ " ;
break ;
case PVT_AXIS_ITALIAN :
outPrefix + = " italian_ " ;
break ;
default :
if ( GetTeam ( ) = = TEAM_AXIS ) {
outPrefix + = " german_ " ;
} else {
outPrefix + = " american_ " ;
}
break ;
}
} else {
switch ( m_voiceType ) {
case PVT_ALLIED_AIRBORNE :
outPrefix + = " airborne_ " ;
break ;
case PVT_ALLIED_MANON :
outPrefix + = " manon_ " ;
break ;
case PVT_ALLIED_SAS :
outPrefix + = " sas_ " ;
break ;
case PVT_ALLIED_PILOT :
outPrefix + = " pilot_ " ;
break ;
case PVT_ALLIED_ARMY :
outPrefix + = " army_ " ;
break ;
case PVT_ALLIED_RANGER :
outPrefix + = " ranger_ " ;
break ;
case PVT_AXIS_AXIS1 :
outPrefix + = " axis1_ " ;
break ;
case PVT_AXIS_AXIS2 :
outPrefix + = " axis2_ " ;
break ;
case PVT_AXIS_AXIS3 :
outPrefix + = " axis3_ " ;
break ;
case PVT_AXIS_AXIS4 :
outPrefix + = " axis4_ " ;
break ;
case PVT_AXIS_AXIS5 :
outPrefix + = " axis5_ " ;
break ;
default :
if ( dm_team ! = TEAM_AXIS ) {
outPrefix + = " army_ " ;
} else {
outPrefix + = " axis4_ " ;
}
2023-08-10 14:18:40 +02:00
}
}
2023-08-10 03:46:28 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : PlayInstantMessageSound ( const char * name )
2023-08-10 03:46:28 +02:00
{
str soundName ;
2023-08-10 18:43:21 +02:00
if ( g_protocol < PROTOCOL_MOHTA_MIN ) {
2023-08-10 03:46:28 +02:00
gi . DPrintf2 ( " Instant message sound isn't supported on protocol below version 15 " ) ;
return ;
}
GetTeamDialogPrefix ( soundName ) ;
soundName + = name ;
gi . MSG_SetClient ( client - > ps . clientNum ) ;
gi . MSG_StartCGM ( CGM_VOICE_CHAT ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 0 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 1 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 2 ] ) ;
gi . MSG_WriteBits ( 0 , 1 ) ;
gi . MSG_WriteBits ( edict - g_entities , 6 ) ;
gi . MSG_WriteString ( soundName . c_str ( ) ) ;
gi . MSG_EndCGM ( ) ;
}
2023-08-04 00:04:29 +02:00
void Player : : EventDMMessage ( Event * ev )
{
2023-11-03 21:56:31 +01:00
int i ;
2024-09-16 20:20:19 +02:00
//int iStringLength;
2023-11-03 21:56:31 +01:00
int iMode = 0 ;
str sToken ;
char szPrintString [ MAX_SAY_TEXT ] ; // it's MAX_STRING_CHARS in mohaa
2024-09-16 20:20:19 +02:00
size_t iStringLength ;
2023-11-03 21:56:31 +01:00
const char * pTmpInstantMsg = " " ;
qboolean bInstaMessage = qfalse ;
AliasListNode_t * pSoundAlias = NULL ;
const char * pszAliasname = NULL ;
str sAliasName ;
str sRandomAlias ;
gentity_t * ent ;
2023-08-04 00:04:29 +02:00
2023-08-29 18:48:14 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
2023-08-04 00:04:29 +02:00
return ;
}
if ( ev - > NumArgs ( ) < = 1 ) {
return ;
}
2023-11-03 21:56:31 +01:00
sToken = ev - > GetString ( 2 ) ;
2023-08-04 00:04:29 +02:00
// Check for taunts
2023-11-03 21:56:31 +01:00
if ( sToken . length ( ) = = 3 & & * sToken = = ' * ' & & sToken [ 1 ] > ' 0 ' & & sToken [ 1 ] < = ' 9 ' & & sToken [ 2 ] > ' 0 '
& & sToken [ 2 ] < = ' 9 ' ) {
unsigned int n1 , n2 ;
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
if ( IsSpectator ( ) | | IsDead ( ) ) {
// spectators or death players can't talk
return ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2024-09-26 19:27:49 +02:00
if ( ! g_instamsg_allowed - > integer ) {
// Added in OPM
return ;
}
if ( g_instamsg_minDelay - > integer > 0 & & level . inttime < m_iInstantMessageTime + g_instamsg_minDelay - > integer ) {
// Added in OPM
return ;
}
2023-11-03 21:56:31 +01:00
GetTeamDialogPrefix ( sAliasName ) ;
2024-10-03 19:06:03 +02:00
if ( g_target_game > = target_game_e : : TG_MOHTT & & sToken [ 1 ] = = ' 6 ' ) {
// Added in 2.30
// Liberation messages
sAliasName + = va ( " lib%c " , ( sToken [ 2 ] + ' 0 ' ) ) ;
} else {
sAliasName + = va ( " %c%c " , ( sToken [ 1 ] + ' 0 ' ) , ( sToken [ 2 ] + ' 0 ' ) ) ;
}
2023-11-03 21:56:31 +01:00
sRandomAlias = GetRandomAlias ( sAliasName , & pSoundAlias ) ;
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
// find a random alias
if ( sRandomAlias . length ( ) > 0 ) {
pszAliasname = sRandomAlias . c_str ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( ! pszAliasname ) {
pszAliasname = gi . GlobalAlias_FindRandom ( sAliasName , & pSoundAlias ) ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( ! pszAliasname | | ! pSoundAlias ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
n1 = sToken [ 1 ] - ' 1 ' ;
n2 = sToken [ 2 ] - ' 1 ' ;
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( g_protocol > = PROTOCOL_MOHTA_MIN ) {
if ( n1 > = ARRAY_LEN ( pInstantMsgEng ) | | n2 > = ARRAY_LEN ( pInstantMsgEng [ 0 ] ) ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
pTmpInstantMsg = pInstantMsgEng [ n1 ] [ n2 ] ;
} else {
if ( n1 > = ARRAY_LEN ( pInstantMsgEng_ver6 ) | | n2 > = ARRAY_LEN ( pInstantMsgEng_ver6 [ 0 ] ) ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
// fallback to old version
pTmpInstantMsg = pInstantMsgEng_ver6 [ n1 ] [ n2 ] ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
bInstaMessage = qtrue ;
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( g_gametype - > integer = = GT_FFA ) {
iMode = 0 ;
} else {
if ( n1 = = 4 ) {
iMode = 0 ;
2023-08-04 00:04:29 +02:00
} else {
2023-11-03 21:56:31 +01:00
iMode = - 1 ;
2023-08-04 00:04:29 +02:00
}
2024-09-26 19:10:01 +02:00
}
2024-09-26 19:27:49 +02:00
} else {
if ( ! g_textmsg_allowed - > integer ) {
// Added in OPM
2016-03-27 11:49:47 +02:00
2024-09-26 19:27:49 +02:00
str errorString = gi . LV_ConvertString ( " Message Error " ) ;
str reasonString = gi . LV_ConvertString ( " Text chat is disabled on this server " ) ;
gi . SendServerCommand (
edict - g_entities ,
" print \" " HUD_MESSAGE_CHAT_WHITE " %s: %s. \n \" " ,
errorString . c_str ( ) ,
reasonString . c_str ( )
) ;
return ;
}
if ( g_textmsg_minDelay - > integer > 0 & & level . inttime < m_iTextChatTime + g_textmsg_minDelay - > integer ) {
// Added in OPM
return ;
2023-08-04 00:04:29 +02:00
}
}
2016-03-27 11:49:47 +02:00
2024-09-26 19:27:49 +02:00
if ( bInstaMessage ) {
if ( g_voiceChatTime - > value > 0 ) {
m_fTalkTime = g_voiceChatTime - > value + level . time ;
}
m_iInstantMessageTime = level . inttime ;
} else {
2023-11-03 21:56:31 +01:00
iMode = ev - > GetInteger ( 1 ) ;
if ( g_textChatTime - > value > 0 ) {
m_fTalkTime = g_textChatTime - > value + level . time ;
}
2024-09-26 19:27:49 +02:00
m_iTextChatTime = level . inttime ;
2023-11-03 21:56:31 +01:00
}
2016-03-27 11:49:47 +02:00
2024-09-20 21:53:48 +02:00
Q_strncpyz ( szPrintString , " print \" " HUD_MESSAGE_CHAT_WHITE , sizeof ( szPrintString ) ) ;
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( m_bSpectator ) {
if ( iMode < = 0 ) {
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , gi . CL_LV_ConvertString ( " (spectator) " ) ) ;
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " " ) ;
2023-11-03 21:56:31 +01:00
} else if ( iMode < = game . maxclients ) {
ent = & g_entities [ iMode - 1 ] ;
if ( ent - > inuse & & ent - > entity & & ! static_cast < Player * > ( ent - > entity ) - > IsSpectator ( ) ) {
str errorString = gi . LV_ConvertString ( " Message Error " ) ;
str reasonString =
gi . LV_ConvertString ( " Spectators are not allowed to send private messages to non-spectators " ) ;
gi . SendServerCommand (
edict - g_entities ,
2023-11-04 00:20:27 +01:00
" print \" " HUD_MESSAGE_CHAT_WHITE " %s: %s. \n \" " ,
2023-11-03 21:56:31 +01:00
errorString . c_str ( ) ,
reasonString . c_str ( )
) ;
2023-08-04 00:04:29 +02:00
return ;
}
}
2023-11-03 21:56:31 +01:00
} else if ( IsDead ( ) | | m_bTempSpectator ) {
if ( iMode < = 0 ) {
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , gi . CL_LV_ConvertString ( " (dead) " ) ) ;
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " " ) ;
2023-11-03 21:56:31 +01:00
} else if ( iMode < = game . maxclients ) {
ent = & g_entities [ iMode - 1 ] ;
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
if ( ent - > inuse & & ent - > entity & & ! static_cast < Player * > ( ent - > entity ) - > IsSpectator ( ) ) {
str errorString = gi . LV_ConvertString ( " Message Error " ) ;
str reasonString =
gi . LV_ConvertString ( " Dead players are not allowed to send private messages to active players " ) ;
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
gi . SendServerCommand (
edict - g_entities ,
2023-11-04 00:20:27 +01:00
" print \" " HUD_MESSAGE_CHAT_WHITE " %s: %s. \n \" " ,
2023-11-03 21:56:31 +01:00
errorString . c_str ( ) ,
reasonString . c_str ( )
) ;
return ;
}
}
} else if ( iMode < 0 ) {
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , gi . CL_LV_ConvertString ( " (team) " ) ) ;
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " " ) ;
2023-11-03 21:56:31 +01:00
} else if ( iMode > 0 ) {
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , gi . CL_LV_ConvertString ( " (private) " ) ) ;
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " " ) ;
2023-08-04 00:04:29 +02:00
}
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , client - > pers . netname ) ;
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
if ( bInstaMessage ) {
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " : " ) ;
Q_strcat ( szPrintString , sizeof ( szPrintString ) , gi . LV_ConvertString ( pTmpInstantMsg ) ) ;
2023-11-03 21:56:31 +01:00
} else {
bool met_comment ;
2023-08-04 00:04:29 +02:00
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " : " ) ;
2023-11-03 21:56:31 +01:00
iStringLength = strlen ( szPrintString ) ;
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
for ( i = 2 ; i < = ev - > NumArgs ( ) ; i + + ) {
sToken = ev - > GetString ( i ) ;
// Added in 2.40
// Special battle language tokens
// So players can easily tell their position, health, etc.
sToken = TranslateBattleLanguageTokens ( sToken ) ;
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
if ( iStringLength + sToken . length ( ) > ( ARRAY_LEN ( szPrintString ) - 1 ) ) {
break ;
}
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
// Added in OPM.
// Checks for comments in string (as COM_Parse will parse them)
if ( strstr ( sToken , " /* " ) ) {
met_comment = true ;
}
2023-08-04 00:04:29 +02:00
2023-11-03 21:56:31 +01:00
if ( strstr ( sToken , " */ " ) & & met_comment ) {
// ignore messages containing comments
return ;
}
2023-08-04 00:04:29 +02:00
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " " ) ;
Q_strcat ( szPrintString , sizeof ( szPrintString ) , gi . LV_ConvertString ( sToken ) ) ;
2023-08-04 00:04:29 +02:00
}
}
2024-09-20 21:53:48 +02:00
Q_strcat ( szPrintString , sizeof ( szPrintString ) , " \n " ) ;
2023-11-03 21:56:31 +01:00
// ignore names containing comments
if ( strstr ( client - > pers . netname , " // " )
| | ( strstr ( client - > pers . netname , " /* " ) & & strstr ( client - > pers . netname , " */ " ) ) ) {
return ;
}
if ( iMode = = 0 ) {
//
// team message
//
if ( ! IsSpectator ( ) | | g_spectate_allow_full_chat - > integer ) {
for ( i = 0 ; i < game . maxclients ; i + + ) {
ent = & g_entities [ i ] ;
2023-08-04 00:04:29 +02:00
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2023-11-03 21:56:31 +01:00
gi . SendServerCommand ( i , " %s " , szPrintString ) ;
2023-08-04 00:04:29 +02:00
if ( bInstaMessage ) {
gi . MSG_SetClient ( i ) ;
gi . MSG_StartCGM ( BG_MapCGMToProtocol ( g_protocol , CGM_VOICE_CHAT ) ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 0 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 1 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 2 ] ) ;
2023-11-03 21:56:31 +01:00
gi . MSG_WriteBits ( qtrue , 1 ) ;
2023-08-04 00:04:29 +02:00
gi . MSG_WriteBits ( edict - g_entities , 6 ) ;
2023-11-03 21:56:31 +01:00
gi . MSG_WriteString ( sAliasName . c_str ( ) ) ;
2023-08-04 00:04:29 +02:00
gi . MSG_EndCGM ( ) ;
}
}
2023-11-03 21:56:31 +01:00
} else {
//
// send a message to spectators
//
for ( i = 0 ; i < game . maxclients ; i + + ) {
ent = & g_entities [ i ] ;
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( ! static_cast < Player * > ( ent - > entity ) - > IsSpectator ( ) ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
gi . SendServerCommand ( i , " %s " , szPrintString ) ;
}
}
} else if ( iMode < 0 ) {
//
2023-08-04 00:04:29 +02:00
// team message
2023-11-03 21:56:31 +01:00
//
if ( IsSpectator ( ) ) {
for ( i = 0 ; i < game . maxclients ; i + + ) {
ent = & g_entities [ i ] ;
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
if ( ! static_cast < Player * > ( ent - > entity ) - > IsSpectator ( ) ) {
continue ;
}
gi . SendServerCommand ( i , " %s " , szPrintString ) ;
2023-08-04 00:04:29 +02:00
}
2023-11-03 21:56:31 +01:00
} else {
for ( i = 0 ; i < game . maxclients ; i + + ) {
ent = & g_entities [ i ] ;
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
if ( static_cast < Player * > ( ent - > entity ) - > GetTeam ( ) ! = GetTeam ( ) ) {
gi . MSG_SetClient ( i ) ;
gi . MSG_StartCGM ( BG_MapCGMToProtocol ( g_protocol , CGM_VOICE_CHAT ) ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 0 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 1 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 2 ] ) ;
gi . MSG_WriteBits ( qtrue , 1 ) ;
gi . MSG_WriteBits ( edict - g_entities , 6 ) ;
gi . MSG_WriteString ( sAliasName . c_str ( ) ) ;
gi . MSG_EndCGM ( ) ;
continue ;
}
gi . SendServerCommand ( i , " %s " , szPrintString ) ;
if ( bInstaMessage ) {
gi . MSG_SetClient ( i ) ;
gi . MSG_StartCGM ( BG_MapCGMToProtocol ( g_protocol , CGM_VOICE_CHAT ) ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 0 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 1 ] ) ;
gi . MSG_WriteCoord ( m_vViewPos [ 2 ] ) ;
gi . MSG_WriteBits ( qfalse , 1 ) ;
gi . MSG_WriteBits ( edict - g_entities , 6 ) ;
gi . MSG_WriteString ( sAliasName . c_str ( ) ) ;
gi . MSG_EndCGM ( ) ;
}
2023-08-04 00:04:29 +02:00
}
}
2023-11-03 21:56:31 +01:00
} else if ( iMode < = game . maxclients ) {
ent = & g_entities [ iMode - 1 ] ;
if ( ! ent - > inuse | | ! ent - > entity ) {
str errorString = gi . LV_ConvertString ( " Message Error " ) ;
str reasonString = gi . LV_ConvertString ( " is not a connected client " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
gi . SendServerCommand (
2023-11-03 21:56:31 +01:00
edict - g_entities ,
2023-11-04 00:20:27 +01:00
" print \" " HUD_MESSAGE_CHAT_WHITE " %s: %i %s. \n \" " ,
2023-11-03 21:56:31 +01:00
errorString . c_str ( ) ,
iMode ,
reasonString . c_str ( )
2023-08-04 00:04:29 +02:00
) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-11-04 00:05:18 +01:00
gi . SendServerCommand ( iMode - 1 , " %s " , szPrintString ) ;
if ( ent - > entity ! = this ) {
gi . SendServerCommand (
edict - g_entities ,
2023-11-04 00:20:27 +01:00
" print \" " HUD_MESSAGE_CHAT_WHITE " %s %i: \n \" " ,
2023-11-04 00:05:18 +01:00
gi . LV_ConvertString ( " Message to player " ) ,
iMode
) ;
gi . SendServerCommand ( edict - g_entities , " %s " , szPrintString ) ;
}
2023-11-03 21:56:31 +01:00
} else {
str errorString = gi . LV_ConvertString ( " Message Error " ) ;
str reasonString = gi . LV_ConvertString ( " is a bad client number " ) ;
2016-03-27 11:49:47 +02:00
2023-11-03 21:56:31 +01:00
gi . SendServerCommand (
edict - g_entities ,
2023-11-04 00:20:27 +01:00
" print \" " HUD_MESSAGE_CHAT_WHITE " %s: %i %s. \n \" " ,
2023-11-03 21:56:31 +01:00
errorString . c_str ( ) ,
iMode ,
reasonString . c_str ( )
) ;
return ;
}
2016-03-27 11:49:47 +02:00
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageCondition ( ) const
2023-08-10 03:46:28 +02:00
{
int healthRatio ;
if ( health < = 0 ) {
return " dead " ;
}
if ( health > = max_health ) {
return " just peachy " ;
}
healthRatio = ( health * 5.f ) / max_health ;
2023-08-10 18:43:21 +02:00
switch ( healthRatio ) {
2023-08-10 03:46:28 +02:00
case 0 :
return " almost dead " ;
case 1 :
2024-09-19 10:52:47 +02:00
return " severely wounded " ;
2023-08-10 03:46:28 +02:00
case 2 :
return " wounded " ;
case 3 :
return " slightly wounded " ;
case 4 :
default :
return " pretty good " ;
}
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageDirection ( ) const
2023-08-10 03:46:28 +02:00
{
int dir = ( ( m_vViewAng . y - world - > m_fNorth ) + 22.5f + 360.f ) / 45.f ;
2023-08-10 18:43:21 +02:00
switch ( dir % 8 ) {
2023-08-10 03:46:28 +02:00
case 0 :
2023-08-10 14:18:40 +02:00
return " North " ;
case 1 :
return " North West " ;
case 2 :
return " West " ;
case 3 :
return " South West " ;
case 4 :
return " South " ;
case 5 :
return " South East " ;
case 6 :
return " East " ;
case 7 :
return " North East " ;
2023-08-10 03:46:28 +02:00
default :
return " ??? " ;
}
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageLocation ( ) const
2023-08-10 03:46:28 +02:00
{
2023-11-03 21:56:31 +01:00
return gi . CL_LV_ConvertString ( level . GetDMLocation ( m_vViewPos ) . c_str ( ) ) ;
2023-08-10 03:46:28 +02:00
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageLocalFolks ( )
2023-08-10 03:46:28 +02:00
{
2023-08-10 14:18:40 +02:00
static char buf [ 256 ] ;
2023-08-10 18:43:21 +02:00
char * p ;
char * curP ;
2023-08-11 00:48:09 +02:00
size_t remaining ;
size_t length ;
2023-08-10 18:43:21 +02:00
Player * pPlayer ;
Player * pFolk ;
gentity_t * ent ;
int i ;
2023-08-10 14:18:40 +02:00
remaining = ARRAY_LEN ( buf ) - 1 ;
2023-08-10 18:43:21 +02:00
p = buf ;
curP = NULL ;
pFolk = NULL ;
2023-08-10 14:18:40 +02:00
for ( i = 0 ; i < game . maxclients ; i + + ) {
ent = & g_entities [ i ] ;
if ( ! ent - > inuse | | ! ent - > entity ) {
continue ;
}
2023-08-10 18:43:21 +02:00
pPlayer = static_cast < Player * > ( ent - > entity ) ;
2023-08-10 14:18:40 +02:00
if ( pPlayer ! = this & & pPlayer - > GetTeam ( ) = = GetTeam ( ) & & CanSee ( pPlayer , 360 , 1600 , false ) ) {
if ( p ! = buf ) {
if ( remaining < 2 ) {
// No more space remaining
break ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( p , " , " , sizeof ( buf ) - ( p - buf ) ) ;
2023-08-10 14:18:40 +02:00
p + = 2 ;
curP = p ;
remaining - = 2 ;
}
length = strlen ( client - > pers . netname ) ;
if ( remaining < length ) {
break ;
}
2024-09-20 21:53:48 +02:00
Q_strncpyz ( p , client - > pers . netname , sizeof ( buf ) - ( p - buf ) ) ;
2023-08-10 14:18:40 +02:00
p + = length ;
remaining - = length ;
pFolk = pPlayer ;
}
}
if ( curP & & remaining > = 2 ) {
2024-09-20 21:53:48 +02:00
Q_strncpyz ( curP , " and " , sizeof ( buf ) - ( curP - buf ) ) ;
Q_strncpyz ( curP + strlen ( curP ) , pFolk - > client - > pers . netname , sizeof ( buf ) - ( curP + strlen ( curP ) - buf ) ) ;
2023-08-10 14:18:40 +02:00
} else if ( ! pFolk ) {
return " nobody " ;
}
return buf ;
2023-08-10 03:46:28 +02:00
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageWeapon ( ) const
2023-08-10 03:46:28 +02:00
{
return GetCurrentDMWeaponType ( ) . c_str ( ) ;
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageDistance ( ) const
2023-08-10 03:46:28 +02:00
{
2023-08-10 18:43:21 +02:00
Vector vStart , vEnd ;
Vector vForward ;
2023-08-10 14:18:40 +02:00
trace_t trace ;
2023-08-10 18:43:21 +02:00
float dist ;
2023-08-10 14:18:40 +02:00
vStart = m_vViewPos ;
AngleVectors ( m_vViewAng , vForward , NULL , NULL ) ;
vEnd = vStart + vForward * 10240 ;
2023-08-10 18:43:21 +02:00
trace = G_Trace (
vStart ,
vec_zero ,
vec_zero ,
vEnd ,
static_cast < const Entity * > ( this ) ,
MASK_BATTLELANGUAGE ,
qfalse ,
" Player::GetBattleLanguageDistance "
) ;
2023-08-10 14:18:40 +02:00
dist = ( vStart - trace . endpos ) . length ( ) ;
if ( g_qunits_to_feet - > integer ) {
return GetBattleLanguageDistanceFeet ( dist ) ;
} else {
return GetBattleLanguageDistanceMeters ( dist ) ;
}
2023-08-10 03:46:28 +02:00
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageDistanceMeters ( float dist ) const
2023-08-10 03:46:28 +02:00
{
int meters ;
meters = ( int ) ( ( dist + 26.f ) / 52.f ) ;
2023-08-10 18:43:21 +02:00
if ( meters > = 5 ) {
2023-08-10 03:46:28 +02:00
if ( meters < 21 ) {
meters = 5 * ( ( meters + 2 ) / 5 ) ;
} else if ( meters < 101 ) {
meters = 10 * ( ( meters + 5 ) / 10 ) ;
} else {
meters = 25 * ( ( meters + 12 ) / 25 ) ;
}
}
return va ( " %d meters " , meters ) ;
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageDistanceFeet ( float dist ) const
2023-08-10 03:46:28 +02:00
{
int ft ;
ft = ( int ) ( ( dist + 26.f ) / 52.f ) ;
2023-08-10 18:43:21 +02:00
if ( ft > = 11 ) {
2023-08-10 03:46:28 +02:00
if ( ft < 51 ) {
ft = 5 * ( ( ft + 2 ) / 5 ) ;
} else if ( ft < 251 ) {
ft = 10 * ( ( ft + 5 ) / 10 ) ;
} else {
ft = 25 * ( ( ft + 12 ) / 25 ) ;
}
}
return va ( " %d feet " , ft ) ;
}
2023-11-03 22:00:49 +01:00
str Player : : GetBattleLanguageTarget ( ) const
2023-08-10 03:46:28 +02:00
{
2023-08-10 18:43:21 +02:00
Vector vStart , vEnd ;
Vector vForward ;
2023-08-10 14:18:40 +02:00
trace_t trace ;
vStart = m_vViewPos ;
AngleVectors ( m_vViewAng , vForward , NULL , NULL ) ;
vEnd = vStart + vForward * 10240 ;
2023-08-10 18:43:21 +02:00
trace = G_Trace (
vStart ,
vec_zero ,
vec_zero ,
vEnd ,
static_cast < const Entity * > ( this ) ,
MASK_BATTLELANGUAGE ,
qfalse ,
" Player::GetBattleLanguageDistance "
) ;
2023-08-10 14:18:40 +02:00
if ( ! trace . ent ) {
return " something " ;
}
if ( ! trace . ent - > entity | | trace . ent - > entity = = world ) {
return " something " ;
}
2023-08-10 18:43:21 +02:00
2023-08-10 14:18:40 +02:00
if ( trace . ent - > entity - > IsSubclassOfPlayer ( ) ) {
2023-08-10 18:43:21 +02:00
Player * pPlayer = static_cast < Player * > ( trace . ent - > entity ) ;
2023-08-10 14:18:40 +02:00
return pPlayer - > client - > pers . netname ;
}
if ( trace . ent - > entity - > IsSubclassOfSentient ( ) ) {
return " someone " ;
}
return " something " ;
2023-08-10 03:46:28 +02:00
}
2023-11-03 22:00:49 +01:00
str Player : : TranslateBattleLanguageTokens ( const char * string )
2023-08-10 03:46:28 +02:00
{
2023-11-03 22:00:49 +01:00
str token ;
int type ;
2023-08-10 03:46:28 +02:00
if ( ! g_chat_expansions - > integer ) {
return string ;
}
if ( ! string ) {
2024-09-08 23:54:47 +02:00
return str ( ) ;
2023-08-10 03:46:28 +02:00
}
if ( string [ 0 ] ! = ' $ ' ) {
return string ;
}
type = string [ 1 ] ;
if ( ! type | | string [ 2 ] ) {
return string ;
}
2023-08-10 18:43:21 +02:00
switch ( type ) {
2023-08-10 14:18:40 +02:00
case ' a ' :
token = GetBattleLanguageTarget ( ) ;
break ;
case ' c ' :
token = GetBattleLanguageCondition ( ) ;
break ;
case ' d ' :
token = GetBattleLanguageDirection ( ) ;
break ;
case ' l ' :
token = GetBattleLanguageLocation ( ) ;
break ;
case ' n ' :
token = GetBattleLanguageLocalFolks ( ) ;
break ;
case ' r ' :
token = GetBattleLanguageDistance ( ) ;
break ;
case ' w ' :
token = GetBattleLanguageWeapon ( ) ;
break ;
default :
return string ;
}
return gi . LV_ConvertString ( token ) ;
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventIPrint ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str sString = ev - > GetString ( 1 ) ;
qboolean iBold = qfalse ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
iBold = ev - > GetInteger ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( iBold ) {
gi . SendServerCommand ( edict - g_entities , " print \" " HUD_MESSAGE_WHITE " %s \n \" " , sString . c_str ( ) ) ;
} else {
gi . SendServerCommand ( edict - g_entities , " print \" " HUD_MESSAGE_YELLOW " %s \n \" " , sString . c_str ( ) ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:21:19 +02:00
void Player : : SetViewangles ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
SetViewAngles ( ev - > GetVector ( 1 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : GetViewangles ( Event * ev )
2023-08-04 00:04:29 +02:00
{
2023-09-19 20:08:35 +02:00
ev - > AddVector ( GetVAngles ( ) ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : EventGetUseHeld ( Event * ev )
2023-08-04 00:04:29 +02:00
{
2023-08-19 00:35:32 +02:00
ev - > AddInteger ( ( buttons & BUTTON_USE ) ? true : false ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:21:19 +02:00
void Player : : EventGetFireHeld ( Event * ev )
2023-08-04 00:04:29 +02:00
{
ev - > AddInteger ( buttons & ( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ) ? qtrue : qfalse ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-10 18:43:21 +02:00
void Player : : EventGetPrimaryFireHeld ( Event * ev )
2023-08-10 03:46:28 +02:00
{
ev - > AddInteger ( buttons & BUTTON_ATTACKLEFT ? true : false ) ;
}
2023-08-10 18:43:21 +02:00
void Player : : EventGetSecondaryFireHeld ( Event * ev )
2023-08-10 03:46:28 +02:00
{
2023-08-10 14:18:40 +02:00
ev - > AddInteger ( buttons & BUTTON_ATTACKRIGHT ? true : false ) ;
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : BeginTempSpectator ( void )
{
m_bTempSpectator = true ;
2023-08-10 13:31:35 +02:00
Spectator ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EndSpectator ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:21:19 +02:00
m_bSpectator = false ;
2023-08-04 00:04:29 +02:00
m_bTempSpectator = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
client - > ps . pm_flags & = ~ ( PMF_SPECTATING | PMF_SPECTATE_FOLLOW ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventGetReady ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( m_bReady ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventSetReady ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( m_bReady ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_bReady = true ;
gi . Printf ( " %s is ready \n " , client - > pers . netname ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventSetNotReady ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( ! m_bReady ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_bReady = false ;
gi . Printf ( " %s is not ready \n " , client - > pers . netname ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventGetDMTeam ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( dm_team = = TEAM_FREEFORALL ) {
ev - > AddConstString ( STRING_FREEFORALL ) ;
} else if ( dm_team = = TEAM_AXIS ) {
ev - > AddConstString ( STRING_AXIS ) ;
} else if ( dm_team = = TEAM_ALLIES ) {
ev - > AddConstString ( STRING_ALLIES ) ;
} else if ( dm_team = = TEAM_SPECTATOR ) {
ev - > AddConstString ( STRING_SPECTATOR ) ;
} else {
ScriptError ( " dmteam is invalid in single player " ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : EventGetNetName ( Event * ev )
2023-08-10 03:46:28 +02:00
{
ev - > AddString ( client - > pers . netname ) ;
}
2023-08-04 00:04:29 +02:00
void Player : : EventSetViewModelAnim ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str anim ;
int force_restart = 0 ;
qboolean bfullanim = 0 ;
anim = ev - > GetString ( 1 ) ;
if ( ev - > NumArgs ( ) > 1 ) {
force_restart = ev - > GetInteger ( 2 ) ;
}
if ( ev - > NumArgs ( ) > 2 ) {
bfullanim = ev - > GetInteger ( 3 ) ;
}
ViewModelAnim ( anim , force_restart , bfullanim ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : FullHeal ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( IsDead ( ) ) {
if ( ! ev - > IsFromScript ( ) ) {
HUDPrint ( " TESTING: Cannot resurrect yourself with the fullheal. \n " ) ;
}
} else {
if ( ! ev - > IsFromScript ( ) ) {
HUDPrint ( " TESTING: You used the fullheal. \n " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
health = max_health ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-10 03:46:28 +02:00
void Player : : RemoveFromVehiclesAndTurretsInternal ( void )
{
2023-08-10 18:43:21 +02:00
if ( m_pVehicle ) {
Event * event ;
2023-08-10 17:01:55 +02:00
m_pVehicle - > flags & = ~ FL_GODMODE ;
event = new Event ( EV_Use ) ;
event - > AddEntity ( this ) ;
m_pVehicle - > ProcessEvent ( event ) ;
2023-08-10 18:43:21 +02:00
} else if ( m_pTurret ) {
2023-08-10 17:01:55 +02:00
m_pTurret - > TurretUsed ( this ) ;
}
2023-08-10 03:46:28 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : RemoveFromVehiclesAndTurrets ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-10 18:43:21 +02:00
Weapon * activeWeap = GetActiveWeapon ( WEAPON_MAIN ) ;
2023-08-10 17:01:55 +02:00
if ( activeWeap & & activeWeap - > IsCarryableTurret ( ) ) {
2023-08-10 18:43:21 +02:00
CarryableTurret * pTurret = static_cast < CarryableTurret * > ( activeWeap ) ;
2023-08-10 17:01:55 +02:00
pTurret - > DropTurret ( NULL ) ;
}
if ( ! m_pVehicle & & ! m_pTurret ) {
return ;
}
2023-08-04 00:04:29 +02:00
if ( m_pVehicle & & m_pVehicle - > isLocked ( ) ) {
m_pVehicle - > UnLock ( ) ;
2023-08-10 17:01:55 +02:00
if ( m_pTurret & & m_pTurret - > IsSubclassOfVehicleTurretGun ( ) ) {
2023-08-04 00:04:29 +02:00
VehicleTurretGun * turret = ( VehicleTurretGun * ) m_pTurret . Pointer ( ) ;
if ( turret - > isLocked ( ) ) {
turret - > UnLock ( ) ;
2023-08-10 17:01:55 +02:00
RemoveFromVehiclesAndTurretsInternal ( ) ;
2023-08-04 00:04:29 +02:00
turret - > Lock ( ) ;
} else {
2023-08-10 17:01:55 +02:00
RemoveFromVehiclesAndTurretsInternal ( ) ;
2023-08-04 00:04:29 +02:00
}
} else {
2023-08-10 17:01:55 +02:00
RemoveFromVehiclesAndTurretsInternal ( ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-10-04 00:25:55 +02:00
// the vehicle might have been modified
if ( m_pVehicle ) {
m_pVehicle - > Lock ( ) ;
}
2023-08-10 17:01:55 +02:00
} else if ( m_pTurret & & m_pTurret - > IsSubclassOfVehicleTurretGun ( ) ) {
2023-08-04 00:04:29 +02:00
VehicleTurretGun * turret = ( VehicleTurretGun * ) m_pTurret . Pointer ( ) ;
if ( turret - > isLocked ( ) ) {
2023-08-10 18:43:21 +02:00
turret - > UnLock ( ) ;
RemoveFromVehiclesAndTurretsInternal ( ) ;
2023-10-04 00:25:55 +02:00
// the turret might have been modified
if ( m_pTurret ) {
turret - > Lock ( ) ;
}
2023-08-04 00:04:29 +02:00
} else {
2023-08-10 17:01:55 +02:00
RemoveFromVehiclesAndTurretsInternal ( ) ;
2023-08-04 00:04:29 +02:00
}
} else {
2023-08-10 17:01:55 +02:00
RemoveFromVehiclesAndTurretsInternal ( ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventEnterIntermission ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( ! level . intermissiontime ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( level . intermissiontype ) {
G_DisplayScores ( this ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( level . intermissiontype = = TRANS_MISSION_FAILED | | IsDead ( ) ) {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_success " , " 0 " ) ;
gi . cvar_set ( " g_failed " , " 1 " ) ;
2023-08-04 00:04:29 +02:00
} else {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " g_success " , " 1 " ) ;
gi . cvar_set ( " g_failed " , " 0 " ) ;
2023-08-04 00:04:29 +02:00
}
} else {
G_HideScores ( this ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
bool Player : : BlocksAIMovement ( )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
return false ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventSetPerferredWeapon ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
m_sPerferredWeaponOverride = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetMouthAngle ( Event * ev )
{
int tag_num ;
float angle_percent ;
Vector mouth_angles ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
angle_percent = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( angle_percent < 0 ) {
angle_percent = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( angle_percent > 1 ) {
angle_percent = 1 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
tag_num = gi . Tag_NumForName ( edict - > tiki , " tag_mouth " ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( tag_num ! = - 1 ) {
SetControllerTag ( MOUTH_TAG , tag_num ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
mouth_angles = vec_zero ;
mouth_angles [ PITCH ] = max_mouth_angle * angle_percent ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetControllerAngles ( MOUTH_TAG , mouth_angles ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
int Player : : GetMoveResult ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
return moveresult ;
2016-03-27 11:49:47 +02:00
}
2024-09-29 18:49:24 +02:00
qboolean Player : : CheckCanSwitchTeam ( teamtype_t team ) {
float startTime ;
startTime = dmManager . GetMatchStartTime ( ) ;
if ( startTime > = 0.0f & & ( level . time - startTime ) > 30.0
& & ( level . time - m_fTeamSelectTime ) < g_teamswitchdelay - > integer ) {
int seconds = g_teamswitchdelay - > integer - ( level . time - m_fTeamSelectTime ) ;
gi . SendServerCommand (
edict - g_entities ,
" print \" " HUD_MESSAGE_WHITE " %s %i %s \n \" " ,
gi . LV_ConvertString ( " Can not change teams again for another " ) ,
seconds + 1 ,
gi . LV_ConvertString ( " seconds " )
) ;
return qfalse ;
}
// Added in OPM
// Check and prevent joining the team with the highest number of players
if ( g_teambalance - > integer & & g_gametype - > integer > = GT_TEAM & & ! dmManager . WaitingForPlayers ( ) ) {
DM_Team * pNewTeam = dmManager . GetTeam ( team ) ;
int i ;
for ( i = 0 ; i < 2 ; i + + ) {
DM_Team * pTeam = dmManager . GetTeam ( ( teamtype_t ) ( TEAM_ALLIES + i ) ) ;
int numTeamPlayers = pTeam - > m_players . NumObjects ( ) ;
if ( pTeam - > m_players . IndexOfObject ( this ) ) {
// Don't count the current player
numTeamPlayers - - ;
}
if ( pNewTeam - > m_players . NumObjects ( ) > numTeamPlayers ) {
gi . SendServerCommand (
edict - g_entities ,
" print \" " HUD_MESSAGE_WHITE " %s \n \" " ,
gi . LV_ConvertString ( " That team has enough players. Choose the team that has the lowest number of players. " )
) ;
return qfalse ;
}
}
}
return qtrue ;
}
2023-08-04 00:04:29 +02:00
qboolean Player : : ViewModelAnim ( str anim , qboolean force_restart , qboolean bFullAnim )
2016-03-27 11:49:47 +02:00
{
2023-08-19 21:06:25 +02:00
Unregister ( STRING_VIEWMODELANIM_DONE ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( client = = NULL ) {
return true ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
int viewModelAnim ;
playerState_t * playerState = & client - > ps ;
2023-08-13 16:11:25 +02:00
Weapon * weapon ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! anim . length ( ) ) {
anim = " " ;
2023-11-03 21:56:31 +01:00
}
2023-08-13 17:59:41 +02:00
2023-11-03 21:56:31 +01:00
// Copy the item prefix and the anim name
weapon = GetActiveWeapon ( WEAPON_MAIN ) ;
2016-03-27 11:49:47 +02:00
2023-08-13 16:11:25 +02:00
if ( ! Q_stricmp ( anim , " charge " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_CHARGE ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " fire " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_FIRE ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " fire_secondary " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_FIRE_SECONDARY ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " rechamber " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_RECHAMBER ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " reload " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_RELOAD ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " reload_single " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_RELOAD_SINGLE ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " reload_end " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_RELOAD_END ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " pullout " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_PULLOUT ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " putaway " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_PUTAWAY ;
2023-08-13 16:11:25 +02:00
} else if ( ! Q_stricmp ( anim , " ladderstep " ) ) {
2023-08-04 00:04:29 +02:00
viewModelAnim = VM_ANIM_LADDERSTEP ;
} else {
2023-08-13 17:59:41 +02:00
if ( ! Q_stricmp ( anim , " idle " ) ) {
viewModelAnim = VM_ANIM_IDLE ;
} else if ( ! Q_stricmp ( anim , " idle0 " ) ) {
viewModelAnim = VM_ANIM_IDLE_0 ;
} else if ( ! Q_stricmp ( anim , " idle1 " ) ) {
viewModelAnim = VM_ANIM_IDLE_1 ;
} else if ( ! Q_stricmp ( anim , " idle2 " ) ) {
viewModelAnim = VM_ANIM_IDLE_2 ;
} else {
// Defaults to idle
viewModelAnim = VM_ANIM_IDLE ;
}
2023-08-13 16:11:25 +02:00
2023-08-13 17:59:41 +02:00
//
// check the fire movement speed if the weapon has a max fire movement
//
if ( weapon & & weapon - > m_fMaxFireMovement < 1 ) {
float length ;
2016-03-27 11:49:47 +02:00
2023-08-13 17:59:41 +02:00
length = velocity . length ( ) ;
if ( length / sv_runspeed - > value > ( ( weapon - > m_fMaxFireMovement * weapon - > m_fMovementSpeed ) + 0.1f ) ) {
// Set the view model animation to disabled
viewModelAnim = VM_ANIM_DISABLED ;
}
2023-08-13 16:11:25 +02:00
}
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-13 16:11:25 +02:00
if ( ! weapon ) {
weapon = newActiveWeapon . weapon ;
}
if ( weapon ) {
m_sVMAcurrent = GetItemPrefix ( weapon - > getName ( ) ) + str ( " _ " ) + anim ;
2023-08-04 00:04:29 +02:00
} else {
m_sVMAcurrent = " unarmed_ " + anim ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_sVMcurrent = anim ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( viewModelAnim ! = playerState - > iViewModelAnim | | force_restart ) {
playerState - > iViewModelAnimChanged = ( playerState - > iViewModelAnimChanged + 1 ) & 3 ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
playerState - > iViewModelAnim = viewModelAnim ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_fpsTiki & & gi . Anim_NumForName ( m_fpsTiki , m_sVMAcurrent ) < 0 ) {
2023-11-04 19:01:48 +01:00
//gi.DPrintf("WARNING: Invalid view model anim \"%s\"\n", m_sVMAcurrent.c_str());
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
animDoneVM = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
m_fVMAtime = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return true ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : FindAlias ( str & output , str name , AliasListNode_t * * node )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
const char * alias = gi . Alias_FindRandom ( edict - > tiki , name , node ) ;
if ( alias = = NULL ) {
alias = gi . GlobalAlias_FindRandom ( name , node ) ;
}
if ( alias ! = NULL ) {
output = alias ;
}
2016-03-27 11:49:47 +02:00
}
2023-09-11 21:28:05 +02:00
bool Player : : HasVotedYes ( ) const
{
return voted ;
}
bool Player : : HasVotedNo ( ) const
{
return ! voted ;
}
2023-08-10 03:46:28 +02:00
void Player : : TickSprint ( )
{
float timeHeld ;
if ( last_ucmd . buttons & BUTTON_RUN & & last_ucmd . forwardmove ) {
timeHeld = 0 ;
if ( ! m_fLastSprintTime ) {
m_fLastSprintTime = level . time ;
}
} else {
2023-08-10 18:43:21 +02:00
timeHeld = 0 ;
2023-08-10 03:46:28 +02:00
m_fLastSprintTime = 0 ;
}
2023-08-10 18:43:21 +02:00
if ( last_ucmd . rightmove ) {
m_fLastSprintTime = timeHeld ;
}
if ( last_ucmd . upmove ) {
m_fLastSprintTime = timeHeld ;
}
2023-08-10 03:46:28 +02:00
}
float Player : : GetRunSpeed ( ) const
{
float sprintTime ;
float sprintMult ;
2023-08-10 14:18:40 +02:00
sprintTime = sv_sprinttime - > value ;
sprintMult = sv_sprintmult - > value ;
2023-08-10 18:43:21 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-10 14:18:40 +02:00
sprintTime = sv_sprinttime_dm - > value ;
sprintMult = sv_sprintmult_dm - > value ;
}
2023-08-10 03:46:28 +02:00
2023-08-16 13:17:01 +02:00
if ( sv_sprinton - > integer = = 1 & & m_fLastSprintTime & & ( level . time - m_fLastSprintTime ) > sprintTime ) {
2023-08-10 03:46:28 +02:00
return sv_runspeed - > value * sprintMult ;
} else {
return sv_runspeed - > value ;
}
}
void Player : : FireWeapon ( int number , firemode_t mode )
{
if ( m_pVehicle | | m_pTurret ) {
return ;
}
Sentient : : FireWeapon ( number , mode ) ;
2023-08-10 18:43:21 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER ) {
2023-08-10 03:46:28 +02:00
//
// Make sure to remove the player's invulnerability
//
CancelInvulnerable ( ) ;
}
}
void Player : : SetInvulnerable ( )
{
if ( IsInvulnerable ( ) ) {
return ;
}
if ( ! sv_invulnerabletime - > integer ) {
return ;
}
if ( gi . Cvar_Get ( " g_invulnoverride " , " 0 " , 0 ) - > integer = = 1 ) {
return ;
}
if ( IsDead ( ) ) {
return ;
}
if ( IsSpectator ( ) | | GetTeam ( ) = = TEAM_SPECTATOR ) {
return ;
}
//
// The player can now be invulnerable
//
2023-08-10 18:43:21 +02:00
takedamage = DAMAGE_NO ;
2023-08-10 03:46:28 +02:00
m_iInvulnerableTimeRemaining = sv_invulnerabletime - > integer ;
2023-08-10 18:43:21 +02:00
m_fLastInvulnerableTime = level . time ;
m_fInvulnerableTimeElapsed = level . time ;
2023-08-10 03:46:28 +02:00
TickInvulnerable ( ) ;
}
void Player : : TickInvulnerable ( )
{
2023-08-10 18:43:21 +02:00
if ( m_iInvulnerableTimeRemaining > = 0 & & level . time > = m_fInvulnerableTimeElapsed ) {
2023-08-10 14:18:40 +02:00
if ( m_iInvulnerableTimeRemaining ) {
m_fInvulnerableTimeElapsed = m_fInvulnerableTimeElapsed + 1.f ;
} else {
SetVulnerable ( ) ;
m_fInvulnerableTimeElapsed = 0 ;
}
2023-08-10 03:46:28 +02:00
2023-08-10 14:18:40 +02:00
m_iInvulnerableTimeRemaining - - ;
}
2023-08-10 03:46:28 +02:00
}
void Player : : SetVulnerable ( )
{
2023-08-10 18:43:21 +02:00
if ( IsInvulnerable ( ) ) {
takedamage = DAMAGE_AIM ;
2023-08-10 03:46:28 +02:00
m_fLastInvulnerableTime = 0 ;
}
}
bool Player : : IsInvulnerable ( )
{
return m_fLastInvulnerableTime ! = 0 ;
}
void Player : : CancelInvulnerable ( )
{
2023-08-10 18:43:21 +02:00
if ( IsInvulnerable ( ) ) {
2023-08-10 03:46:28 +02:00
SetVulnerable ( ) ;
m_iInvulnerableTimeRemaining = - 1 ;
gi . centerprintf ( edict , " " ) ;
}
}
void Player : : InitInvulnerable ( )
{
2023-08-10 18:43:21 +02:00
m_fLastInvulnerableTime = 0 ;
2023-08-10 03:46:28 +02:00
m_iInvulnerableTimeRemaining = - 1 ;
}
void Player : : TickTeamSpawn ( )
{
2023-08-10 18:43:21 +02:00
int timeLeft ;
if ( ! IsSpectator ( ) & & ! IsDead ( ) | | ( GetTeam ( ) = = TEAM_SPECTATOR | | ! client - > pers . dm_primary [ 0 ] ) ) {
return ;
}
timeLeft = dmManager . GetTeamSpawnTimeLeft ( ) ;
if ( timeLeft = = - 1 ) {
// Can spawn
m_fSpawnTimeLeft = 0 ;
return ;
}
if ( timeLeft = = m_fSpawnTimeLeft ) {
// Still waiting
return ;
}
if ( m_bShouldRespawn ) {
// The player can spawn
m_fSpawnTimeLeft = 0 ;
return ;
}
m_fSpawnTimeLeft = timeLeft ;
if ( timeLeft ) {
if ( AllowTeamRespawn ( ) ) {
const char * string ;
if ( timeLeft = = 1 ) {
string = va ( " Next respawn in 1 second " ) ;
} else {
string = va ( " Next respawn in %d seconds " , timeLeft ) ;
}
gi . centerprintf ( edict , string ) ;
}
} else if ( m_bWaitingForRespawn & & AllowTeamRespawn ( ) ) {
m_bWaitingForRespawn = false ;
m_bDeathSpectator = false ;
EndSpectator ( ) ;
PostEvent ( EV_Player_Respawn , 0 ) ;
} else {
m_bShouldRespawn = true ;
}
2023-08-10 03:46:28 +02:00
}
bool Player : : ShouldForceSpectatorOnDeath ( ) const
{
return dmManager . GetTeamSpawnTimeLeft ( ) > 0 ;
}
2023-09-24 16:38:06 +02:00
bool Player : : HasVehicle ( ) const
2023-08-10 03:46:28 +02:00
{
return m_pVehicle ! = NULL ;
}
void Player : : setContentsSolid ( )
{
edict - > r . contents = CONTENTS_BODY ;
}
void Player : : UserSelectWeapon ( bool bWait )
{
2023-08-10 18:43:21 +02:00
nationality_t nationality ;
char buf [ 256 ] ;
2023-08-13 16:11:25 +02:00
if ( g_protocol < PROTOCOL_MOHTA_MIN ) {
//
// nationality was first introduced in 2.0
//
if ( bWait ) {
gi . SendServerCommand ( edict - g_entities , " stufftext \" wait 250;pushmenu_weaponselect \" " ) ;
} else {
gi . SendServerCommand ( edict - g_entities , " stufftext \" pushmenu_weaponselect \" " ) ;
}
return ;
}
2023-08-10 18:43:21 +02:00
if ( GetTeam ( ) = = TEAM_AXIS ) {
2023-11-14 00:49:32 +01:00
nationality = GetPlayerAxisTeamType ( client - > pers . dm_playergermanmodel ) ;
2023-08-10 18:43:21 +02:00
} else {
2023-11-14 00:49:32 +01:00
nationality = GetPlayerAlliedTeamType ( client - > pers . dm_playermodel ) ;
2023-08-10 18:43:21 +02:00
}
if ( bWait ) {
2024-09-20 21:53:48 +02:00
Q_strncpyz ( buf , " stufftext \" wait 250;pushmenu " , sizeof ( buf ) ) ;
2023-08-10 18:43:21 +02:00
} else {
2024-09-20 21:53:48 +02:00
Q_strncpyz ( buf , " stufftext \" pushmenu " , sizeof ( buf ) ) ;
2023-08-10 18:43:21 +02:00
}
if ( dmflags - > integer & DF_WEAPON_NO_RIFLE & & dmflags - > integer & DF_WEAPON_NO_SNIPER
& & dmflags - > integer & DF_WEAPON_NO_SMG & & dmflags - > integer & DF_WEAPON_NO_MG
& & dmflags - > integer & DF_WEAPON_NO_ROCKET & & dmflags - > integer & DF_WEAPON_NO_SHOTGUN
& & dmflags - > integer & DF_WEAPON_NO_LANDMINE & & ! QueryLandminesAllowed ( ) ) {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " dmflags " , va ( " %i " , dmflags - > integer & ~ DF_WEAPON_NO_RIFLE ) ) ;
2023-08-10 18:43:21 +02:00
Com_Printf ( " No valid weapons -- re-allowing the rifle \n " ) ;
2024-09-20 21:53:48 +02:00
Q_strncpyz ( client - > pers . dm_primary , " rifle " , sizeof ( client - > pers . dm_primary ) ) ;
2023-08-10 18:43:21 +02:00
}
switch ( nationality ) {
case NA_BRITISH :
2024-09-20 21:53:48 +02:00
Q_strcat ( buf , sizeof ( buf ) , " SelectPrimaryWeapon_british \" " ) ;
2023-08-10 18:43:21 +02:00
break ;
case NA_RUSSIAN :
2024-09-20 21:53:48 +02:00
Q_strcat ( buf , sizeof ( buf ) , " SelectPrimaryWeapon_russian \" " ) ;
2023-08-10 18:43:21 +02:00
break ;
case NA_GERMAN :
2024-09-20 21:53:48 +02:00
Q_strcat ( buf , sizeof ( buf ) , " SelectPrimaryWeapon_german \" " ) ;
2023-08-10 18:43:21 +02:00
break ;
case NA_ITALIAN :
2024-09-20 21:53:48 +02:00
Q_strcat ( buf , sizeof ( buf ) , " SelectPrimaryWeapon_italian \" " ) ;
2023-08-10 18:43:21 +02:00
break ;
default :
2024-09-20 21:53:48 +02:00
Q_strcat ( buf , sizeof ( buf ) , " SelectPrimaryWeapon \" " ) ;
2023-08-10 18:43:21 +02:00
break ;
}
gi . SendServerCommand ( edict - g_entities , buf ) ;
2023-08-10 03:46:28 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : PickWeaponEvent ( Event * ev )
2023-08-10 03:46:28 +02:00
{
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
return ;
}
UserSelectWeapon ( false ) ;
}
bool Player : : AllowTeamRespawn ( ) const
{
2023-08-10 18:43:21 +02:00
if ( m_bSpectator & & ! m_bDeathSpectator
& & ( ! dmManager . AllowTeamRespawn ( TEAM_ALLIES ) | | ! dmManager . AllowTeamRespawn ( TEAM_AXIS ) ) ) {
return false ;
}
if ( GetTeam ( ) > TEAM_AXIS | | GetTeam ( ) < TEAM_ALLIES ) {
return false ;
}
return dmManager . AllowTeamRespawn ( GetTeam ( ) ) ;
2023-08-10 03:46:28 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : EventUseWeaponClass ( Event * ev )
2023-08-10 03:46:28 +02:00
{
if ( m_pTurret | | level . playerfrozen ) {
return ;
}
Sentient : : EventUseWeaponClass ( ev ) ;
}
2023-08-10 18:43:21 +02:00
void Player : : EventAddKills ( Event * ev )
2023-08-10 03:46:28 +02:00
{
SafePtr < DM_Team > pTeam = GetDM_Team ( ) ;
2023-08-10 18:43:21 +02:00
if ( pTeam ) {
2023-08-10 03:46:28 +02:00
// Add kills to the team
pTeam - > AddKills ( this , ev - > GetInteger ( 1 ) ) ;
}
}
bool Player : : CanKnockback ( float minHealth ) const
{
if ( m_pTurret | | m_pVehicle ) {
return minHealth > = health ;
} else {
return 1 ;
}
}
2023-08-10 18:43:21 +02:00
void Player : : EventKillAxis ( Event * ev )
2023-08-10 03:46:28 +02:00
{
2023-08-10 18:43:21 +02:00
float radius = 0 ;
if ( ev - > NumArgs ( ) > = 1 ) {
radius = ev - > GetFloat ( 1 ) ;
}
for ( Sentient * pSent = level . m_HeadSentient [ TEAM_GERMAN ] ; pSent ; pSent = pSent - > m_NextSentient ) {
if ( radius > 0 ) {
Vector delta = pSent - > origin - origin ;
if ( radius < delta . length ( ) ) {
continue ;
}
}
pSent - > Damage ( this , this , pSent - > max_health + 25 , origin , vec_zero , vec_zero , 0 , 0 , MOD_NONE ) ;
}
2023-08-10 03:46:28 +02:00
}
2023-08-10 18:43:21 +02:00
void Player : : EventGetTurret ( Event * ev )
2023-08-10 03:46:28 +02:00
{
ev - > AddEntity ( m_pTurret ) ;
}
2023-08-10 18:43:21 +02:00
void Player : : EventGetVehicle ( Event * ev )
2023-08-10 03:46:28 +02:00
{
ev - > AddEntity ( m_pVehicle ) ;
}
2023-08-04 00:04:29 +02:00
bool Player : : IsReady ( void ) const
2016-03-27 11:49:47 +02:00
{
2023-09-23 19:38:17 +02:00
return m_bReady & & ! IsDead ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Spawned ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Event * ev = new Event ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddEntity ( this ) ;
scriptedEvents [ SE_SPAWN ] . Trigger ( ev ) ;
2016-03-27 11:49:47 +02:00
}
2024-09-22 19:59:10 +02:00
void Player : : AddKills ( int num )
2016-03-27 11:49:47 +02:00
{
2024-09-22 19:59:10 +02:00
num_kills + = num ;
if ( g_gametype - > integer > = GT_TEAM_ROUNDS ) {
num_deaths + = num ;
}
2016-03-27 11:49:47 +02:00
}
2024-09-22 19:59:10 +02:00
void Player : : AddDeaths ( int num )
2016-03-27 11:49:47 +02:00
{
2024-09-22 19:59:10 +02:00
num_deaths + = num ;
2016-03-27 11:49:47 +02:00
}
2024-09-22 19:59:10 +02:00
////////////////////////////
//
// Added in OPM
//
////////////////////////////
qboolean Player : : canUse ( )
2016-03-27 11:49:47 +02:00
{
2024-09-22 19:59:10 +02:00
int touch [ MAX_GENTITIES ] ;
int num = getUseableEntities ( touch , MAX_GENTITIES ) ;
return num ? true : false ;
2016-03-27 11:49:47 +02:00
}
2024-09-22 19:59:10 +02:00
qboolean Player : : canUse ( Entity * entity , bool requiresLookAt )
2016-03-27 11:49:47 +02:00
{
2024-09-22 19:59:10 +02:00
gentity_t * hit ;
int touch [ MAX_GENTITIES ] ;
int num ;
int i ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
num = getUseableEntities ( touch , MAX_GENTITIES , requiresLookAt ) ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
for ( i = 0 ; i < num ; i + + ) {
hit = & g_entities [ touch [ i ] ] ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
if ( ! hit - > inuse | | hit - > entity = = NULL ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
if ( hit - > entity = = entity ) {
return true ;
}
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
return false ;
2016-03-27 11:49:47 +02:00
}
2024-09-22 19:59:10 +02:00
int Player : : getUseableEntities ( int * touch , int maxcount , bool requiresLookAt )
2016-03-27 11:49:47 +02:00
{
2024-09-22 19:59:10 +02:00
Vector end ;
Vector start ;
trace_t trace ;
Vector offset ;
Vector max ;
Vector min ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
if ( ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & IsSpectator ( ) ) | | IsDead ( ) ) {
return 0 ;
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
if ( m_pTurret ) {
* touch = m_pTurret - > entnum ;
return 1 ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
if ( m_pTurret ) {
return 0 ;
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
AngleVectors ( client - > ps . viewangles , offset , NULL , NULL ) ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
start = origin ;
start . z + = client - > ps . viewheight ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
if ( requiresLookAt ) {
min = Vector ( - 4.f , - 4.f , - 4.f ) ;
max = Vector ( 4.f , 4.f , 4.f ) ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
end [ 0 ] = start [ 0 ] + ( offset [ 0 ] * 64.f ) ;
end [ 1 ] = start [ 1 ] + ( offset [ 1 ] * 64.f ) ;
if ( v_angle [ 0 ] < = 0.0f ) {
end [ 2 ] = start [ 2 ] + ( offset [ 2 ] * 40.f ) ;
} else {
end [ 2 ] = start [ 2 ] + ( offset [ 2 ] * 88.f ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
trace = G_Trace ( start , min , max , end , this , MASK_USE , false , " Player::getUseableEntity " ) ;
offset = trace . endpos ;
min = offset - Vector ( 16.f , 16.f , 16.f ) ;
max = offset + Vector ( 16.f , 16.f , 16.f ) ;
2023-08-04 00:04:29 +02:00
} else {
2024-09-22 19:59:10 +02:00
min = start - Vector ( 31.f , 31.f , 31.f ) ;
max = start + Vector ( 31.f , 31.f , 31.f ) ;
2023-08-04 00:04:29 +02:00
}
2024-09-22 19:59:10 +02:00
return gi . AreaEntities ( min , max , touch , maxcount ) ;
}
void Player : : Postthink ( void )
{
if ( bindmaster ) {
SetViewAngles ( GetViewAngles ( ) + Vector ( 0 , bindmaster - > avelocity [ YAW ] * level . frametime , 0 ) ) ;
}
}
void Player : : AdminRights ( Event * ev )
{
// FIXME: Admin manager ?
ev - > AddInteger ( 0 ) ;
UNIMPLEMENTED ( ) ;
}
void Player : : IsAdmin ( Event * ev )
{
// FIXME: Admin manager ?
ev - > AddInteger ( 0 ) ;
UNIMPLEMENTED ( ) ;
}
void Player : : BindWeap ( Event * ev )
{
2024-11-09 00:19:12 +01:00
Entity * ent = ev - > GetEntity ( 1 ) ;
Listener * scriptOwner ;
//
// FIXME: deprecate and use something else instead
// like implement this in the Item class directly
// this is dangerous to use especially if the weapon
// is a VehicleTurretGun, could easily mess up the camera
if ( ent ) {
scriptOwner = ent - > GetScriptOwner ( ) ;
if ( scriptOwner ! = this ) {
ent - > SetScriptOwner ( this ) ;
} else {
ent - > SetScriptOwner ( NULL ) ;
}
}
2024-09-22 19:59:10 +02:00
}
void Player : : AddDeaths ( Event * ev )
{
AddDeaths ( ev - > GetInteger ( 1 ) ) ;
}
void Player : : Dive ( Event * ev )
{
float height , airborne_duration , speed ;
Vector forwardvector = orientation [ 0 ] ;
height = ev - > GetFloat ( 1 ) ;
if ( ev - > NumArgs ( ) < 2 | | ev - > IsNilAt ( 2 ) ) {
airborne_duration = 1 ;
} else {
airborne_duration = ev - > GetFloat ( 2 ) ;
}
speed = height * airborne_duration ;
velocity [ 0 ] + = height * forwardvector [ 0 ] * ( speed / 16 ) ;
velocity [ 1 ] + = height * forwardvector [ 1 ] * ( speed / 16 ) ;
velocity [ 2 ] + = height * speed / 6.80f ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventSetTeam ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str team_name ;
teamtype_t teamType ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
team_name = ev - > GetString ( 1 ) ;
if ( ! team_name . length ( ) ) {
ScriptError ( " Invalid team name ! " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( Q_stricmp ( team_name , " none " ) = = 0 ) {
teamType = TEAM_NONE ;
} else if ( Q_stricmp ( team_name , " spectator " ) = = 0 ) {
teamType = TEAM_SPECTATOR ;
} else if ( Q_stricmp ( team_name , " freeforall " ) = = 0 ) {
teamType = TEAM_FREEFORALL ;
} else if ( Q_stricmp ( team_name , " allies " ) = = 0 ) {
teamType = TEAM_ALLIES ;
} else if ( Q_stricmp ( team_name , " axis " ) = = 0 ) {
teamType = TEAM_AXIS ;
} else {
ScriptError ( " Unknown team name \" %s \" \n " , team_name . c_str ( ) ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
SetTeam ( teamType ) ;
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
gi . DPrintf ( " Player::SetTeam : Player is now on team \" %s \" \n " , team_name . c_str ( ) ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventGetViewModelAnim ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddString ( m_sVMcurrent ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventGetViewModelAnimFinished ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( animDoneVM ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : EventGetViewModelAnimValid ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str anim_name = ev - > GetString ( 1 ) ;
str fullanim ;
bool bFullAnim = false ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
bFullAnim = ev - > GetBoolean ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! bFullAnim ) {
// Copy the item prefix and the anim name
Item * item = GetActiveWeapon ( WEAPON_MAIN ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! item ) {
item = ( Item * ) newActiveWeapon . weapon . Pointer ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( item ) {
fullanim = GetItemPrefix ( item - > getName ( ) ) + str ( " _ " ) + anim_name ;
} else {
fullanim = " unarmed_ " + anim_name ;
}
} else {
fullanim = anim_name ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! m_fpsTiki | | gi . Anim_NumForName ( m_fpsTiki , fullanim . c_str ( ) ) < 0 ) {
ev - > AddInteger ( 0 ) ;
} else {
ev - > AddInteger ( 1 ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : FreezeControls ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
m_bFrozen = ev - > GetBoolean ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetConnState ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2024-11-08 21:46:25 +01:00
// Assume CS_ACTIVE
ev - > AddInteger ( 4 ) ;
gi . DPrintf ( " getconnstate is deprecated and will always return 4 (CS_ACTIVE). \n The player is created only when the client begins (CS_ACTIVE state). \n " ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetDamageMultiplier ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddFloat ( damage_multiplier ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetDeaths ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( num_deaths ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetKillHandler ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-11-27 20:07:57 +01:00
if ( m_killedLabel . IsSet ( ) ) {
m_killedLabel . GetScriptValue ( & ev - > GetValue ( ) ) ;
2023-08-04 00:04:29 +02:00
} else {
ev - > AddNil ( ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetKills ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( num_kills ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetMoveSpeedScale ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ev - > AddFloat ( speed_multiplier [ 0 ] ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetLegsState ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
const char * name ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( currentState_Legs ! = NULL ) {
name = currentState_Legs - > getName ( ) ;
} else {
name = " none " ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddString ( name ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetStateFile ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
int clientNum = G_GetClientNumber ( this ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( m_sStateFile . length ( ) ) {
ev - > AddString ( m_sStateFile ) ;
} else {
ev - > AddString ( g_statefile - > string ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : GetTorsoState ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
const char * name ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( currentState_Torso ! = NULL ) {
name = currentState_Torso - > getName ( ) ;
} else {
name = " none " ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddString ( name ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : HideEntity ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
// FIXME: todo
2024-09-22 19:59:10 +02:00
UNIMPLEMENTED ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : ShowEntity ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
// FIXME: REDO
2024-09-22 19:59:10 +02:00
UNIMPLEMENTED ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Inventory ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Entity * ent = NULL ;
ScriptVariable * ref = new ScriptVariable , * array = new ScriptVariable ;
int i = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ref - > setRefValue ( array ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
for ( i = 0 ; i < inventory . NumObjects ( ) ; i + + ) {
ent = G_GetEntity ( inventory [ i ] ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ent = = NULL ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ScriptVariable * index = new ScriptVariable , * value = new ScriptVariable ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
index - > setIntValue ( i + 1 ) ;
value - > setListenerValue ( ( Listener * ) ent ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ref - > setArrayAt ( * index , * value ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddValue ( * array ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : InventorySet ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
ScriptVariable array ;
ScriptVariable * value ;
Entity * ent ;
int arraysize ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > IsNilAt ( 1 ) ) {
// Just clear the inventory
inventory . ClearObjectList ( ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Retrieve the array
array = ev - > GetValue ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Cast the array
array . CastConstArrayValue ( ) ;
arraysize = array . arraysize ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Detach all active weapons and free the inventory
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( inventory . NumObjects ( ) > 0 ) {
inventory . FreeObjectList ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( arraysize < 1 ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Allocate an inventory
for ( int i = 1 ; i < = arraysize ; i + + ) {
// Retrieve the value from the array
value = array [ i ] ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Get the entity from the value
ent = ( Entity * ) value - > entityValue ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ent = = NULL | | ! ent - > edict - > inuse ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Add the entity to the inventory
inventory . AddObject ( ent - > entnum ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
// Clear the variable
array . Clear ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : LeanLeftHeld ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Player * player = NULL ;
int buttonheld = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
player = ( Player * ) this ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
buttonheld = ! ! ( player - > buttons & BUTTON_LEAN_LEFT ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( buttonheld ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : LeanRightHeld ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Player * player = NULL ;
int buttonheld = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
player = ( Player * ) this ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
buttonheld = ! ! ( player - > buttons & BUTTON_LEAN_RIGHT ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( buttonheld ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : PlayLocalSound ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str soundName = ev - > GetString ( 1 ) ;
qboolean loop = false ;
float time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
loop = ev - > GetBoolean ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
time = ev - > GetFloat ( 3 ) ;
} else {
time = 0.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AliasListNode_t * alias = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
const char * found = gi . GlobalAlias_FindRandom ( soundName , & alias ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( found = = NULL ) {
gi . DPrintf ( " ERROR: Player::PlayLocalSound: %s needs to be aliased - Please fix. \n " , soundName . c_str ( ) ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
# ifdef OPM_FEATURES
2023-08-10 14:18:40 +02:00
gi . MSG_SetClient ( client - > ps . clientNum ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 14:18:40 +02:00
gi . MSG_StartCGM ( CGM_PLAYLOCALSOUND ) ;
gi . MSG_WriteString ( found ) ;
gi . MSG_WriteBits ( ! ! loop , 1 ) ;
gi . MSG_WriteFloat ( time ) ;
gi . MSG_WriteFloat ( alias - > volume ) ;
gi . MSG_EndCGM ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-10 14:18:40 +02:00
return ;
2024-09-22 19:59:10 +02:00
# endif
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( loop ) {
edict - > s . loopSound = gi . soundindex ( found , alias - > streamed ) ;
edict - > s . loopSoundVolume = 1.0f ;
edict - > s . loopSoundMinDist = 0 ;
edict - > s . loopSoundMaxDist = 96 ;
edict - > s . loopSoundPitch = 1.0f ;
edict - > s . loopSoundFlags = 1 ; // local sound
} else {
gi . Sound ( & edict - > s . origin , entnum , CHAN_LOCAL , found , 1.0f , 0 , 1.0f , 96 , alias - > streamed ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : RunHeld ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Player * player = NULL ;
int buttonheld = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
player = ( Player * ) this ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
buttonheld = ! ! ( player - > buttons & BUTTON_RUN ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( buttonheld ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SecFireHeld ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
Player * player = NULL ;
int buttonheld = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
player = ( Player * ) this ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
buttonheld = ! ! ( player - > buttons & BUTTON_ATTACKRIGHT ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddInteger ( buttonheld ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetAnimSpeed ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float speed ;
Player * player = ( Player * ) this ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
speed = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( speed < 0.0f ) {
speed = 0.0f ;
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
UNIMPLEMENTED ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetKillHandler ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( ev - > IsNilAt ( 1 ) | | ( ev - > IsStringAt ( 1 ) & & ! ev - > GetString ( 1 ) . icmp ( " none " ) ) ) {
2023-11-27 20:07:57 +01:00
m_killedLabel . Clear ( ) ;
2023-08-04 00:04:29 +02:00
} else {
2023-11-27 20:07:57 +01:00
m_killedLabel . SetScript ( ev - > GetValue ( 1 ) ) ;
2023-08-04 00:04:29 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetSpeed ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float speed ;
Player * player = ( Player * ) this ;
int clientNum = G_GetClientNumber ( this ) ;
int index = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
speed = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( speed < 0.0f ) {
speed = 0.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
index = ev - > GetInteger ( 2 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
/* Reserve a space for moveSpeedScale */
if ( index < 1 | | index > MAX_SPEED_MULTIPLIERS ) {
gi . Printf ( " Player::SetSpeed : invalid index %d. Index must be between 1-%d \n " , index , speed_multiplier ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
return ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
speed_multiplier [ index ] = speed ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : SetStateFile ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
int clientNum = G_GetClientNumber ( this ) ;
qboolean bRemove = false ;
str string ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) < = 0 ) {
bRemove = true ;
} else {
string = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ! string ) {
bRemove = true ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( bRemove ) {
m_sStateFile = " " ;
} else {
m_sStateFile = string ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : StopLocalSound ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str soundName = ev - > GetString ( 1 ) ;
float time ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
time = ev - > GetFloat ( 2 ) ;
} else {
time = 0.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
AliasListNode_t * alias = NULL ;
const char * found = gi . GlobalAlias_FindRandom ( soundName , & alias ) ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( found = = NULL ) {
gi . DPrintf ( " ERROR: Player::StopLocalSound: %s needs to be aliased - Please fix. \n " , soundName . c_str ( ) ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
edict - > s . loopSound = 0 ;
gi . StopSound ( entnum , CHAN_LOCAL ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : Userinfo ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
if ( ! client ) {
ScriptError ( " Entity is probably not of player type - userinfo \n " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
ev - > AddString ( client - > pers . userinfo ) ;
}
2016-03-27 11:49:47 +02:00
2024-09-22 19:59:10 +02:00
int Player : : GetNumKills ( void ) const
{
return num_kills ;
}
int Player : : GetNumDeaths ( void ) const
{
return num_deaths ;
}
# ifdef OPM_FEATURES
void Player : : EventEarthquake ( Event * ev )
{
float duration = ev - > GetFloat ( 1 ) ;
float magnitude = ev - > GetFloat ( 2 ) ;
qboolean no_rampup = ev - > GetBoolean ( 3 ) ;
qboolean no_rampdown = ev - > GetBoolean ( 4 ) ;
// full realistic, smooth earthquake
if ( ev - > NumArgs ( ) > 4 ) {
Vector location = ev - > GetVector ( 5 ) ;
float radius = 1.0f ;
if ( ev - > NumArgs ( ) > 5 ) {
radius = ev - > GetFloat ( 6 ) ;
}
gi . SendServerCommand (
edict - g_entities ,
" eq %f %f %d %d %f %f %f %f " ,
duration ,
magnitude ,
no_rampup ,
no_rampdown ,
location [ 0 ] ,
location [ 1 ] ,
location [ 2 ] ,
radius
) ;
} else {
gi . SendServerCommand ( edict - g_entities , " eq %f %f %d %d " , duration , magnitude , no_rampup , no_rampdown ) ;
}
}
void Player : : SetClientFlag ( Event * ev )
{
str name = ev - > GetString ( 1 ) ;
gi . SendServerCommand ( client - > ps . clientNum , " cf %s " , name . c_str ( ) ) ;
}
void Player : : SetEntityShader ( Event * ev )
{
Entity * entity = ev - > GetEntity ( 1 ) ;
str shadername = ev - > GetString ( 2 ) ;
qboolean fReset = false ;
if ( entity = = NULL ) {
ScriptError ( " Invalid entity ! " ) ;
}
if ( ! shadername . length ( ) ) {
shadername = " default " ;
fReset = true ;
}
gi . SendServerCommand ( edict - g_entities , " setshader %d %s %d " , entity - > entnum , shadername . c_str ( ) , fReset ) ;
}
void Player : : SetLocalSoundRate ( Event * ev )
{
str name = ev - > GetString ( 1 ) ;
float rate = ev - > GetFloat ( 2 ) ;
float time ;
if ( ev - > NumArgs ( ) > 2 ) {
time = ev - > GetFloat ( 3 ) ;
} else {
time = 0.0f ;
}
AliasListNode_t * alias = NULL ;
const char * found = gi . GlobalAlias_FindRandom ( name , & alias ) ;
if ( found = = NULL ) {
gi . DPrintf ( " ERROR: Player::SetLocalSoundRate: %s needs to be aliased - Please fix. \n " , name . c_str ( ) ) ;
return ;
}
gi . MSG_SetClient ( client - > ps . clientNum ) ;
// FIXME...
/*
gi . MSG_StartCGM ( CGM_SETLOCALSOUNDRATE ) ;
gi . MSG_WriteString ( found ) ;
gi . MSG_WriteFloat ( rate ) ;
gi . MSG_WriteFloat ( time ) ;
gi . MSG_EndCGM ( ) ;
*/
}
void Player : : SetVMASpeed ( Event * ev )
{
str name = ev - > GetString ( 1 ) ;
float speed = ev - > GetFloat ( 2 ) ;
if ( ! client | | ! sv_specialgame - > integer ) {
return ;
}
vma_t * vma = & vmalist [ name ] ;
if ( speed < 0.0f ) {
speed = 0.0f ;
}
vma - > name = name ;
vma - > speed = speed ;
// FIXME...
/*
gi . MSG_SetClient ( edict - g_entities ) ;
gi . MSG_StartCGM ( CGM_SETVMASPEED ) ;
gi . MSG_WriteString ( name ) ;
gi . MSG_WriteFloat ( speed ) ;
gi . MSG_EndCGM ( ) ;
*/
}
2023-08-04 00:04:29 +02:00
void Player : : VisionGetNaked ( Event * ev )
{
// return the global vision
if ( ! m_sVision . length ( ) ) {
ev - > AddString ( vision_current ) ;
} else {
ev - > AddString ( m_sVision ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : VisionSetBlur ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
float blur_level = ev - > GetFloat ( 1 ) ;
float fade_time ;
if ( ev - > NumArgs ( ) > 1 ) {
fade_time = ev - > GetFloat ( 2 ) ;
} else {
fade_time = 0.0f ;
}
gi . SendServerCommand ( edict - g_entities , " vsb %f %f " , blur_level , fade_time ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-04 00:04:29 +02:00
void Player : : VisionSetNaked ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-04 00:04:29 +02:00
str vision = ev - > GetString ( 1 ) ;
float fade_time ;
float phase ;
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
fade_time = ev - > GetFloat ( 2 ) ;
} else {
fade_time = 0.0f ;
}
if ( ev - > NumArgs ( ) > 2 ) {
phase = ev - > GetFloat ( 3 ) ;
} else {
phase = 0.0f ;
}
if ( ! vision . length ( ) ) {
vision = vision_current ;
}
2016-03-27 11:49:47 +02:00
2023-08-04 00:04:29 +02:00
if ( vision . length ( ) > = MAX_STRING_TOKENS ) {
ScriptError ( " vision_name exceeds the maximum vision name limit (256) ! \n " ) ;
}
m_sVision = vision ;
gi . SendServerCommand ( edict - g_entities , " vsn %s %f %f " , vision . c_str ( ) , fade_time , phase ) ;
2016-03-27 11:49:47 +02:00
}
2024-09-22 19:59:10 +02:00
# endif