2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2022-07-30 08:57:46 +00:00
# include "character.h"
# include "laser.h"
2023-05-06 20:32:36 +00:00
# include "pickup.h"
2022-07-30 08:57:46 +00:00
# include "projectile.h"
2020-03-11 00:58:50 +00:00
# include <antibot/antibot_data.h>
2022-06-17 17:54:10 +00:00
# include <engine/antibot.h>
2010-05-29 07:25:38 +00:00
# include <engine/shared/config.h>
2022-07-30 08:57:46 +00:00
# include <game/generated/protocol.h>
2021-01-09 13:40:30 +00:00
# include <game/generated/server_data.h>
2010-05-29 07:25:38 +00:00
# include <game/mapitems.h>
2022-07-30 08:57:46 +00:00
2020-09-26 19:41:58 +00:00
# include <game/server/gamecontext.h>
2022-06-17 17:54:10 +00:00
# include <game/server/gamecontroller.h>
2021-01-09 14:37:02 +00:00
# include <game/server/player.h>
2011-04-09 06:41:31 +00:00
# include <game/server/score.h>
2021-01-12 23:29:20 +00:00
# include <game/server/teams.h>
2011-04-09 06:41:31 +00:00
2010-05-29 07:25:38 +00:00
MACRO_ALLOC_POOL_ID_IMPL ( CCharacter , MAX_CLIENTS )
2008-09-24 09:03:49 +00:00
2011-01-29 00:59:50 +00:00
// Character, "physical" player's part
2022-05-18 08:45:31 +00:00
CCharacter : : CCharacter ( CGameWorld * pWorld , CNetObj_PlayerInput LastInput ) :
2022-05-28 17:28:44 +00:00
CEntity ( pWorld , CGameWorld : : ENTTYPE_CHARACTER , vec2 ( 0 , 0 ) , CCharacterCore : : PhysicalSize ( ) )
2008-09-23 07:43:41 +00:00
{
2010-05-29 07:25:38 +00:00
m_Health = 0 ;
m_Armor = 0 ;
2019-05-01 22:34:20 +00:00
m_StrongWeakID = 0 ;
2020-10-17 16:17:13 +00:00
2022-05-18 08:45:31 +00:00
m_Input = LastInput ;
2022-05-22 08:39:18 +00:00
// never initialize both to zero
2020-10-17 16:17:13 +00:00
m_Input . m_TargetX = 0 ;
m_Input . m_TargetY = - 1 ;
m_LatestPrevPrevInput = m_LatestPrevInput = m_LatestInput = m_PrevInput = m_SavedInput = m_Input ;
2022-07-05 14:13:48 +00:00
m_LastTimeCp = - 1 ;
m_LastTimeCpBroadcasted = - 1 ;
for ( float & CurrentTimeCp : m_aCurrentTimeCp )
{
CurrentTimeCp = 0.0f ;
}
2008-09-23 07:43:41 +00:00
}
2008-07-06 11:21:21 +00:00
2010-05-29 07:25:38 +00:00
void CCharacter : : Reset ( )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
Destroy ( ) ;
2008-07-06 11:21:21 +00:00
}
2010-05-29 07:25:38 +00:00
bool CCharacter : : Spawn ( CPlayer * pPlayer , vec2 Pos )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
m_EmoteStop = - 1 ;
m_LastAction = - 1 ;
2012-10-06 11:47:37 +00:00
m_LastNoAmmoSound = - 1 ;
2010-05-29 07:25:38 +00:00
m_LastWeapon = WEAPON_HAMMER ;
m_QueuedWeapon = - 1 ;
2014-12-29 14:54:55 +00:00
m_LastRefillJumps = false ;
2014-02-09 22:31:29 +00:00
m_LastPenalty = false ;
2015-03-10 21:57:40 +00:00
m_LastBonus = false ;
2015-07-09 00:08:14 +00:00
2018-07-15 21:03:30 +00:00
m_TeleGunTeleport = false ;
2018-11-02 23:02:20 +00:00
m_IsBlueTeleGunTeleport = false ;
2018-02-14 15:27:26 +00:00
2010-05-29 07:25:38 +00:00
m_pPlayer = pPlayer ;
m_Pos = Pos ;
2011-04-13 18:37:12 +00:00
2020-03-11 00:58:50 +00:00
mem_zero ( & m_LatestPrevPrevInput , sizeof ( m_LatestPrevPrevInput ) ) ;
2020-10-17 17:02:58 +00:00
m_LatestPrevPrevInput . m_TargetY = - 1 ;
2022-04-17 21:04:54 +00:00
m_NumInputs = 0 ;
2020-03-11 00:58:50 +00:00
m_SpawnTick = Server ( ) - > Tick ( ) ;
m_WeaponChangeTick = Server ( ) - > Tick ( ) ;
Antibot ( ) - > OnSpawn ( m_pPlayer - > GetCID ( ) ) ;
2010-05-29 07:25:38 +00:00
m_Core . Reset ( ) ;
2022-05-28 18:24:24 +00:00
m_Core . Init ( & GameServer ( ) - > m_World . m_Core , Collision ( ) ) ;
2014-04-14 08:56:14 +00:00
m_Core . m_ActiveWeapon = WEAPON_GUN ;
2010-05-29 07:25:38 +00:00
m_Core . m_Pos = m_Pos ;
2022-05-22 19:40:15 +00:00
m_Core . m_Id = m_pPlayer - > GetCID ( ) ;
2010-05-29 07:25:38 +00:00
GameServer ( ) - > m_World . m_Core . m_apCharacters [ m_pPlayer - > GetCID ( ) ] = & m_Core ;
2011-01-29 00:59:50 +00:00
2010-05-29 07:25:38 +00:00
m_ReckoningTick = 0 ;
2022-05-27 17:19:20 +00:00
m_SendCore = CCharacterCore ( ) ;
2023-11-22 17:34:39 +00:00
m_ReckoningCore = CCharacterCore ( ) ;
2023-09-24 16:14:09 +00:00
2010-05-29 07:25:38 +00:00
GameServer ( ) - > m_World . InsertEntity ( this ) ;
m_Alive = true ;
2011-01-29 00:59:50 +00:00
2010-05-29 07:25:38 +00:00
GameServer ( ) - > m_pController - > OnCharacterSpawn ( this ) ;
2011-01-29 00:59:50 +00:00
DDRaceInit ( ) ;
2015-07-09 00:08:14 +00:00
2022-05-28 18:24:24 +00:00
m_TuneZone = Collision ( ) - > IsTune ( Collision ( ) - > GetMapIndex ( Pos ) ) ;
2014-04-18 12:27:58 +00:00
m_TuneZoneOld = - 1 ; // no zone leave msg on spawn
2014-03-27 00:28:44 +00:00
m_NeededFaketuning = 0 ; // reset fake tunings on respawn and send the client
2014-04-18 12:27:58 +00:00
SendZoneMsgs ( ) ; // we want a entermessage also on spawn
2014-03-27 00:28:44 +00:00
GameServer ( ) - > SendTuningParams ( m_pPlayer - > GetCID ( ) , m_TuneZone ) ;
2011-01-29 00:59:50 +00:00
2014-09-26 00:05:22 +00:00
Server ( ) - > StartRecord ( m_pPlayer - > GetCID ( ) ) ;
2008-07-06 11:21:21 +00:00
return true ;
}
2010-05-29 07:25:38 +00:00
void CCharacter : : Destroy ( )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
GameServer ( ) - > m_World . m_Core . m_apCharacters [ m_pPlayer - > GetCID ( ) ] = 0 ;
m_Alive = false ;
2022-06-30 17:29:58 +00:00
SetSolo ( false ) ;
2008-07-06 11:21:21 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacter : : SetWeapon ( int W )
2008-07-06 11:21:21 +00:00
{
2014-04-14 08:56:14 +00:00
if ( W = = m_Core . m_ActiveWeapon )
2008-07-06 11:21:21 +00:00
return ;
2011-04-13 18:37:12 +00:00
2014-04-14 08:56:14 +00:00
m_LastWeapon = m_Core . m_ActiveWeapon ;
2010-05-29 07:25:38 +00:00
m_QueuedWeapon = - 1 ;
2014-09-06 22:15:03 +00:00
m_Core . m_ActiveWeapon = W ;
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_WEAPON_SWITCH , TeamMask ( ) ) ;
2011-04-13 18:37:12 +00:00
2014-04-14 08:56:14 +00:00
if ( m_Core . m_ActiveWeapon < 0 | | m_Core . m_ActiveWeapon > = NUM_WEAPONS )
m_Core . m_ActiveWeapon = 0 ;
2008-07-06 11:21:21 +00:00
}
2022-06-30 17:29:58 +00:00
void CCharacter : : SetJetpack ( bool Active )
{
m_Core . m_Jetpack = Active ;
}
2014-12-25 10:37:44 +00:00
void CCharacter : : SetSolo ( bool Solo )
{
2019-04-21 13:16:28 +00:00
m_Core . m_Solo = Solo ;
2014-12-25 10:37:44 +00:00
Teams ( ) - > m_Core . SetSolo ( m_pPlayer - > GetCID ( ) , Solo ) ;
}
2022-06-30 17:29:58 +00:00
void CCharacter : : SetSuper ( bool Super )
{
m_Core . m_Super = Super ;
if ( Super )
{
m_TeamBeforeSuper = Team ( ) ;
Teams ( ) - > SetCharacterTeam ( GetPlayer ( ) - > GetCID ( ) , TEAM_SUPER ) ;
m_DDRaceState = DDRACE_CHEAT ;
}
else
{
Teams ( ) - > SetForceCharacterTeam ( GetPlayer ( ) - > GetCID ( ) , m_TeamBeforeSuper ) ;
}
}
2022-04-18 14:37:35 +00:00
void CCharacter : : SetLiveFrozen ( bool Active )
{
m_Core . m_LiveFrozen = Active ;
}
2022-06-30 17:29:58 +00:00
void CCharacter : : SetDeepFrozen ( bool Active )
{
m_Core . m_DeepFrozen = Active ;
}
2010-05-29 07:25:38 +00:00
bool CCharacter : : IsGrounded ( )
2008-07-06 11:21:21 +00:00
{
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > CheckPoint ( m_Pos . x + GetProximityRadius ( ) / 2 , m_Pos . y + GetProximityRadius ( ) / 2 + 5 ) )
2008-07-06 11:21:21 +00:00
return true ;
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > CheckPoint ( m_Pos . x - GetProximityRadius ( ) / 2 , m_Pos . y + GetProximityRadius ( ) / 2 + 5 ) )
2008-07-06 11:21:21 +00:00
return true ;
2015-04-16 15:28:03 +00:00
2022-05-28 18:24:24 +00:00
int MoveRestrictionsBelow = Collision ( ) - > GetMoveRestrictions ( m_Pos + vec2 ( 0 , GetProximityRadius ( ) / 2 + 4 ) , 0.0f ) ;
2022-01-22 16:34:23 +00:00
return ( MoveRestrictionsBelow & CANTMOVE_DOWN ) ! = 0 ;
2008-07-06 11:21:21 +00:00
}
2014-04-13 23:34:50 +00:00
void CCharacter : : HandleJetpack ( )
{
vec2 Direction = normalize ( vec2 ( m_LatestInput . m_TargetX , m_LatestInput . m_TargetY ) ) ;
bool FullAuto = false ;
2019-11-22 14:37:18 +00:00
if ( m_Core . m_ActiveWeapon = = WEAPON_GRENADE | | m_Core . m_ActiveWeapon = = WEAPON_SHOTGUN | | m_Core . m_ActiveWeapon = = WEAPON_LASER )
2014-04-13 23:34:50 +00:00
FullAuto = true ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Jetpack & & m_Core . m_ActiveWeapon = = WEAPON_GUN )
2014-04-13 23:34:50 +00:00
FullAuto = true ;
// check if we gonna fire
bool WillFire = false ;
if ( CountInput ( m_LatestPrevInput . m_Fire , m_LatestInput . m_Fire ) . m_Presses )
WillFire = true ;
2022-03-21 22:50:41 +00:00
if ( FullAuto & & ( m_LatestInput . m_Fire & 1 ) & & m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_Ammo )
2014-04-13 23:34:50 +00:00
WillFire = true ;
if ( ! WillFire )
return ;
// check for ammo
2022-03-21 22:50:41 +00:00
if ( ! m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_Ammo | | m_FreezeTime )
2014-04-13 23:34:50 +00:00
{
return ;
}
2014-04-14 08:56:14 +00:00
switch ( m_Core . m_ActiveWeapon )
2014-04-13 23:34:50 +00:00
{
2020-09-26 19:41:58 +00:00
case WEAPON_GUN :
{
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Jetpack )
2014-04-13 23:34:50 +00:00
{
2020-09-26 19:41:58 +00:00
float Strength ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
Strength = Tuning ( ) - > m_JetpackStrength ;
2020-09-26 19:41:58 +00:00
else
2023-09-05 23:08:01 +00:00
Strength = TuningList ( ) [ m_TuneZone ] . m_JetpackStrength ;
2020-09-26 19:41:58 +00:00
TakeDamage ( Direction * - 1.0f * ( Strength / 100.0f / 6.11f ) , 0 , m_pPlayer - > GetCID ( ) , m_Core . m_ActiveWeapon ) ;
2014-04-13 23:34:50 +00:00
}
}
2020-09-26 19:41:58 +00:00
}
2014-04-13 23:34:50 +00:00
}
2008-07-06 11:21:21 +00:00
2010-05-29 07:25:38 +00:00
void CCharacter : : HandleNinja ( )
2008-07-06 11:21:21 +00:00
{
2014-04-14 08:56:14 +00:00
if ( m_Core . m_ActiveWeapon ! = WEAPON_NINJA )
2010-05-29 07:25:38 +00:00
return ;
2011-04-13 18:37:12 +00:00
2022-03-24 00:05:41 +00:00
if ( ( Server ( ) - > Tick ( ) - m_Core . m_Ninja . m_ActivationTick ) > ( g_pData - > m_Weapons . m_Ninja . m_Duration * Server ( ) - > TickSpeed ( ) / 1000 ) )
2008-07-06 11:21:21 +00:00
{
// time's up, return
2016-10-08 17:42:42 +00:00
RemoveNinja ( ) ;
2010-05-29 07:25:38 +00:00
return ;
2008-07-06 11:21:21 +00:00
}
2011-04-13 18:37:12 +00:00
2022-03-24 00:05:41 +00:00
int NinjaTime = m_Core . m_Ninja . m_ActivationTick + ( g_pData - > m_Weapons . m_Ninja . m_Duration * Server ( ) - > TickSpeed ( ) / 1000 ) - Server ( ) - > Tick ( ) ;
2013-12-09 12:53:26 +00:00
2020-09-26 19:41:58 +00:00
if ( NinjaTime % Server ( ) - > TickSpeed ( ) = = 0 & & NinjaTime / Server ( ) - > TickSpeed ( ) < = 5 )
2013-12-09 12:53:26 +00:00
{
2022-06-25 09:16:59 +00:00
GameServer ( ) - > CreateDamageInd ( m_Pos , 0 , NinjaTime / Server ( ) - > TickSpeed ( ) , TeamMask ( ) & GameServer ( ) - > ClientsMaskExcludeClientVersionAndHigher ( VERSION_DDNET_NEW_HUD ) ) ;
2013-12-09 12:53:26 +00:00
}
2020-06-20 10:54:41 +00:00
m_Armor = clamp ( 10 - ( NinjaTime / 15 ) , 0 , 10 ) ;
2013-12-09 12:53:26 +00:00
2010-05-29 07:25:38 +00:00
// force ninja Weapon
SetWeapon ( WEAPON_NINJA ) ;
2008-07-06 11:21:21 +00:00
2022-03-24 00:05:41 +00:00
m_Core . m_Ninja . m_CurrentMoveTime - - ;
2008-07-06 11:21:21 +00:00
2022-03-24 00:05:41 +00:00
if ( m_Core . m_Ninja . m_CurrentMoveTime = = 0 )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
// reset velocity
2022-03-24 00:05:41 +00:00
m_Core . m_Vel = m_Core . m_Ninja . m_ActivationDir * m_Core . m_Ninja . m_OldVelAmount ;
2008-07-06 11:21:21 +00:00
}
2022-03-24 00:05:41 +00:00
if ( m_Core . m_Ninja . m_CurrentMoveTime > 0 )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
// Set velocity
2022-03-24 00:05:41 +00:00
m_Core . m_Vel = m_Core . m_Ninja . m_ActivationDir * g_pData - > m_Weapons . m_Ninja . m_Velocity ;
2010-05-29 07:25:38 +00:00
vec2 OldPos = m_Pos ;
2022-06-12 12:06:58 +00:00
vec2 GroundElasticity ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
GroundElasticity = vec2 ( Tuning ( ) - > m_GroundElasticityX , Tuning ( ) - > m_GroundElasticityY ) ;
2022-06-12 12:06:58 +00:00
else
2023-09-05 23:08:01 +00:00
GroundElasticity = vec2 ( TuningList ( ) [ m_TuneZone ] . m_GroundElasticityX , TuningList ( ) [ m_TuneZone ] . m_GroundElasticityY ) ;
2022-06-12 12:06:58 +00:00
Collision ( ) - > MoveBox ( & m_Core . m_Pos , & m_Core . m_Vel , vec2 ( GetProximityRadius ( ) , GetProximityRadius ( ) ) , GroundElasticity ) ;
2011-04-13 18:37:12 +00:00
2008-07-06 11:21:21 +00:00
// reset velocity so the client doesn't predict stuff
2010-05-29 07:25:38 +00:00
m_Core . m_Vel = vec2 ( 0.f , 0.f ) ;
2008-07-06 11:21:21 +00:00
2010-05-29 07:25:38 +00:00
// check if we Hit anything along the way
2008-07-06 11:21:21 +00:00
{
2022-11-09 22:07:15 +00:00
CEntity * apEnts [ MAX_CLIENTS ] ;
2021-01-09 20:40:03 +00:00
float Radius = GetProximityRadius ( ) * 2.0f ;
2022-12-30 17:03:05 +00:00
int Num = GameServer ( ) - > m_World . FindEntities ( OldPos , Radius , apEnts , MAX_CLIENTS , CGameWorld : : ENTTYPE_CHARACTER ) ;
2008-07-06 11:21:21 +00:00
2013-08-04 20:50:14 +00:00
// check that we're not in solo part
2020-09-26 19:41:58 +00:00
if ( Teams ( ) - > m_Core . GetSolo ( m_pPlayer - > GetCID ( ) ) )
2013-08-04 20:50:14 +00:00
return ;
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < Num ; + + i )
2008-07-06 11:21:21 +00:00
{
2022-11-09 22:07:15 +00:00
auto * pChr = static_cast < CCharacter * > ( apEnts [ i ] ) ;
if ( pChr = = this )
2008-07-06 11:21:21 +00:00
continue ;
2011-04-13 18:37:12 +00:00
2013-08-04 20:50:14 +00:00
// Don't hit players in other teams
2022-11-09 22:07:15 +00:00
if ( Team ( ) ! = pChr - > Team ( ) )
2013-08-04 20:50:14 +00:00
continue ;
// Don't hit players in solo parts
2022-11-09 22:07:15 +00:00
if ( Teams ( ) - > m_Core . GetSolo ( pChr - > m_pPlayer - > GetCID ( ) ) )
2013-08-04 20:50:14 +00:00
return ;
2010-05-29 07:25:38 +00:00
// make sure we haven't Hit this object before
bool bAlreadyHit = false ;
2020-09-26 19:41:58 +00:00
for ( int j = 0 ; j < m_NumObjectsHit ; j + + )
2008-07-06 11:21:21 +00:00
{
2022-11-09 22:07:15 +00:00
if ( m_apHitObjects [ j ] = = pChr )
2010-05-29 07:25:38 +00:00
bAlreadyHit = true ;
2008-07-06 11:21:21 +00:00
}
2020-09-26 19:41:58 +00:00
if ( bAlreadyHit )
2008-07-06 11:21:21 +00:00
continue ;
// check so we are sufficiently close
2022-11-09 22:07:15 +00:00
if ( distance ( pChr - > m_Pos , m_Pos ) > ( GetProximityRadius ( ) * 2.0f ) )
2008-07-06 11:21:21 +00:00
continue ;
2022-06-16 22:12:25 +00:00
// Hit a player, give them damage and stuffs...
2022-11-09 22:07:15 +00:00
GameServer ( ) - > CreateSound ( pChr - > m_Pos , SOUND_NINJA_HIT , TeamMask ( ) ) ;
2008-07-06 11:21:21 +00:00
// set his velocity to fast upward (for now)
2010-05-29 07:25:38 +00:00
if ( m_NumObjectsHit < 10 )
2022-11-09 22:07:15 +00:00
m_apHitObjects [ m_NumObjectsHit + + ] = pChr ;
2011-04-13 18:37:12 +00:00
2022-11-09 22:07:15 +00:00
pChr - > TakeDamage ( vec2 ( 0 , - 10.0f ) , g_pData - > m_Weapons . m_Ninja . m_pBase - > m_Damage , m_pPlayer - > GetCID ( ) , WEAPON_NINJA ) ;
2008-07-06 11:21:21 +00:00
}
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
return ;
2008-07-06 11:21:21 +00:00
}
}
2010-05-29 07:25:38 +00:00
void CCharacter : : DoWeaponSwitch ( )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
// make sure we can switch
2022-03-21 22:50:41 +00:00
if ( m_ReloadTimer ! = 0 | | m_QueuedWeapon = = - 1 | | m_Core . m_aWeapons [ WEAPON_NINJA ] . m_Got | | ! m_Core . m_aWeapons [ m_QueuedWeapon ] . m_Got )
2008-07-06 11:21:21 +00:00
return ;
2010-05-29 07:25:38 +00:00
// switch Weapon
SetWeapon ( m_QueuedWeapon ) ;
2008-07-06 11:21:21 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacter : : HandleWeaponSwitch ( )
2008-07-06 11:21:21 +00:00
{
2014-04-14 08:56:14 +00:00
int WantedWeapon = m_Core . m_ActiveWeapon ;
2010-05-29 07:25:38 +00:00
if ( m_QueuedWeapon ! = - 1 )
WantedWeapon = m_QueuedWeapon ;
2011-04-09 06:41:31 +00:00
2011-02-13 05:35:13 +00:00
bool Anything = false ;
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < NUM_WEAPONS - 1 ; + + i )
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ i ] . m_Got )
2020-09-26 19:41:58 +00:00
Anything = true ;
if ( ! Anything )
return ;
2010-05-29 07:25:38 +00:00
// select Weapon
int Next = CountInput ( m_LatestPrevInput . m_NextWeapon , m_LatestInput . m_NextWeapon ) . m_Presses ;
int Prev = CountInput ( m_LatestPrevInput . m_PrevWeapon , m_LatestInput . m_PrevWeapon ) . m_Presses ;
2008-07-06 11:21:21 +00:00
2010-05-29 07:25:38 +00:00
if ( Next < 128 ) // make sure we only try sane stuff
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
while ( Next ) // Next Weapon selection
2008-07-06 11:21:21 +00:00
{
2020-09-26 19:41:58 +00:00
WantedWeapon = ( WantedWeapon + 1 ) % NUM_WEAPONS ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ WantedWeapon ] . m_Got )
2010-05-29 07:25:38 +00:00
Next - - ;
2008-07-06 11:21:21 +00:00
}
}
2010-05-29 07:25:38 +00:00
if ( Prev < 128 ) // make sure we only try sane stuff
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
while ( Prev ) // Prev Weapon selection
2008-07-06 11:21:21 +00:00
{
2020-09-26 19:41:58 +00:00
WantedWeapon = ( WantedWeapon - 1 ) < 0 ? NUM_WEAPONS - 1 : WantedWeapon - 1 ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ WantedWeapon ] . m_Got )
2010-05-29 07:25:38 +00:00
Prev - - ;
2008-07-06 11:21:21 +00:00
}
}
2010-05-29 07:25:38 +00:00
// Direct Weapon selection
if ( m_LatestInput . m_WantedWeapon )
2020-09-26 19:41:58 +00:00
WantedWeapon = m_Input . m_WantedWeapon - 1 ;
2008-07-06 11:21:21 +00:00
// check for insane values
2022-03-21 22:50:41 +00:00
if ( WantedWeapon > = 0 & & WantedWeapon < NUM_WEAPONS & & WantedWeapon ! = m_Core . m_ActiveWeapon & & m_Core . m_aWeapons [ WantedWeapon ] . m_Got )
2010-05-29 07:25:38 +00:00
m_QueuedWeapon = WantedWeapon ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
DoWeaponSwitch ( ) ;
2008-07-06 11:21:21 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacter : : FireWeapon ( )
2008-07-06 11:21:21 +00:00
{
2011-01-29 00:59:50 +00:00
if ( m_ReloadTimer ! = 0 )
2020-03-11 00:58:50 +00:00
{
2020-09-26 19:41:58 +00:00
if ( m_LatestInput . m_Fire & 1 )
2020-03-11 00:58:50 +00:00
{
Antibot ( ) - > OnHammerFireReloading ( m_pPlayer - > GetCID ( ) ) ;
}
2008-07-06 11:21:21 +00:00
return ;
2020-03-11 00:58:50 +00:00
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
DoWeaponSwitch ( ) ;
2023-05-04 21:34:57 +00:00
vec2 MouseTarget = vec2 ( m_LatestInput . m_TargetX , m_LatestInput . m_TargetY ) ;
vec2 Direction = normalize ( MouseTarget ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
bool FullAuto = false ;
2019-11-22 14:37:18 +00:00
if ( m_Core . m_ActiveWeapon = = WEAPON_GRENADE | | m_Core . m_ActiveWeapon = = WEAPON_SHOTGUN | | m_Core . m_ActiveWeapon = = WEAPON_LASER )
2010-05-29 07:25:38 +00:00
FullAuto = true ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Jetpack & & m_Core . m_ActiveWeapon = = WEAPON_GUN )
2013-11-13 12:25:26 +00:00
FullAuto = true ;
2019-07-31 19:08:36 +00:00
// allow firing directly after coming out of freeze or being unfrozen
// by something
if ( m_FrozenLastTick )
2013-11-13 12:25:26 +00:00
FullAuto = true ;
2008-07-06 11:21:21 +00:00
2019-10-15 13:13:23 +00:00
// don't fire hammer when player is deep and sv_deepfly is disabled
2022-06-30 17:29:58 +00:00
if ( ! g_Config . m_SvDeepfly & & m_Core . m_ActiveWeapon = = WEAPON_HAMMER & & m_Core . m_DeepFrozen )
2016-05-02 14:25:34 +00:00
return ;
2008-07-06 11:21:21 +00:00
// check if we gonna fire
2010-05-29 07:25:38 +00:00
bool WillFire = false ;
if ( CountInput ( m_LatestPrevInput . m_Fire , m_LatestInput . m_Fire ) . m_Presses )
WillFire = true ;
2011-04-13 18:37:12 +00:00
2022-03-21 22:50:41 +00:00
if ( FullAuto & & ( m_LatestInput . m_Fire & 1 ) & & m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_Ammo )
2010-05-29 07:25:38 +00:00
WillFire = true ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( ! WillFire )
2008-07-06 11:21:21 +00:00
return ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
if ( m_FreezeTime )
2008-07-06 11:21:21 +00:00
{
2011-04-09 06:41:31 +00:00
// Timer stuff to avoid shrieking orchestra caused by unfreeze-plasma
2020-09-26 19:41:58 +00:00
if ( m_PainSoundTimer < = 0 & & ! ( m_LatestPrevInput . m_Fire & 1 ) )
2010-11-04 23:52:37 +00:00
{
2019-07-31 19:08:16 +00:00
m_PainSoundTimer = 1 * Server ( ) - > TickSpeed ( ) ;
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_PLAYER_PAIN_LONG , TeamMask ( ) ) ;
2010-11-04 23:52:37 +00:00
}
2008-07-06 11:21:21 +00:00
return ;
}
2014-11-02 09:59:22 +00:00
2008-07-06 11:21:21 +00:00
// check for ammo
2022-03-21 22:50:41 +00:00
if ( ! m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_Ammo )
2008-07-06 11:21:21 +00:00
return ;
2014-11-02 09:59:22 +00:00
2021-01-09 20:40:03 +00:00
vec2 ProjStartPos = m_Pos + Direction * GetProximityRadius ( ) * 0.75f ;
2011-04-13 18:37:12 +00:00
2014-04-14 08:56:14 +00:00
switch ( m_Core . m_ActiveWeapon )
2008-07-06 11:21:21 +00:00
{
2020-09-26 19:41:58 +00:00
case WEAPON_HAMMER :
{
// reset objects Hit
m_NumObjectsHit = 0 ;
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_HAMMER_FIRE , TeamMask ( ) ) ;
2010-08-24 14:32:46 +00:00
2020-09-26 19:41:58 +00:00
Antibot ( ) - > OnHammerFire ( m_pPlayer - > GetCID ( ) ) ;
2020-03-11 00:58:50 +00:00
2022-07-08 13:31:58 +00:00
if ( m_Core . m_HammerHitDisabled )
2020-09-26 19:41:58 +00:00
break ;
2011-04-13 18:37:12 +00:00
2022-11-09 22:07:15 +00:00
CEntity * apEnts [ MAX_CLIENTS ] ;
2020-09-26 19:41:58 +00:00
int Hits = 0 ;
2022-11-09 22:07:15 +00:00
int Num = GameServer ( ) - > m_World . FindEntities ( ProjStartPos , GetProximityRadius ( ) * 0.5f , apEnts ,
2020-09-26 19:41:58 +00:00
MAX_CLIENTS , CGameWorld : : ENTTYPE_CHARACTER ) ;
2008-07-06 11:21:21 +00:00
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < Num ; + + i )
{
2022-11-09 22:07:15 +00:00
auto * pTarget = static_cast < CCharacter * > ( apEnts [ i ] ) ;
2011-04-13 18:37:12 +00:00
2022-05-28 18:24:24 +00:00
//if ((pTarget == this) || Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL))
2020-09-26 19:41:58 +00:00
if ( ( pTarget = = this | | ( pTarget - > IsAlive ( ) & & ! CanCollide ( pTarget - > GetPlayer ( ) - > GetCID ( ) ) ) ) )
continue ;
2008-07-06 11:21:21 +00:00
2020-09-26 19:41:58 +00:00
// set his velocity to fast upward (for now)
if ( length ( pTarget - > m_Pos - ProjStartPos ) > 0.0f )
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateHammerHit ( pTarget - > m_Pos - normalize ( pTarget - > m_Pos - ProjStartPos ) * GetProximityRadius ( ) * 0.5f , TeamMask ( ) ) ;
2020-09-26 19:41:58 +00:00
else
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateHammerHit ( ProjStartPos , TeamMask ( ) ) ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
vec2 Dir ;
if ( length ( pTarget - > m_Pos - m_Pos ) > 0.0f )
Dir = normalize ( pTarget - > m_Pos - m_Pos ) ;
else
Dir = vec2 ( 0.f , - 1.f ) ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
float Strength ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
Strength = Tuning ( ) - > m_HammerStrength ;
2020-09-26 19:41:58 +00:00
else
2023-09-05 23:08:01 +00:00
Strength = TuningList ( ) [ m_TuneZone ] . m_HammerStrength ;
2014-07-16 00:59:39 +00:00
2020-09-26 19:41:58 +00:00
vec2 Temp = pTarget - > m_Core . m_Vel + normalize ( Dir + vec2 ( 0.f , - 1.1f ) ) * 10.0f ;
Temp = ClampVel ( pTarget - > m_MoveRestrictions , Temp ) ;
Temp - = pTarget - > m_Core . m_Vel ;
pTarget - > TakeDamage ( ( vec2 ( 0.f , - 1.0f ) + Temp ) * Strength , g_pData - > m_Weapons . m_Hammer . m_pBase - > m_Damage ,
m_pPlayer - > GetCID ( ) , m_Core . m_ActiveWeapon ) ;
pTarget - > UnFreeze ( ) ;
2014-07-16 00:59:39 +00:00
2020-09-26 19:41:58 +00:00
if ( m_FreezeHammer )
pTarget - > Freeze ( ) ;
2020-03-11 00:58:50 +00:00
2021-07-21 20:28:59 +00:00
Antibot ( ) - > OnHammerHit ( m_pPlayer - > GetCID ( ) , pTarget - > GetPlayer ( ) - > GetCID ( ) ) ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
Hits + + ;
}
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
// if we Hit anything, we have to wait for the reload
if ( Hits )
2021-04-25 09:29:07 +00:00
{
float FireDelay ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
FireDelay = Tuning ( ) - > m_HammerHitFireDelay ;
2021-04-25 09:29:07 +00:00
else
2023-09-05 23:08:01 +00:00
FireDelay = TuningList ( ) [ m_TuneZone ] . m_HammerHitFireDelay ;
2021-04-25 09:29:07 +00:00
m_ReloadTimer = FireDelay * Server ( ) - > TickSpeed ( ) / 1000 ;
}
2020-09-26 19:41:58 +00:00
}
break ;
2008-07-06 11:21:21 +00:00
2020-09-26 19:41:58 +00:00
case WEAPON_GUN :
{
2022-06-30 17:29:58 +00:00
if ( ! m_Core . m_Jetpack | | ! m_pPlayer - > m_NinjaJetpack | | m_Core . m_HasTelegunGun )
2008-07-06 11:21:21 +00:00
{
2020-09-26 19:41:58 +00:00
int Lifetime ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
Lifetime = ( int ) ( Server ( ) - > TickSpeed ( ) * Tuning ( ) - > m_GunLifetime ) ;
2020-09-26 19:41:58 +00:00
else
2023-09-05 23:08:01 +00:00
Lifetime = ( int ) ( Server ( ) - > TickSpeed ( ) * TuningList ( ) [ m_TuneZone ] . m_GunLifetime ) ;
2020-09-26 19:41:58 +00:00
2020-12-06 18:58:04 +00:00
new CProjectile (
2020-09-26 19:41:58 +00:00
GameWorld ( ) ,
WEAPON_GUN , //Type
m_pPlayer - > GetCID ( ) , //Owner
ProjStartPos , //Pos
Direction , //Dir
Lifetime , //Span
2022-02-14 23:12:52 +00:00
false , //Freeze
false , //Explosive
2023-05-04 21:34:57 +00:00
- 1 , //SoundImpact
MouseTarget //InitDir
2020-09-26 19:41:58 +00:00
) ;
2014-01-09 18:00:41 +00:00
2023-01-05 13:19:14 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_GUN_FIRE , TeamMask ( ) ) ; // NOLINT(clang-analyzer-unix.Malloc)
2020-09-26 19:41:58 +00:00
}
}
break ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
case WEAPON_SHOTGUN :
{
float LaserReach ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
LaserReach = Tuning ( ) - > m_LaserReach ;
2020-09-26 19:41:58 +00:00
else
2023-09-05 23:08:01 +00:00
LaserReach = TuningList ( ) [ m_TuneZone ] . m_LaserReach ;
2011-04-09 06:41:31 +00:00
2020-09-26 19:41:58 +00:00
new CLaser ( & GameServer ( ) - > m_World , m_Pos , Direction , LaserReach , m_pPlayer - > GetCID ( ) , WEAPON_SHOTGUN ) ;
2023-01-05 13:19:14 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_SHOTGUN_FIRE , TeamMask ( ) ) ; // NOLINT(clang-analyzer-unix.Malloc)
2020-09-26 19:41:58 +00:00
}
break ;
2015-07-09 00:08:14 +00:00
2020-09-26 19:41:58 +00:00
case WEAPON_GRENADE :
{
int Lifetime ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
Lifetime = ( int ) ( Server ( ) - > TickSpeed ( ) * Tuning ( ) - > m_GrenadeLifetime ) ;
2020-09-26 19:41:58 +00:00
else
2023-09-05 23:08:01 +00:00
Lifetime = ( int ) ( Server ( ) - > TickSpeed ( ) * TuningList ( ) [ m_TuneZone ] . m_GrenadeLifetime ) ;
2020-09-26 19:41:58 +00:00
2020-12-06 18:58:04 +00:00
new CProjectile (
2020-09-26 19:41:58 +00:00
GameWorld ( ) ,
WEAPON_GRENADE , //Type
m_pPlayer - > GetCID ( ) , //Owner
ProjStartPos , //Pos
Direction , //Dir
Lifetime , //Span
2022-02-14 23:12:52 +00:00
false , //Freeze
2020-09-26 19:41:58 +00:00
true , //Explosive
2023-05-04 21:34:57 +00:00
SOUND_GRENADE_EXPLODE , //SoundImpact
MouseTarget // MouseTarget
) ;
2020-09-26 19:41:58 +00:00
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_GRENADE_FIRE , TeamMask ( ) ) ;
2020-09-26 19:41:58 +00:00
}
break ;
case WEAPON_LASER :
{
float LaserReach ;
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
LaserReach = Tuning ( ) - > m_LaserReach ;
2020-09-26 19:41:58 +00:00
else
2023-09-05 23:08:01 +00:00
LaserReach = TuningList ( ) [ m_TuneZone ] . m_LaserReach ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
new CLaser ( GameWorld ( ) , m_Pos , Direction , LaserReach , m_pPlayer - > GetCID ( ) , WEAPON_LASER ) ;
2023-01-05 13:19:14 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_LASER_FIRE , TeamMask ( ) ) ; // NOLINT(clang-analyzer-unix.Malloc)
2020-09-26 19:41:58 +00:00
}
break ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
case WEAPON_NINJA :
{
// reset Hit objects
m_NumObjectsHit = 0 ;
2010-08-24 14:32:46 +00:00
2022-03-24 00:05:41 +00:00
m_Core . m_Ninja . m_ActivationDir = Direction ;
m_Core . m_Ninja . m_CurrentMoveTime = g_pData - > m_Weapons . m_Ninja . m_Movetime * Server ( ) - > TickSpeed ( ) / 1000 ;
m_Core . m_Ninja . m_OldVelAmount = length ( m_Core . m_Vel ) ;
2011-04-13 18:37:12 +00:00
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_NINJA_FIRE , TeamMask ( ) ) ;
2020-09-26 19:41:58 +00:00
}
break ;
2008-07-06 11:21:21 +00:00
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
m_AttackTick = Server ( ) - > Tick ( ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( ! m_ReloadTimer )
2015-02-12 14:20:22 +00:00
{
float FireDelay ;
2020-09-26 19:41:58 +00:00
if ( ! m_TuneZone )
2023-09-05 23:08:01 +00:00
Tuning ( ) - > Get ( 38 + m_Core . m_ActiveWeapon , & FireDelay ) ;
2015-02-12 14:20:22 +00:00
else
2023-09-05 23:08:01 +00:00
TuningList ( ) [ m_TuneZone ] . Get ( 38 + m_Core . m_ActiveWeapon , & FireDelay ) ;
2015-02-12 14:20:22 +00:00
m_ReloadTimer = FireDelay * Server ( ) - > TickSpeed ( ) / 1000 ;
}
2008-07-06 11:21:21 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacter : : HandleWeapons ( )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
//ninja
HandleNinja ( ) ;
2014-04-13 23:34:50 +00:00
HandleJetpack ( ) ;
2011-04-13 18:37:12 +00:00
2011-01-29 00:59:50 +00:00
if ( m_PainSoundTimer > 0 )
2010-11-04 23:52:37 +00:00
m_PainSoundTimer - - ;
2008-10-08 18:36:30 +00:00
2008-07-06 11:21:21 +00:00
// check reload timer
2010-05-29 07:25:38 +00:00
if ( m_ReloadTimer )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
m_ReloadTimer - - ;
return ;
2008-07-06 11:21:21 +00:00
}
2010-05-29 07:25:38 +00:00
// fire Weapon, if wanted
2014-11-02 09:59:22 +00:00
FireWeapon ( ) ;
2010-05-29 07:25:38 +00:00
}
void CCharacter : : GiveNinja ( )
{
2022-03-24 00:05:41 +00:00
m_Core . m_Ninja . m_ActivationTick = Server ( ) - > Tick ( ) ;
2022-03-21 22:50:41 +00:00
m_Core . m_aWeapons [ WEAPON_NINJA ] . m_Got = true ;
m_Core . m_aWeapons [ WEAPON_NINJA ] . m_Ammo = - 1 ;
2020-09-26 19:41:58 +00:00
if ( m_Core . m_ActiveWeapon ! = WEAPON_NINJA )
2014-04-14 08:56:14 +00:00
m_LastWeapon = m_Core . m_ActiveWeapon ;
m_Core . m_ActiveWeapon = WEAPON_NINJA ;
2011-04-13 18:37:12 +00:00
2022-03-21 22:50:41 +00:00
if ( ! m_Core . m_aWeapons [ WEAPON_NINJA ] . m_Got )
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_PICKUP_NINJA , TeamMask ( ) ) ;
2008-07-06 11:21:21 +00:00
}
2016-10-08 17:42:42 +00:00
void CCharacter : : RemoveNinja ( )
{
2023-10-09 09:11:55 +00:00
m_Core . m_Ninja . m_ActivationDir = vec2 ( 0 , 0 ) ;
m_Core . m_Ninja . m_ActivationTick = 0 ;
2022-03-24 00:05:41 +00:00
m_Core . m_Ninja . m_CurrentMoveTime = 0 ;
2023-10-09 09:11:55 +00:00
m_Core . m_Ninja . m_OldVelAmount = 0 ;
2022-03-21 22:50:41 +00:00
m_Core . m_aWeapons [ WEAPON_NINJA ] . m_Got = false ;
2023-10-09 09:11:55 +00:00
m_Core . m_aWeapons [ WEAPON_NINJA ] . m_Ammo = 0 ;
2016-10-08 17:42:42 +00:00
m_Core . m_ActiveWeapon = m_LastWeapon ;
2017-02-21 16:10:08 +00:00
2020-09-26 19:41:58 +00:00
SetWeapon ( m_Core . m_ActiveWeapon ) ;
2016-10-08 17:42:42 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacter : : SetEmote ( int Emote , int Tick )
{
m_EmoteType = Emote ;
m_EmoteStop = Tick ;
}
void CCharacter : : OnPredictedInput ( CNetObj_PlayerInput * pNewInput )
2008-07-06 11:21:21 +00:00
{
// check for changes
2016-08-27 15:06:52 +00:00
if ( mem_comp ( & m_SavedInput , pNewInput , sizeof ( CNetObj_PlayerInput ) ) ! = 0 )
2010-05-29 07:25:38 +00:00
m_LastAction = Server ( ) - > Tick ( ) ;
2011-04-13 18:37:12 +00:00
2008-07-06 11:21:21 +00:00
// copy new input
2010-05-29 07:25:38 +00:00
mem_copy ( & m_Input , pNewInput , sizeof ( m_Input ) ) ;
2011-04-13 18:37:12 +00:00
2011-12-10 17:21:12 +00:00
// it is not allowed to aim in the center
2010-05-29 07:25:38 +00:00
if ( m_Input . m_TargetX = = 0 & & m_Input . m_TargetY = = 0 )
2011-04-13 18:37:12 +00:00
m_Input . m_TargetY = - 1 ;
2017-08-25 11:20:10 +00:00
2017-08-25 11:27:37 +00:00
mem_copy ( & m_SavedInput , & m_Input , sizeof ( m_SavedInput ) ) ;
2008-07-06 11:21:21 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacter : : OnDirectInput ( CNetObj_PlayerInput * pNewInput )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
mem_copy ( & m_LatestPrevInput , & m_LatestInput , sizeof ( m_LatestInput ) ) ;
mem_copy ( & m_LatestInput , pNewInput , sizeof ( m_LatestInput ) ) ;
2022-04-28 13:59:20 +00:00
m_NumInputs + + ;
2011-04-13 18:37:12 +00:00
2011-12-10 17:21:12 +00:00
// it is not allowed to aim in the center
if ( m_LatestInput . m_TargetX = = 0 & & m_LatestInput . m_TargetY = = 0 )
m_LatestInput . m_TargetY = - 1 ;
2020-03-11 00:58:50 +00:00
Antibot ( ) - > OnDirectInput ( m_pPlayer - > GetCID ( ) ) ;
2022-04-28 13:34:25 +00:00
if ( m_NumInputs > 1 & & m_pPlayer - > GetTeam ( ) ! = TEAM_SPECTATORS )
2008-07-06 11:21:21 +00:00
{
2010-05-29 07:25:38 +00:00
HandleWeaponSwitch ( ) ;
FireWeapon ( ) ;
2008-07-06 11:21:21 +00:00
}
2011-04-13 18:37:12 +00:00
2020-03-11 00:58:50 +00:00
mem_copy ( & m_LatestPrevPrevInput , & m_LatestPrevInput , sizeof ( m_LatestInput ) ) ;
2010-05-29 07:25:38 +00:00
mem_copy ( & m_LatestPrevInput , & m_LatestInput , sizeof ( m_LatestInput ) ) ;
2008-07-06 11:21:21 +00:00
}
2021-04-08 14:36:43 +00:00
void CCharacter : : ResetHook ( )
{
2022-05-22 19:40:15 +00:00
m_Core . SetHookedPlayer ( - 1 ) ;
2021-04-08 14:36:43 +00:00
m_Core . m_HookState = HOOK_RETRACTED ;
m_Core . m_TriggeredEvents | = COREEVENT_HOOK_RETRACT ;
m_Core . m_HookPos = m_Core . m_Pos ;
}
2011-06-09 20:30:03 +00:00
void CCharacter : : ResetInput ( )
{
2014-02-18 21:26:17 +00:00
m_Input . m_Direction = 0 ;
2011-06-09 20:30:03 +00:00
// simulate releasing the fire button
2020-09-26 19:41:58 +00:00
if ( ( m_Input . m_Fire & 1 ) ! = 0 )
2014-02-18 21:26:17 +00:00
m_Input . m_Fire + + ;
m_Input . m_Fire & = INPUT_STATE_MASK ;
m_Input . m_Jump = 0 ;
2011-06-09 20:30:03 +00:00
m_LatestPrevInput = m_LatestInput = m_Input ;
}
2022-07-19 16:34:49 +00:00
void CCharacter : : PreTick ( )
2010-09-17 11:26:06 +00:00
{
2022-05-30 14:04:15 +00:00
if ( m_StartTime > Server ( ) - > Tick ( ) )
{
// Prevent the player from getting a negative time
// The main reason why this can happen is because of time penalty tiles
// However, other reasons are hereby also excluded
GameServer ( ) - > SendChatTarget ( m_pPlayer - > GetCID ( ) , " You died of old age " ) ;
Die ( m_pPlayer - > GetCID ( ) , WEAPON_WORLD ) ;
}
2019-07-31 19:08:16 +00:00
if ( m_Paused )
2011-12-29 13:58:39 +00:00
return ;
2020-06-12 19:22:54 +00:00
// set emote
if ( m_EmoteStop < Server ( ) - > Tick ( ) )
{
2021-01-12 19:15:10 +00:00
m_EmoteType = m_pPlayer - > GetDefaultEmote ( ) ;
2020-06-12 19:22:54 +00:00
m_EmoteStop = - 1 ;
}
2011-01-29 00:59:50 +00:00
DDRaceTick ( ) ;
2015-07-09 00:08:14 +00:00
2020-05-15 16:29:34 +00:00
Antibot ( ) - > OnCharacterTick ( m_pPlayer - > GetCID ( ) ) ;
2020-03-11 00:58:50 +00:00
2011-01-29 00:59:50 +00:00
m_Core . m_Input = m_Input ;
2022-10-27 15:50:08 +00:00
m_Core . Tick ( true , ! g_Config . m_SvNoWeakHook ) ;
2022-07-19 16:34:49 +00:00
}
void CCharacter : : Tick ( )
{
2022-10-27 15:50:08 +00:00
if ( g_Config . m_SvNoWeakHook )
2022-07-19 16:34:49 +00:00
{
if ( m_Paused )
return ;
m_Core . TickDeferred ( ) ;
}
else
{
PreTick ( ) ;
}
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
if ( ! m_PrevInput . m_Hook & & m_Input . m_Hook & & ! ( m_Core . m_TriggeredEvents & COREEVENT_HOOK_ATTACH_PLAYER ) )
2020-03-11 00:58:50 +00:00
{
Antibot ( ) - > OnHookAttach ( m_pPlayer - > GetCID ( ) , false ) ;
}
2011-01-29 00:59:50 +00:00
// handle Weapons
HandleWeapons ( ) ;
2010-08-28 20:53:42 +00:00
2011-01-29 23:58:47 +00:00
DDRacePostCoreTick ( ) ;
2010-08-28 20:53:42 +00:00
2020-09-26 19:41:58 +00:00
if ( m_Core . m_TriggeredEvents & COREEVENT_HOOK_ATTACH_PLAYER )
2020-03-11 00:58:50 +00:00
{
2023-09-05 21:53:03 +00:00
const int HookedPlayer = m_Core . HookedPlayer ( ) ;
if ( HookedPlayer ! = - 1 & & GameServer ( ) - > m_apPlayers [ HookedPlayer ] - > GetTeam ( ) ! = TEAM_SPECTATORS )
2020-03-11 00:58:50 +00:00
{
Antibot ( ) - > OnHookAttach ( m_pPlayer - > GetCID ( ) , true ) ;
}
}
2011-01-29 00:59:50 +00:00
// Previnput
m_PrevInput = m_Input ;
2011-04-09 06:41:31 +00:00
2011-01-29 00:59:50 +00:00
m_PrevPos = m_Core . m_Pos ;
}
2010-08-28 20:53:42 +00:00
2022-07-19 16:22:44 +00:00
void CCharacter : : TickDeferred ( )
2011-01-29 00:59:50 +00:00
{
// advance the dummy
{
2023-11-22 17:34:39 +00:00
CWorldCore TempWorld ;
m_ReckoningCore . Init ( & TempWorld , Collision ( ) , & Teams ( ) - > m_Core , m_pTeleOuts ) ;
m_ReckoningCore . m_Id = m_pPlayer - > GetCID ( ) ;
2019-04-11 22:46:54 +00:00
m_ReckoningCore . Tick ( false ) ;
2018-08-22 06:33:21 +00:00
m_ReckoningCore . Move ( ) ;
2011-01-29 00:59:50 +00:00
m_ReckoningCore . Quantize ( ) ;
}
2011-04-13 18:37:12 +00:00
2011-01-29 00:59:50 +00:00
//lastsentcore
vec2 StartPos = m_Core . m_Pos ;
vec2 StartVel = m_Core . m_Vel ;
2022-05-28 17:28:44 +00:00
bool StuckBefore = Collision ( ) - > TestBox ( m_Core . m_Pos , CCharacterCore : : PhysicalSizeVec2 ( ) ) ;
2011-04-13 18:37:12 +00:00
2011-09-01 18:29:08 +00:00
m_Core . m_Id = m_pPlayer - > GetCID ( ) ;
2018-08-22 06:33:21 +00:00
m_Core . Move ( ) ;
2022-05-28 17:28:44 +00:00
bool StuckAfterMove = Collision ( ) - > TestBox ( m_Core . m_Pos , CCharacterCore : : PhysicalSizeVec2 ( ) ) ;
2011-01-29 00:59:50 +00:00
m_Core . Quantize ( ) ;
2022-05-28 17:28:44 +00:00
bool StuckAfterQuant = Collision ( ) - > TestBox ( m_Core . m_Pos , CCharacterCore : : PhysicalSizeVec2 ( ) ) ;
2011-01-29 00:59:50 +00:00
m_Pos = m_Core . m_Pos ;
2011-04-13 18:37:12 +00:00
2011-01-29 00:59:50 +00:00
if ( ! StuckBefore & & ( StuckAfterMove | | StuckAfterQuant ) )
{
// Hackish solution to get rid of strict-aliasing warning
union
2010-08-28 20:53:42 +00:00
{
2011-01-29 00:59:50 +00:00
float f ;
unsigned u ;
2020-09-26 19:41:58 +00:00
} StartPosX , StartPosY , StartVelX , StartVelY ;
2011-01-29 00:59:50 +00:00
StartPosX . f = StartPos . x ;
StartPosY . f = StartPos . y ;
StartVelX . f = StartVel . x ;
StartVelY . f = StartVel . y ;
char aBuf [ 256 ] ;
2011-04-13 18:37:12 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " STUCK!!! %d %d %d %f %f %f %f %x %x %x %x " ,
2011-01-29 00:59:50 +00:00
StuckBefore ,
StuckAfterMove ,
StuckAfterQuant ,
StartPos . x , StartPos . y ,
StartVel . x , StartVel . y ,
StartPosX . u , StartPosY . u ,
StartVelX . u , StartVelY . u ) ;
GameServer ( ) - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " game " , aBuf ) ;
}
2020-07-18 17:39:24 +00:00
{
int Events = m_Core . m_TriggeredEvents ;
int CID = m_pPlayer - > GetCID ( ) ;
2023-01-24 08:27:29 +00:00
CClientMask TeamMask = Teams ( ) - > TeamMask ( Team ( ) , - 1 , CID ) ;
2020-07-18 17:39:24 +00:00
// Some sounds are triggered client-side for the acting player
// so we need to avoid duplicating them
2023-01-24 08:27:29 +00:00
CClientMask TeamMaskExceptSelf = Teams ( ) - > TeamMask ( Team ( ) , CID , CID ) ;
2020-07-18 17:39:24 +00:00
// Some are triggered client-side but only on Sixup
2023-01-24 08:27:29 +00:00
CClientMask TeamMaskExceptSelfIfSixup = Server ( ) - > IsSixup ( CID ) ? TeamMaskExceptSelf : TeamMask ;
2020-07-18 17:39:24 +00:00
2020-09-26 19:41:58 +00:00
if ( Events & COREEVENT_GROUND_JUMP )
2020-07-18 17:39:24 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_PLAYER_JUMP , TeamMaskExceptSelf ) ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
if ( Events & COREEVENT_HOOK_ATTACH_PLAYER )
2020-07-18 17:39:24 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_HOOK_ATTACH_PLAYER , TeamMaskExceptSelfIfSixup ) ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
if ( Events & COREEVENT_HOOK_ATTACH_GROUND )
2020-07-18 17:39:24 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_HOOK_ATTACH_GROUND , TeamMaskExceptSelf ) ;
2020-09-26 19:41:58 +00:00
if ( Events & COREEVENT_HOOK_HIT_NOHOOK )
2020-07-18 17:39:24 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_HOOK_NOATTACH , TeamMaskExceptSelf ) ;
}
2011-01-29 00:59:50 +00:00
if ( m_pPlayer - > GetTeam ( ) = = TEAM_SPECTATORS )
{
m_Pos . x = m_Input . m_TargetX ;
m_Pos . y = m_Input . m_TargetY ;
}
2011-04-13 18:37:12 +00:00
2011-01-29 00:59:50 +00:00
// update the m_SendCore if needed
{
CNetObj_Character Predicted ;
CNetObj_Character Current ;
mem_zero ( & Predicted , sizeof ( Predicted ) ) ;
mem_zero ( & Current , sizeof ( Current ) ) ;
m_ReckoningCore . Write ( & Predicted ) ;
m_Core . Write ( & Current ) ;
// only allow dead reackoning for a top of 3 seconds
2022-06-30 22:36:32 +00:00
if ( m_Core . m_Reset | | m_ReckoningTick + Server ( ) - > TickSpeed ( ) * 3 < Server ( ) - > Tick ( ) | | mem_comp ( & Predicted , & Current , sizeof ( CNetObj_Character ) ) ! = 0 )
2011-01-29 00:59:50 +00:00
{
m_ReckoningTick = Server ( ) - > Tick ( ) ;
m_SendCore = m_Core ;
m_ReckoningCore = m_Core ;
2022-06-30 22:36:32 +00:00
m_Core . m_Reset = false ;
2011-01-29 00:59:50 +00:00
}
}
}
2012-01-09 23:49:31 +00:00
void CCharacter : : TickPaused ( )
{
+ + m_AttackTick ;
+ + m_DamageTakenTick ;
2022-03-24 00:05:41 +00:00
+ + m_Core . m_Ninja . m_ActivationTick ;
2012-01-09 23:49:31 +00:00
+ + m_ReckoningTick ;
if ( m_LastAction ! = - 1 )
+ + m_LastAction ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_AmmoRegenStart > - 1 )
+ + m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_AmmoRegenStart ;
2012-01-09 23:49:31 +00:00
if ( m_EmoteStop > - 1 )
+ + m_EmoteStop ;
}
2011-01-29 00:59:50 +00:00
bool CCharacter : : IncreaseHealth ( int Amount )
{
if ( m_Health > = 10 )
return false ;
2020-09-26 19:41:58 +00:00
m_Health = clamp ( m_Health + Amount , 0 , 10 ) ;
2011-01-29 00:59:50 +00:00
return true ;
}
bool CCharacter : : IncreaseArmor ( int Amount )
{
if ( m_Armor > = 10 )
return false ;
2020-09-26 19:41:58 +00:00
m_Armor = clamp ( m_Armor + Amount , 0 , 10 ) ;
2011-01-29 00:59:50 +00:00
return true ;
}
2023-04-03 01:06:32 +00:00
void CCharacter : : Die ( int Killer , int Weapon , bool SendKillMsg )
2011-01-29 00:59:50 +00:00
{
2014-09-26 00:25:53 +00:00
if ( Server ( ) - > IsRecording ( m_pPlayer - > GetCID ( ) ) )
2023-10-30 02:32:50 +00:00
{
CPlayerData * pData = GameServer ( ) - > Score ( ) - > PlayerData ( m_pPlayer - > GetCID ( ) ) ;
if ( pData - > m_RecordStopTick - Server ( ) - > Tick ( ) < = Server ( ) - > TickSpeed ( ) & & pData - > m_RecordStopTick ! = - 1 )
Server ( ) - > SaveDemo ( m_pPlayer - > GetCID ( ) , pData - > m_RecordFinishTime ) ;
else
Server ( ) - > StopRecord ( m_pPlayer - > GetCID ( ) ) ;
pData - > m_RecordStopTick = - 1 ;
}
2014-09-26 00:25:53 +00:00
2011-01-29 00:59:50 +00:00
int ModeSpecial = GameServer ( ) - > m_pController - > OnCharacterDeath ( this , GameServer ( ) - > m_apPlayers [ Killer ] , Weapon ) ;
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d " ,
Killer , Server ( ) - > ClientName ( Killer ) ,
m_pPlayer - > GetCID ( ) , Server ( ) - > ClientName ( m_pPlayer - > GetCID ( ) ) , Weapon , ModeSpecial ) ;
GameServer ( ) - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " game " , aBuf ) ;
// send the kill message
2023-07-13 15:39:07 +00:00
if ( SendKillMsg & & ( Team ( ) = = TEAM_FLOCK | | Teams ( ) - > Count ( Team ( ) ) = = 1 | | Teams ( ) - > GetTeamState ( Team ( ) ) = = CGameTeams : : TEAMSTATE_OPEN | | Teams ( ) - > TeamLocked ( Team ( ) ) = = false ) )
2023-03-17 21:53:10 +00:00
{
2023-04-03 01:06:32 +00:00
CNetMsg_Sv_KillMsg Msg ;
Msg . m_Killer = Killer ;
Msg . m_Victim = m_pPlayer - > GetCID ( ) ;
Msg . m_Weapon = Weapon ;
Msg . m_ModeSpecial = ModeSpecial ;
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , - 1 ) ;
2023-03-17 21:53:10 +00:00
}
2011-01-29 00:59:50 +00:00
// a nice sound
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateSound ( m_Pos , SOUND_PLAYER_DIE , TeamMask ( ) ) ;
2011-04-13 18:37:12 +00:00
2019-06-07 09:44:19 +00:00
// this is to rate limit respawning to 3 secs
m_pPlayer - > m_PreviousDieTick = m_pPlayer - > m_DieTick ;
2011-01-29 00:59:50 +00:00
m_pPlayer - > m_DieTick = Server ( ) - > Tick ( ) ;
2011-04-13 18:37:12 +00:00
2011-01-29 00:59:50 +00:00
m_Alive = false ;
2022-06-30 17:29:58 +00:00
SetSolo ( false ) ;
2019-04-12 14:16:21 +00:00
2010-05-29 07:25:38 +00:00
GameServer ( ) - > m_World . RemoveEntity ( this ) ;
2011-01-29 00:59:50 +00:00
GameServer ( ) - > m_World . m_Core . m_apCharacters [ m_pPlayer - > GetCID ( ) ] = 0 ;
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateDeath ( m_Pos , m_pPlayer - > GetCID ( ) , TeamMask ( ) ) ;
2014-04-12 10:08:20 +00:00
Teams ( ) - > OnCharacterDeath ( GetPlayer ( ) - > GetCID ( ) , Weapon ) ;
2011-01-29 00:59:50 +00:00
}
bool CCharacter : : TakeDamage ( vec2 Force , int Dmg , int From , int Weapon )
2008-07-06 11:21:21 +00:00
{
2020-09-26 19:41:58 +00:00
if ( Dmg )
2014-01-09 18:50:37 +00:00
{
m_EmoteType = EMOTE_PAIN ;
m_EmoteStop = Server ( ) - > Tick ( ) + 500 * Server ( ) - > TickSpeed ( ) / 1000 ;
}
2008-07-06 11:21:21 +00:00
2011-01-29 00:59:50 +00:00
vec2 Temp = m_Core . m_Vel + Force ;
2018-08-15 15:47:07 +00:00
m_Core . m_Vel = ClampVel ( m_MoveRestrictions , Temp ) ;
2011-04-09 06:41:31 +00:00
2011-01-29 00:59:50 +00:00
return true ;
}
2020-06-12 19:22:54 +00:00
//TODO: Move the emote stuff to a function
2020-06-22 16:02:17 +00:00
void CCharacter : : SnapCharacter ( int SnappingClient , int ID )
2011-01-29 00:59:50 +00:00
{
2022-07-30 08:57:46 +00:00
int SnappingClientVersion = GameServer ( ) - > GetClientVersion ( SnappingClient ) ;
2020-06-12 19:22:54 +00:00
CCharacterCore * pCore ;
int Tick , Emote = m_EmoteType , Weapon = m_Core . m_ActiveWeapon , AmmoCount = 0 ,
2020-09-26 19:41:58 +00:00
Health = 0 , Armor = 0 ;
2011-01-29 00:59:50 +00:00
if ( ! m_ReckoningTick | | GameServer ( ) - > m_World . m_Paused )
{
2020-06-12 19:22:54 +00:00
Tick = 0 ;
pCore = & m_Core ;
2011-01-29 00:59:50 +00:00
}
else
{
2020-06-12 19:22:54 +00:00
Tick = m_ReckoningTick ;
pCore = & m_SendCore ;
2011-01-29 00:59:50 +00:00
}
2011-04-13 18:37:12 +00:00
2020-06-12 19:22:54 +00:00
// change eyes and use ninja graphic if player is frozen
2023-01-05 19:24:06 +00:00
if ( m_Core . m_DeepFrozen | | m_FreezeTime > 0 | | m_Core . m_LiveFrozen )
2013-12-31 05:13:57 +00:00
{
2020-06-12 19:22:54 +00:00
if ( Emote = = EMOTE_NORMAL )
2022-06-30 17:29:58 +00:00
Emote = ( m_Core . m_DeepFrozen | | m_Core . m_LiveFrozen ) ? EMOTE_PAIN : EMOTE_BLINK ;
2022-01-08 11:30:51 +00:00
2023-01-05 19:24:06 +00:00
if ( ( m_Core . m_DeepFrozen | | m_FreezeTime > 0 ) & & SnappingClientVersion < VERSION_DDNET_NEW_HUD )
2022-01-07 15:53:40 +00:00
Weapon = WEAPON_NINJA ;
2011-01-29 00:59:50 +00:00
}
2022-01-08 11:30:51 +00:00
2023-04-26 20:35:23 +00:00
// solo, collision, jetpack and ninjajetpack prediction
2020-06-12 19:22:54 +00:00
if ( m_pPlayer - > GetCID ( ) = = SnappingClient )
2015-03-14 17:55:50 +00:00
{
2023-04-26 20:35:23 +00:00
int Faketuning = 0 ;
if ( m_pPlayer - > GetClientVersion ( ) < VERSION_DDNET_NEW_HUD )
2015-03-14 17:55:50 +00:00
{
2023-04-26 20:35:23 +00:00
if ( m_Core . m_Jetpack & & Weapon ! = WEAPON_NINJA )
Faketuning | = FAKETUNE_JETPACK ;
if ( m_Core . m_Solo )
Faketuning | = FAKETUNE_SOLO ;
if ( m_Core . m_HammerHitDisabled )
Faketuning | = FAKETUNE_NOHAMMER ;
if ( m_Core . m_CollisionDisabled )
Faketuning | = FAKETUNE_NOCOLL ;
if ( m_Core . m_HookHitDisabled )
Faketuning | = FAKETUNE_NOHOOK ;
if ( ! m_Core . m_EndlessJump & & m_Core . m_Jumps = = 0 )
Faketuning | = FAKETUNE_NOJUMP ;
2015-03-14 17:55:50 +00:00
}
2023-04-26 20:35:23 +00:00
if ( Faketuning ! = m_NeededFaketuning )
2015-03-14 17:55:50 +00:00
{
2023-04-26 20:35:23 +00:00
m_NeededFaketuning = Faketuning ;
GameServer ( ) - > SendTuningParams ( m_pPlayer - > GetCID ( ) , m_TuneZone ) ; // update tunings
2015-03-14 17:55:50 +00:00
}
}
// change eyes, use ninja graphic and set ammo count if player has ninjajetpack
2023-01-05 19:24:06 +00:00
if ( m_pPlayer - > m_NinjaJetpack & & m_Core . m_Jetpack & & m_Core . m_ActiveWeapon = = WEAPON_GUN & & ! m_Core . m_DeepFrozen & & m_FreezeTime = = 0 & & ! m_Core . m_HasTelegunGun )
2014-01-09 18:00:41 +00:00
{
2020-06-12 19:22:54 +00:00
if ( Emote = = EMOTE_NORMAL )
Emote = EMOTE_HAPPY ;
Weapon = WEAPON_NINJA ;
AmmoCount = 10 ;
2014-01-09 18:00:41 +00:00
}
2011-01-29 00:59:50 +00:00
2022-03-04 20:23:32 +00:00
if ( m_pPlayer - > GetCID ( ) = = SnappingClient | | SnappingClient = = SERVER_DEMO_CLIENT | |
2011-06-19 09:28:39 +00:00
( ! g_Config . m_SvStrictSpectateMode & & m_pPlayer - > GetCID ( ) = = GameServer ( ) - > m_apPlayers [ SnappingClient ] - > m_SpectatorID ) )
2011-01-29 00:59:50 +00:00
{
2020-06-12 19:22:54 +00:00
Health = m_Health ;
Armor = m_Armor ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_Ammo > 0 )
2023-03-26 14:42:31 +00:00
AmmoCount = ( m_FreezeTime = = 0 ) ? m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_Ammo : 0 ;
2011-01-29 00:59:50 +00:00
}
2022-12-22 23:06:29 +00:00
if ( GetPlayer ( ) - > IsAfk ( ) | | GetPlayer ( ) - > IsPaused ( ) )
2017-05-19 17:12:52 +00:00
{
2023-01-05 19:24:06 +00:00
if ( m_FreezeTime > 0 | | m_Core . m_DeepFrozen | | m_Core . m_LiveFrozen )
2020-06-12 19:22:54 +00:00
Emote = EMOTE_NORMAL ;
2017-05-19 17:12:52 +00:00
else
2020-06-12 19:22:54 +00:00
Emote = EMOTE_BLINK ;
2017-05-19 17:12:52 +00:00
}
2014-01-22 00:46:15 +00:00
2020-06-12 19:22:54 +00:00
if ( Emote = = EMOTE_NORMAL )
2011-01-29 00:59:50 +00:00
{
2023-11-23 13:42:30 +00:00
if ( 5 * Server ( ) - > TickSpeed ( ) - ( ( Server ( ) - > Tick ( ) - m_LastAction ) % ( 5 * Server ( ) - > TickSpeed ( ) ) ) < 5 )
2020-06-12 19:22:54 +00:00
Emote = EMOTE_BLINK ;
2011-01-29 00:59:50 +00:00
}
2020-06-12 19:22:54 +00:00
if ( ! Server ( ) - > IsSixup ( SnappingClient ) )
{
2023-02-10 18:34:57 +00:00
CNetObj_Character * pCharacter = Server ( ) - > SnapNewItem < CNetObj_Character > ( ID ) ;
2020-06-12 19:22:54 +00:00
if ( ! pCharacter )
return ;
pCore - > Write ( pCharacter ) ;
pCharacter - > m_Tick = Tick ;
pCharacter - > m_Emote = Emote ;
if ( pCharacter - > m_HookedPlayer ! = - 1 )
{
if ( ! Server ( ) - > Translate ( pCharacter - > m_HookedPlayer , SnappingClient ) )
pCharacter - > m_HookedPlayer = - 1 ;
}
pCharacter - > m_AttackTick = m_AttackTick ;
pCharacter - > m_Direction = m_Input . m_Direction ;
pCharacter - > m_Weapon = Weapon ;
pCharacter - > m_AmmoCount = AmmoCount ;
pCharacter - > m_Health = Health ;
pCharacter - > m_Armor = Armor ;
pCharacter - > m_PlayerFlags = GetPlayer ( ) - > m_PlayerFlags ;
}
else
{
2023-02-10 18:34:57 +00:00
protocol7 : : CNetObj_Character * pCharacter = Server ( ) - > SnapNewItem < protocol7 : : CNetObj_Character > ( ID ) ;
2020-06-12 19:22:54 +00:00
if ( ! pCharacter )
return ;
2020-06-13 12:43:24 +00:00
pCore - > Write ( reinterpret_cast < CNetObj_CharacterCore * > ( static_cast < protocol7 : : CNetObj_CharacterCore * > ( pCharacter ) ) ) ;
2022-04-10 16:49:10 +00:00
if ( pCharacter - > m_Angle > ( int ) ( pi * 256.0f ) )
{
pCharacter - > m_Angle - = ( int ) ( 2.0f * pi * 256.0f ) ;
}
2020-06-12 19:22:54 +00:00
pCharacter - > m_Tick = Tick ;
pCharacter - > m_Emote = Emote ;
pCharacter - > m_AttackTick = m_AttackTick ;
pCharacter - > m_Direction = m_Input . m_Direction ;
pCharacter - > m_Weapon = Weapon ;
pCharacter - > m_AmmoCount = AmmoCount ;
2020-06-20 10:54:41 +00:00
2023-01-05 19:24:06 +00:00
if ( m_FreezeTime > 0 | | m_Core . m_DeepFrozen )
2022-05-24 15:26:49 +00:00
pCharacter - > m_AmmoCount = m_Core . m_FreezeStart + g_Config . m_SvFreezeDelay * Server ( ) - > TickSpeed ( ) ;
2020-06-20 10:54:41 +00:00
else if ( Weapon = = WEAPON_NINJA )
2022-03-24 00:05:41 +00:00
pCharacter - > m_AmmoCount = m_Core . m_Ninja . m_ActivationTick + g_pData - > m_Weapons . m_Ninja . m_Duration * Server ( ) - > TickSpeed ( ) / 1000 ;
2020-06-20 10:54:41 +00:00
2020-06-12 19:22:54 +00:00
pCharacter - > m_Health = Health ;
pCharacter - > m_Armor = Armor ;
2023-10-29 13:53:13 +00:00
int TriggeredEvents7 = 0 ;
if ( m_Core . m_TriggeredEvents & COREEVENT_GROUND_JUMP )
TriggeredEvents7 | = protocol7 : : COREEVENTFLAG_GROUND_JUMP ;
if ( m_Core . m_TriggeredEvents & COREEVENT_AIR_JUMP )
TriggeredEvents7 | = protocol7 : : COREEVENTFLAG_AIR_JUMP ;
if ( m_Core . m_TriggeredEvents & COREEVENT_HOOK_ATTACH_PLAYER )
TriggeredEvents7 | = protocol7 : : COREEVENTFLAG_HOOK_ATTACH_PLAYER ;
if ( m_Core . m_TriggeredEvents & COREEVENT_HOOK_ATTACH_GROUND )
TriggeredEvents7 | = protocol7 : : COREEVENTFLAG_HOOK_ATTACH_GROUND ;
if ( m_Core . m_TriggeredEvents & COREEVENT_HOOK_HIT_NOHOOK )
TriggeredEvents7 | = protocol7 : : COREEVENTFLAG_HOOK_HIT_NOHOOK ;
pCharacter - > m_TriggeredEvents = TriggeredEvents7 ;
2020-06-12 19:22:54 +00:00
}
}
2021-09-02 00:34:32 +00:00
bool CCharacter : : CanSnapCharacter ( int SnappingClient )
{
2022-03-04 20:23:32 +00:00
if ( SnappingClient = = SERVER_DEMO_CLIENT )
2021-09-02 00:34:32 +00:00
return true ;
CCharacter * pSnapChar = GameServer ( ) - > GetPlayerChar ( SnappingClient ) ;
CPlayer * pSnapPlayer = GameServer ( ) - > m_apPlayers [ SnappingClient ] ;
if ( pSnapPlayer - > GetTeam ( ) = = TEAM_SPECTATORS | | pSnapPlayer - > IsPaused ( ) )
{
2022-03-07 21:16:28 +00:00
if ( pSnapPlayer - > m_SpectatorID ! = SPEC_FREEVIEW & & ! CanCollide ( pSnapPlayer - > m_SpectatorID ) & & ( pSnapPlayer - > m_ShowOthers = = SHOW_OTHERS_OFF | | ( pSnapPlayer - > m_ShowOthers = = SHOW_OTHERS_ONLY_TEAM & & ! SameTeam ( pSnapPlayer - > m_SpectatorID ) ) ) )
2021-09-02 00:34:32 +00:00
return false ;
2022-03-07 21:16:28 +00:00
else if ( pSnapPlayer - > m_SpectatorID = = SPEC_FREEVIEW & & ! CanCollide ( SnappingClient ) & & pSnapPlayer - > m_SpecTeam & & ! SameTeam ( SnappingClient ) )
2021-09-02 00:34:32 +00:00
return false ;
}
2022-06-30 17:29:58 +00:00
else if ( pSnapChar & & ! pSnapChar - > m_Core . m_Super & & ! CanCollide ( SnappingClient ) & & ( pSnapPlayer - > m_ShowOthers = = SHOW_OTHERS_OFF | | ( pSnapPlayer - > m_ShowOthers = = SHOW_OTHERS_ONLY_TEAM & & ! SameTeam ( SnappingClient ) ) ) )
2021-09-02 00:34:32 +00:00
return false ;
return true ;
}
2023-06-11 11:24:02 +00:00
bool CCharacter : : IsSnappingCharacterInView ( int SnappingClientID )
2020-06-12 19:22:54 +00:00
{
2020-06-30 12:17:27 +00:00
int ID = m_pPlayer - > GetCID ( ) ;
2020-06-12 19:22:54 +00:00
2022-05-09 20:46:20 +00:00
// A player may not be clipped away if his hook or a hook attached to him is in the field of view
2023-06-11 11:24:02 +00:00
bool PlayerAndHookNotInView = NetworkClippedLine ( SnappingClientID , m_Pos , m_Core . m_HookPos ) ;
2022-05-09 20:46:20 +00:00
bool AttachedHookInView = false ;
if ( PlayerAndHookNotInView )
{
2022-05-22 19:43:31 +00:00
for ( const auto & AttachedPlayerID : m_Core . m_AttachedPlayers )
2022-05-09 20:46:20 +00:00
{
2023-10-05 20:37:53 +00:00
const CCharacter * pOtherPlayer = GameServer ( ) - > GetPlayerChar ( AttachedPlayerID ) ;
2023-09-05 21:53:03 +00:00
if ( pOtherPlayer & & pOtherPlayer - > m_Core . HookedPlayer ( ) = = ID )
2022-05-09 20:46:20 +00:00
{
2023-06-11 11:24:02 +00:00
if ( ! NetworkClippedLine ( SnappingClientID , m_Pos , pOtherPlayer - > m_Pos ) )
2022-05-09 20:46:20 +00:00
{
AttachedHookInView = true ;
break ;
}
}
}
}
if ( PlayerAndHookNotInView & & ! AttachedHookInView )
2023-06-11 11:24:02 +00:00
{
return false ;
}
return true ;
}
void CCharacter : : Snap ( int SnappingClient )
{
int ID = m_pPlayer - > GetCID ( ) ;
if ( ! Server ( ) - > Translate ( ID , SnappingClient ) )
return ;
if ( ! CanSnapCharacter ( SnappingClient ) )
2022-05-09 20:46:20 +00:00
{
return ;
}
2020-06-12 19:22:54 +00:00
2023-06-11 11:24:02 +00:00
if ( ! IsSnappingCharacterInView ( SnappingClient ) )
return ;
2020-06-30 12:17:27 +00:00
SnapCharacter ( SnappingClient , ID ) ;
2019-04-17 21:47:32 +00:00
2023-02-10 18:34:57 +00:00
CNetObj_DDNetCharacter * pDDNetCharacter = Server ( ) - > SnapNewItem < CNetObj_DDNetCharacter > ( ID ) ;
2020-01-16 11:35:26 +00:00
if ( ! pDDNetCharacter )
return ;
2019-04-17 21:47:32 +00:00
pDDNetCharacter - > m_Flags = 0 ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Solo )
2019-04-17 21:47:32 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_SOLO ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Super )
2019-04-19 09:17:28 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_SUPER ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_EndlessHook )
2019-04-19 09:17:28 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_ENDLESS_HOOK ;
2023-09-05 23:08:01 +00:00
if ( m_Core . m_CollisionDisabled | | ! Tuning ( ) - > m_PlayerCollision )
2022-07-08 13:31:58 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_COLLISION_DISABLED ;
2023-09-05 23:08:01 +00:00
if ( m_Core . m_HookHitDisabled | | ! Tuning ( ) - > m_PlayerHooking )
2022-07-08 13:31:58 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_HOOK_HIT_DISABLED ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_EndlessJump )
2019-04-19 09:17:28 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_ENDLESS_JUMP ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Jetpack )
2019-04-19 09:17:28 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_JETPACK ;
2022-07-08 13:31:58 +00:00
if ( m_Core . m_HammerHitDisabled )
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_HAMMER_HIT_DISABLED ;
if ( m_Core . m_ShotgunHitDisabled )
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_SHOTGUN_HIT_DISABLED ;
if ( m_Core . m_GrenadeHitDisabled )
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_GRENADE_HIT_DISABLED ;
if ( m_Core . m_LaserHitDisabled )
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_LASER_HIT_DISABLED ;
2019-08-19 08:09:53 +00:00
if ( m_Core . m_HasTelegunGun )
2019-04-19 09:17:28 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_TELEGUN_GUN ;
2019-08-19 08:09:53 +00:00
if ( m_Core . m_HasTelegunGrenade )
2019-04-19 09:17:28 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_TELEGUN_GRENADE ;
2019-08-19 08:09:53 +00:00
if ( m_Core . m_HasTelegunLaser )
2019-04-19 09:17:28 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_TELEGUN_LASER ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ WEAPON_HAMMER ] . m_Got )
2019-05-01 21:47:40 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_WEAPON_HAMMER ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ WEAPON_GUN ] . m_Got )
2019-05-01 21:47:40 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_WEAPON_GUN ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ WEAPON_SHOTGUN ] . m_Got )
2019-05-01 21:47:40 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_WEAPON_SHOTGUN ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ WEAPON_GRENADE ] . m_Got )
2019-05-01 21:47:40 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_WEAPON_GRENADE ;
2022-03-21 22:50:41 +00:00
if ( m_Core . m_aWeapons [ WEAPON_LASER ] . m_Got )
2019-05-01 21:47:40 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_WEAPON_LASER ;
if ( m_Core . m_ActiveWeapon = = WEAPON_NINJA )
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_WEAPON_NINJA ;
2022-01-08 11:30:51 +00:00
if ( m_Core . m_LiveFrozen )
2022-07-08 13:31:58 +00:00
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_MOVEMENTS_DISABLED ;
2019-04-23 15:57:26 +00:00
2022-06-30 17:29:58 +00:00
pDDNetCharacter - > m_FreezeEnd = m_Core . m_DeepFrozen ? - 1 : m_FreezeTime = = 0 ? 0 : Server ( ) - > Tick ( ) + m_FreezeTime ;
2019-05-01 21:47:40 +00:00
pDDNetCharacter - > m_Jumps = m_Core . m_Jumps ;
pDDNetCharacter - > m_TeleCheckpoint = m_TeleCheckpoint ;
2019-05-01 22:34:20 +00:00
pDDNetCharacter - > m_StrongWeakID = m_StrongWeakID ;
2022-03-27 16:18:53 +00:00
2022-10-25 16:51:56 +00:00
// Display Information
2022-05-24 15:26:49 +00:00
pDDNetCharacter - > m_JumpedTotal = m_Core . m_JumpedTotal ;
pDDNetCharacter - > m_NinjaActivationTick = m_Core . m_Ninja . m_ActivationTick ;
pDDNetCharacter - > m_FreezeStart = m_Core . m_FreezeStart ;
if ( m_Core . m_IsInFreeze )
{
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_IN_FREEZE ;
}
if ( Teams ( ) - > IsPractice ( Team ( ) ) )
{
pDDNetCharacter - > m_Flags | = CHARACTERFLAG_PRACTICE_MODE ;
}
pDDNetCharacter - > m_TargetX = m_Core . m_Input . m_TargetX ;
pDDNetCharacter - > m_TargetY = m_Core . m_Input . m_TargetY ;
2011-01-29 00:59:50 +00:00
}
2011-04-09 06:41:31 +00:00
// DDRace
2011-02-13 05:35:13 +00:00
bool CCharacter : : CanCollide ( int ClientID )
2011-01-29 00:59:50 +00:00
{
2011-02-13 05:35:13 +00:00
return Teams ( ) - > m_Core . CanCollide ( GetPlayer ( ) - > GetCID ( ) , ClientID ) ;
2011-01-29 00:59:50 +00:00
}
2011-02-13 05:35:13 +00:00
bool CCharacter : : SameTeam ( int ClientID )
2011-01-29 00:59:50 +00:00
{
2011-02-13 05:35:13 +00:00
return Teams ( ) - > m_Core . SameTeam ( GetPlayer ( ) - > GetCID ( ) , ClientID ) ;
2011-01-29 00:59:50 +00:00
}
2010-09-17 11:26:06 +00:00
int CCharacter : : Team ( )
{
2011-07-21 22:01:12 +00:00
return Teams ( ) - > m_Core . Team ( m_pPlayer - > GetCID ( ) ) ;
2010-08-28 20:53:42 +00:00
}
2021-01-12 23:12:08 +00:00
void CCharacter : : SetTeleports ( std : : map < int , std : : vector < vec2 > > * pTeleOuts , std : : map < int , std : : vector < vec2 > > * pTeleCheckOuts )
{
m_pTeleOuts = pTeleOuts ;
m_pTeleCheckOuts = pTeleCheckOuts ;
2023-09-05 22:09:10 +00:00
m_Core . SetTeleOuts ( pTeleOuts ) ;
2021-01-12 23:12:08 +00:00
}
2020-03-11 00:58:50 +00:00
void CCharacter : : FillAntibot ( CAntibotCharacterData * pData )
{
pData - > m_Pos = m_Pos ;
pData - > m_Vel = m_Core . m_Vel ;
pData - > m_Angle = m_Core . m_Angle ;
2023-09-05 21:53:03 +00:00
pData - > m_HookedPlayer = m_Core . HookedPlayer ( ) ;
2020-03-11 00:58:50 +00:00
pData - > m_SpawnTick = m_SpawnTick ;
pData - > m_WeaponChangeTick = m_WeaponChangeTick ;
pData - > m_aLatestInputs [ 0 ] . m_TargetX = m_LatestInput . m_TargetX ;
pData - > m_aLatestInputs [ 0 ] . m_TargetY = m_LatestInput . m_TargetY ;
pData - > m_aLatestInputs [ 1 ] . m_TargetX = m_LatestPrevInput . m_TargetX ;
pData - > m_aLatestInputs [ 1 ] . m_TargetY = m_LatestPrevInput . m_TargetY ;
pData - > m_aLatestInputs [ 2 ] . m_TargetX = m_LatestPrevPrevInput . m_TargetX ;
pData - > m_aLatestInputs [ 2 ] . m_TargetY = m_LatestPrevPrevInput . m_TargetY ;
}
2011-01-29 00:59:50 +00:00
void CCharacter : : HandleBroadcast ( )
2008-07-06 11:21:21 +00:00
{
2010-10-08 13:33:42 +00:00
CPlayerData * pData = GameServer ( ) - > Score ( ) - > PlayerData ( m_pPlayer - > GetCID ( ) ) ;
2013-03-18 11:58:29 +00:00
2022-07-05 14:13:48 +00:00
if ( m_DDRaceState = = DDRACE_STARTED & & m_pPlayer - > GetClientVersion ( ) = = VERSION_VANILLA & &
m_LastTimeCpBroadcasted ! = m_LastTimeCp & & m_LastTimeCp > - 1 & &
m_TimeCpBroadcastEndTick > Server ( ) - > Tick ( ) & & pData - > m_BestTime & & pData - > m_aBestTimeCp [ m_LastTimeCp ] ! = 0 )
2010-10-08 13:33:42 +00:00
{
Added the following settings to Close #123.
sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands"
sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time"
sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands"
Added the following Chat commands to give the player the choice over their settings:
"saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race"
"saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race"
"time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message"
"broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status"
"servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status"
Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques
Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect.
So now players have the choice to see which timer they wanna see if any.
Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
char aBroadcast [ 128 ] ;
2022-07-05 14:13:48 +00:00
float Diff = m_aCurrentTimeCp [ m_LastTimeCp ] - pData - > m_aBestTimeCp [ m_LastTimeCp ] ;
2011-06-05 11:56:04 +00:00
str_format ( aBroadcast , sizeof ( aBroadcast ) , " Checkpoint | Diff : %+5.2f " , Diff ) ;
GameServer ( ) - > SendBroadcast ( aBroadcast , m_pPlayer - > GetCID ( ) ) ;
2022-07-05 14:13:48 +00:00
m_LastTimeCpBroadcasted = m_LastTimeCp ;
2011-06-05 11:56:04 +00:00
m_LastBroadcast = Server ( ) - > Tick ( ) ;
2010-08-10 04:28:17 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( ( m_pPlayer - > m_TimerType = = CPlayer : : TIMERTYPE_BROADCAST | | m_pPlayer - > m_TimerType = = CPlayer : : TIMERTYPE_GAMETIMER_AND_BROADCAST ) & & m_DDRaceState = = DDRACE_STARTED & & m_LastBroadcast + Server ( ) - > TickSpeed ( ) * g_Config . m_SvTimeInBroadcastInterval < = Server ( ) - > Tick ( ) )
Added the following settings to Close #123.
sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands"
sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time"
sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands"
Added the following Chat commands to give the player the choice over their settings:
"saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race"
"saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race"
"time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message"
"broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status"
"servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status"
Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques
Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect.
So now players have the choice to see which timer they wanna see if any.
Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
{
2020-11-13 23:22:21 +00:00
char aBuf [ 32 ] ;
2021-06-23 05:05:49 +00:00
int Time = ( int64_t ) 100 * ( ( float ) ( Server ( ) - > Tick ( ) - m_StartTime ) / ( ( float ) Server ( ) - > TickSpeed ( ) ) ) ;
2020-11-13 23:22:21 +00:00
str_time ( Time , TIME_HOURS , aBuf , sizeof ( aBuf ) ) ;
GameServer ( ) - > SendBroadcast ( aBuf , m_pPlayer - > GetCID ( ) , false ) ;
2022-07-05 14:13:48 +00:00
m_LastTimeCpBroadcasted = m_LastTimeCp ;
Added the following settings to Close #123.
sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands"
sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time"
sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands"
Added the following Chat commands to give the player the choice over their settings:
"saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race"
"saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race"
"time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message"
"broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status"
"servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status"
Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques
Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect.
So now players have the choice to see which timer they wanna see if any.
Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
m_LastBroadcast = Server ( ) - > Tick ( ) ;
}
2011-01-29 00:59:50 +00:00
}
2011-01-21 09:44:29 +00:00
2011-01-29 00:59:50 +00:00
void CCharacter : : HandleSkippableTiles ( int Index )
{
2011-01-29 23:58:47 +00:00
// handle death-tiles and leaving gamelayer
2022-05-28 18:24:24 +00:00
if ( ( Collision ( ) - > GetCollisionAt ( m_Pos . x + GetProximityRadius ( ) / 3.f , m_Pos . y - GetProximityRadius ( ) / 3.f ) = = TILE_DEATH | |
Collision ( ) - > GetCollisionAt ( m_Pos . x + GetProximityRadius ( ) / 3.f , m_Pos . y + GetProximityRadius ( ) / 3.f ) = = TILE_DEATH | |
Collision ( ) - > GetCollisionAt ( m_Pos . x - GetProximityRadius ( ) / 3.f , m_Pos . y - GetProximityRadius ( ) / 3.f ) = = TILE_DEATH | |
Collision ( ) - > GetCollisionAt ( m_Pos . x - GetProximityRadius ( ) / 3.f , m_Pos . y + GetProximityRadius ( ) / 3.f ) = = TILE_DEATH | |
Collision ( ) - > GetFCollisionAt ( m_Pos . x + GetProximityRadius ( ) / 3.f , m_Pos . y - GetProximityRadius ( ) / 3.f ) = = TILE_DEATH | |
Collision ( ) - > GetFCollisionAt ( m_Pos . x + GetProximityRadius ( ) / 3.f , m_Pos . y + GetProximityRadius ( ) / 3.f ) = = TILE_DEATH | |
Collision ( ) - > GetFCollisionAt ( m_Pos . x - GetProximityRadius ( ) / 3.f , m_Pos . y - GetProximityRadius ( ) / 3.f ) = = TILE_DEATH | |
Collision ( ) - > GetFCollisionAt ( m_Pos . x - GetProximityRadius ( ) / 3.f , m_Pos . y + GetProximityRadius ( ) / 3.f ) = = TILE_DEATH ) & &
2022-06-30 17:29:58 +00:00
! m_Core . m_Super & & ! ( Team ( ) & & Teams ( ) - > TeeFinished ( m_pPlayer - > GetCID ( ) ) ) )
2014-01-31 22:24:45 +00:00
{
Die ( m_pPlayer - > GetCID ( ) , WEAPON_WORLD ) ;
return ;
}
2020-09-26 19:41:58 +00:00
if ( GameLayerClipped ( m_Pos ) )
2014-01-31 22:24:45 +00:00
{
Die ( m_pPlayer - > GetCID ( ) , WEAPON_WORLD ) ;
return ;
}
2011-01-29 23:58:47 +00:00
if ( Index < 0 )
return ;
2011-01-21 09:44:29 +00:00
// handle speedup tiles
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > IsSpeedup ( Index ) )
2010-06-11 09:39:32 +00:00
{
2020-11-20 11:14:04 +00:00
vec2 Direction , TempVel = m_Core . m_Vel ;
2011-01-21 09:44:29 +00:00
int Force , MaxSpeed = 0 ;
float TeeAngle , SpeederAngle , DiffAngle , SpeedLeft , TeeSpeed ;
2022-05-28 18:24:24 +00:00
Collision ( ) - > GetSpeedup ( Index , & Direction , & Force , & MaxSpeed ) ;
2011-01-21 09:44:29 +00:00
if ( Force = = 255 & & MaxSpeed )
{
2020-09-26 19:41:58 +00:00
m_Core . m_Vel = Direction * ( MaxSpeed / 5 ) ;
2011-01-21 09:44:29 +00:00
}
else
{
2020-09-26 19:41:58 +00:00
if ( MaxSpeed > 0 & & MaxSpeed < 5 )
MaxSpeed = 5 ;
2011-01-21 09:44:29 +00:00
if ( MaxSpeed > 0 )
{
if ( Direction . x > 0.0000001f )
2023-02-28 20:31:40 +00:00
SpeederAngle = - std : : atan ( Direction . y / Direction . x ) ;
2011-01-21 09:44:29 +00:00
else if ( Direction . x < 0.0000001f )
2023-02-28 20:31:40 +00:00
SpeederAngle = std : : atan ( Direction . y / Direction . x ) + 2.0f * std : : asin ( 1.0f ) ;
2011-01-21 09:44:29 +00:00
else if ( Direction . y > 0.0000001f )
2023-02-28 20:31:40 +00:00
SpeederAngle = std : : asin ( 1.0f ) ;
2011-01-21 09:44:29 +00:00
else
2023-02-28 20:31:40 +00:00
SpeederAngle = std : : asin ( - 1.0f ) ;
2011-01-21 09:44:29 +00:00
if ( SpeederAngle < 0 )
2023-02-28 20:31:40 +00:00
SpeederAngle = 4.0f * std : : asin ( 1.0f ) + SpeederAngle ;
2011-01-21 09:44:29 +00:00
if ( TempVel . x > 0.0000001f )
2023-02-28 20:31:40 +00:00
TeeAngle = - std : : atan ( TempVel . y / TempVel . x ) ;
2011-01-21 09:44:29 +00:00
else if ( TempVel . x < 0.0000001f )
2023-02-28 20:31:40 +00:00
TeeAngle = std : : atan ( TempVel . y / TempVel . x ) + 2.0f * std : : asin ( 1.0f ) ;
2011-01-21 09:44:29 +00:00
else if ( TempVel . y > 0.0000001f )
2023-02-28 20:31:40 +00:00
TeeAngle = std : : asin ( 1.0f ) ;
2011-01-21 09:44:29 +00:00
else
2023-02-28 20:31:40 +00:00
TeeAngle = std : : asin ( - 1.0f ) ;
2011-01-21 09:44:29 +00:00
if ( TeeAngle < 0 )
2023-02-28 20:31:40 +00:00
TeeAngle = 4.0f * std : : asin ( 1.0f ) + TeeAngle ;
2011-01-21 09:44:29 +00:00
2023-02-28 20:31:40 +00:00
TeeSpeed = std : : sqrt ( std : : pow ( TempVel . x , 2 ) + std : : pow ( TempVel . y , 2 ) ) ;
2011-01-21 09:44:29 +00:00
DiffAngle = SpeederAngle - TeeAngle ;
2023-02-28 20:31:40 +00:00
SpeedLeft = MaxSpeed / 5.0f - std : : cos ( DiffAngle ) * TeeSpeed ;
if ( absolute ( ( int ) SpeedLeft ) > Force & & SpeedLeft > 0.0000001f )
2011-01-21 09:44:29 +00:00
TempVel + = Direction * Force ;
2023-02-28 20:31:40 +00:00
else if ( absolute ( ( int ) SpeedLeft ) > Force )
2011-01-21 09:44:29 +00:00
TempVel + = Direction * - Force ;
else
TempVel + = Direction * SpeedLeft ;
}
else
TempVel + = Direction * Force ;
2018-08-15 15:47:07 +00:00
m_Core . m_Vel = ClampVel ( m_MoveRestrictions , TempVel ) ;
2011-01-21 09:44:29 +00:00
}
2010-06-11 09:39:32 +00:00
}
2008-07-06 11:21:21 +00:00
}
2018-08-15 15:47:07 +00:00
bool CCharacter : : IsSwitchActiveCb ( int Number , void * pUser )
{
CCharacter * pThis = ( CCharacter * ) pUser ;
2022-02-13 19:57:27 +00:00
auto & aSwitchers = pThis - > Switchers ( ) ;
2022-06-30 22:36:32 +00:00
return ! aSwitchers . empty ( ) & & pThis - > Team ( ) ! = TEAM_SUPER & & aSwitchers [ Number ] . m_aStatus [ pThis - > Team ( ) ] ;
2018-08-15 15:47:07 +00:00
}
2022-07-03 11:31:54 +00:00
void CCharacter : : SetTimeCheckpoint ( int TimeCheckpoint )
2011-01-29 00:59:50 +00:00
{
2022-07-06 11:36:52 +00:00
if ( TimeCheckpoint > - 1 & & m_DDRaceState = = DDRACE_STARTED & & m_aCurrentTimeCp [ TimeCheckpoint ] = = 0.0f & & m_Time ! = 0.0f )
2010-10-08 13:33:42 +00:00
{
2022-07-05 14:13:48 +00:00
m_LastTimeCp = TimeCheckpoint ;
2022-07-06 11:36:52 +00:00
m_aCurrentTimeCp [ m_LastTimeCp ] = m_Time ;
2022-07-05 14:13:48 +00:00
m_TimeCpBroadcastEndTick = Server ( ) - > Tick ( ) + Server ( ) - > TickSpeed ( ) * 2 ;
2020-09-26 19:41:58 +00:00
if ( m_pPlayer - > GetClientVersion ( ) > = VERSION_DDRACE )
{
2010-11-30 02:24:15 +00:00
CPlayerData * pData = GameServer ( ) - > Score ( ) - > PlayerData ( m_pPlayer - > GetCID ( ) ) ;
2022-07-06 11:36:52 +00:00
if ( pData - > m_BestTime & & pData - > m_aBestTimeCp [ m_LastTimeCp ] ! = 0.0f )
2010-11-30 02:24:15 +00:00
{
2022-07-03 11:31:54 +00:00
CNetMsg_Sv_DDRaceTime Msg ;
Msg . m_Time = ( int ) ( m_Time * 100.0f ) ;
Msg . m_Finish = 0 ;
2022-07-05 14:13:48 +00:00
float Diff = ( m_aCurrentTimeCp [ m_LastTimeCp ] - pData - > m_aBestTimeCp [ m_LastTimeCp ] ) * 100 ;
2022-07-03 11:31:54 +00:00
Msg . m_Check = ( int ) Diff ;
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , m_pPlayer - > GetCID ( ) ) ;
2010-11-30 02:24:15 +00:00
}
}
2010-10-08 13:33:42 +00:00
}
2022-06-30 22:00:03 +00:00
}
2010-11-30 02:24:15 +00:00
2022-06-30 22:00:03 +00:00
void CCharacter : : HandleTiles ( int Index )
{
int MapIndex = Index ;
//int PureMapIndex = Collision()->GetPureMapIndex(m_Pos);
m_TileIndex = Collision ( ) - > GetTileIndex ( MapIndex ) ;
m_TileFIndex = Collision ( ) - > GetFTileIndex ( MapIndex ) ;
m_MoveRestrictions = Collision ( ) - > GetMoveRestrictions ( IsSwitchActiveCb , this , m_Pos , 18.0f , MapIndex ) ;
if ( Index < 0 )
{
m_LastRefillJumps = false ;
m_LastPenalty = false ;
m_LastBonus = false ;
return ;
2010-10-30 18:48:30 +00:00
}
2022-06-30 22:00:03 +00:00
SetTimeCheckpoint ( Collision ( ) - > IsTimeCheckpoint ( MapIndex ) ) ;
SetTimeCheckpoint ( Collision ( ) - > IsFTimeCheckpoint ( MapIndex ) ) ;
2022-07-03 11:31:54 +00:00
int TeleCheckpoint = Collision ( ) - > IsTeleCheckpoint ( MapIndex ) ;
if ( TeleCheckpoint )
m_TeleCheckpoint = TeleCheckpoint ;
2014-12-29 14:54:55 +00:00
2021-01-12 22:26:20 +00:00
GameServer ( ) - > m_pController - > HandleCharacterTiles ( this , Index ) ;
2014-12-29 14:54:55 +00:00
// freeze
2022-06-30 17:29:58 +00:00
if ( ( ( m_TileIndex = = TILE_FREEZE ) | | ( m_TileFIndex = = TILE_FREEZE ) ) & & ! m_Core . m_Super & & ! m_Core . m_DeepFrozen )
2022-03-27 16:18:53 +00:00
{
2011-01-25 09:34:14 +00:00
Freeze ( ) ;
2022-03-27 16:18:53 +00:00
}
2022-06-30 17:29:58 +00:00
else if ( ( ( m_TileIndex = = TILE_UNFREEZE ) | | ( m_TileFIndex = = TILE_UNFREEZE ) ) & & ! m_Core . m_DeepFrozen )
2010-10-08 13:33:42 +00:00
UnFreeze ( ) ;
2014-12-29 14:54:55 +00:00
// deep freeze
2022-06-30 17:29:58 +00:00
if ( ( ( m_TileIndex = = TILE_DFREEZE ) | | ( m_TileFIndex = = TILE_DFREEZE ) ) & & ! m_Core . m_Super & & ! m_Core . m_DeepFrozen )
m_Core . m_DeepFrozen = true ;
else if ( ( ( m_TileIndex = = TILE_DUNFREEZE ) | | ( m_TileFIndex = = TILE_DUNFREEZE ) ) & & ! m_Core . m_Super & & m_Core . m_DeepFrozen )
m_Core . m_DeepFrozen = false ;
2014-12-29 14:54:55 +00:00
2022-01-07 15:53:40 +00:00
// live freeze
2022-06-30 17:29:58 +00:00
if ( ( ( m_TileIndex = = TILE_LFREEZE ) | | ( m_TileFIndex = = TILE_LFREEZE ) ) & & ! m_Core . m_Super )
2022-01-07 15:53:40 +00:00
{
2022-06-30 17:29:58 +00:00
m_Core . m_LiveFrozen = true ;
2022-01-07 15:53:40 +00:00
}
2022-06-30 17:29:58 +00:00
else if ( ( ( m_TileIndex = = TILE_LUNFREEZE ) | | ( m_TileFIndex = = TILE_LUNFREEZE ) ) & & ! m_Core . m_Super )
2022-01-07 15:53:40 +00:00
{
2022-06-30 17:29:58 +00:00
m_Core . m_LiveFrozen = false ;
2022-01-07 15:53:40 +00:00
}
2014-12-29 14:54:55 +00:00
// endless hook
2020-12-26 22:09:33 +00:00
if ( ( ( m_TileIndex = = TILE_EHOOK_ENABLE ) | | ( m_TileFIndex = = TILE_EHOOK_ENABLE ) ) )
2011-01-16 22:13:21 +00:00
{
2022-01-08 11:30:51 +00:00
SetEndlessHook ( true ) ;
2011-01-16 22:13:21 +00:00
}
2020-12-26 22:09:33 +00:00
else if ( ( ( m_TileIndex = = TILE_EHOOK_DISABLE ) | | ( m_TileFIndex = = TILE_EHOOK_DISABLE ) ) )
2011-01-16 22:13:21 +00:00
{
2020-12-26 22:09:33 +00:00
SetEndlessHook ( false ) ;
2011-01-16 22:13:21 +00:00
}
2014-12-29 14:54:55 +00:00
// hit others
2022-07-08 13:31:58 +00:00
if ( ( ( m_TileIndex = = TILE_HIT_DISABLE ) | | ( m_TileFIndex = = TILE_HIT_DISABLE ) ) & & ( ! m_Core . m_HammerHitDisabled | | ! m_Core . m_ShotgunHitDisabled | | ! m_Core . m_GrenadeHitDisabled | | ! m_Core . m_LaserHitDisabled ) )
2014-12-29 14:54:55 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can't hit others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_HammerHitDisabled = true ;
m_Core . m_ShotgunHitDisabled = true ;
m_Core . m_GrenadeHitDisabled = true ;
m_Core . m_LaserHitDisabled = true ;
2014-12-29 14:54:55 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( ( ( m_TileIndex = = TILE_HIT_ENABLE ) | | ( m_TileFIndex = = TILE_HIT_ENABLE ) ) & & ( m_Core . m_HammerHitDisabled | | m_Core . m_ShotgunHitDisabled | | m_Core . m_GrenadeHitDisabled | | m_Core . m_LaserHitDisabled ) )
2011-07-19 21:33:12 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can hit others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_ShotgunHitDisabled = false ;
m_Core . m_GrenadeHitDisabled = false ;
m_Core . m_HammerHitDisabled = false ;
m_Core . m_LaserHitDisabled = false ;
2011-07-19 21:33:12 +00:00
}
2014-12-29 14:54:55 +00:00
// collide with others
2022-07-08 13:31:58 +00:00
if ( ( ( m_TileIndex = = TILE_NPC_DISABLE ) | | ( m_TileFIndex = = TILE_NPC_DISABLE ) ) & & ! m_Core . m_CollisionDisabled )
2014-12-29 14:54:55 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can't collide with others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_CollisionDisabled = true ;
2014-12-29 14:54:55 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( ( ( m_TileIndex = = TILE_NPC_ENABLE ) | | ( m_TileFIndex = = TILE_NPC_ENABLE ) ) & & m_Core . m_CollisionDisabled )
2013-08-05 15:47:04 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can collide with others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_CollisionDisabled = false ;
2013-08-05 15:47:04 +00:00
}
2014-12-29 14:54:55 +00:00
// hook others
2022-07-08 13:31:58 +00:00
if ( ( ( m_TileIndex = = TILE_NPH_DISABLE ) | | ( m_TileFIndex = = TILE_NPH_DISABLE ) ) & & ! m_Core . m_HookHitDisabled )
2013-11-22 14:10:55 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can't hook others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_HookHitDisabled = true ;
2013-11-22 14:10:55 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( ( ( m_TileIndex = = TILE_NPH_ENABLE ) | | ( m_TileFIndex = = TILE_NPH_ENABLE ) ) & & m_Core . m_HookHitDisabled )
2013-08-05 15:47:04 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can hook others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_HookHitDisabled = false ;
2013-08-05 15:47:04 +00:00
}
2014-12-29 14:54:55 +00:00
// unlimited air jumps
2022-06-30 17:29:58 +00:00
if ( ( ( m_TileIndex = = TILE_UNLIMITED_JUMPS_ENABLE ) | | ( m_TileFIndex = = TILE_UNLIMITED_JUMPS_ENABLE ) ) & & ! m_Core . m_EndlessJump )
2013-08-05 15:47:04 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You have unlimited air jumps " ) ;
2019-04-21 13:16:28 +00:00
m_Core . m_EndlessJump = true ;
2013-08-05 15:47:04 +00:00
}
2022-06-30 17:29:58 +00:00
else if ( ( ( m_TileIndex = = TILE_UNLIMITED_JUMPS_DISABLE ) | | ( m_TileFIndex = = TILE_UNLIMITED_JUMPS_DISABLE ) ) & & m_Core . m_EndlessJump )
2013-08-05 15:47:04 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You don't have unlimited air jumps " ) ;
2019-04-21 13:16:28 +00:00
m_Core . m_EndlessJump = false ;
2013-08-05 15:47:04 +00:00
}
2014-12-29 14:54:55 +00:00
// walljump
if ( ( m_TileIndex = = TILE_WALLJUMP ) | | ( m_TileFIndex = = TILE_WALLJUMP ) )
2014-06-21 22:50:11 +00:00
{
2014-06-24 21:47:33 +00:00
if ( m_Core . m_Vel . y > 0 & & m_Core . m_Colliding & & m_Core . m_LeftWall )
2014-06-21 22:50:11 +00:00
{
2014-06-23 12:46:27 +00:00
m_Core . m_LeftWall = false ;
2022-05-16 21:17:19 +00:00
m_Core . m_JumpedTotal = m_Core . m_Jumps > = 2 ? m_Core . m_Jumps - 2 : 0 ;
2014-06-21 22:50:11 +00:00
m_Core . m_Jumped = 1 ;
}
}
2014-12-29 14:54:55 +00:00
// jetpack gun
2022-06-30 17:29:58 +00:00
if ( ( ( m_TileIndex = = TILE_JETPACK_ENABLE ) | | ( m_TileFIndex = = TILE_JETPACK_ENABLE ) ) & & ! m_Core . m_Jetpack )
2014-12-29 14:54:55 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You have a jetpack gun " ) ;
2019-04-21 13:16:28 +00:00
m_Core . m_Jetpack = true ;
2014-12-29 14:54:55 +00:00
}
2022-06-30 17:29:58 +00:00
else if ( ( ( m_TileIndex = = TILE_JETPACK_DISABLE ) | | ( m_TileFIndex = = TILE_JETPACK_DISABLE ) ) & & m_Core . m_Jetpack )
2013-11-22 14:10:55 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You lost your jetpack gun " ) ;
2019-04-21 13:16:28 +00:00
m_Core . m_Jetpack = false ;
2013-11-22 14:10:55 +00:00
}
2014-12-29 14:54:55 +00:00
// refill jumps
if ( ( ( m_TileIndex = = TILE_REFILL_JUMPS ) | | ( m_TileFIndex = = TILE_REFILL_JUMPS ) ) & & ! m_LastRefillJumps )
{
m_Core . m_JumpedTotal = 0 ;
2015-03-22 17:27:57 +00:00
m_Core . m_Jumped = 0 ;
2014-12-29 14:54:55 +00:00
m_LastRefillJumps = true ;
}
if ( ( m_TileIndex ! = TILE_REFILL_JUMPS ) & & ( m_TileFIndex ! = TILE_REFILL_JUMPS ) )
{
m_LastRefillJumps = false ;
}
2018-02-14 15:27:26 +00:00
// Teleport gun
2020-09-26 19:41:58 +00:00
if ( ( ( m_TileIndex = = TILE_TELE_GUN_ENABLE ) | | ( m_TileFIndex = = TILE_TELE_GUN_ENABLE ) ) & & ! m_Core . m_HasTelegunGun )
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core . m_HasTelegunGun = true ;
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " Teleport gun enabled " ) ;
2018-02-14 15:27:26 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( ( ( m_TileIndex = = TILE_TELE_GUN_DISABLE ) | | ( m_TileFIndex = = TILE_TELE_GUN_DISABLE ) ) & & m_Core . m_HasTelegunGun )
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core . m_HasTelegunGun = false ;
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " Teleport gun disabled " ) ;
2018-02-14 15:27:26 +00:00
}
2020-09-26 19:41:58 +00:00
if ( ( ( m_TileIndex = = TILE_TELE_GRENADE_ENABLE ) | | ( m_TileFIndex = = TILE_TELE_GRENADE_ENABLE ) ) & & ! m_Core . m_HasTelegunGrenade )
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core . m_HasTelegunGrenade = true ;
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " Teleport grenade enabled " ) ;
2018-02-14 15:27:26 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( ( ( m_TileIndex = = TILE_TELE_GRENADE_DISABLE ) | | ( m_TileFIndex = = TILE_TELE_GRENADE_DISABLE ) ) & & m_Core . m_HasTelegunGrenade )
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core . m_HasTelegunGrenade = false ;
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " Teleport grenade disabled " ) ;
2018-02-14 15:27:26 +00:00
}
2020-09-26 19:41:58 +00:00
if ( ( ( m_TileIndex = = TILE_TELE_LASER_ENABLE ) | | ( m_TileFIndex = = TILE_TELE_LASER_ENABLE ) ) & & ! m_Core . m_HasTelegunLaser )
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core . m_HasTelegunLaser = true ;
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " Teleport laser enabled " ) ;
2018-02-14 15:27:26 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( ( ( m_TileIndex = = TILE_TELE_LASER_DISABLE ) | | ( m_TileFIndex = = TILE_TELE_LASER_DISABLE ) ) & & m_Core . m_HasTelegunLaser )
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core . m_HasTelegunLaser = false ;
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " Teleport laser disabled " ) ;
2018-02-14 15:27:26 +00:00
}
2014-12-29 14:54:55 +00:00
// stopper
2020-09-26 19:41:58 +00:00
if ( m_Core . m_Vel . y > 0 & & ( m_MoveRestrictions & CANTMOVE_DOWN ) )
2010-10-08 13:33:42 +00:00
{
m_Core . m_Jumped = 0 ;
2013-08-23 23:03:45 +00:00
m_Core . m_JumpedTotal = 0 ;
2010-10-08 13:33:42 +00:00
}
2019-10-06 11:54:16 +00:00
m_Core . m_Vel = ClampVel ( m_MoveRestrictions , m_Core . m_Vel ) ;
2013-08-23 23:03:45 +00:00
2010-11-13 13:22:19 +00:00
// handle switch tiles
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_SWITCHOPEN & & Team ( ) ! = TEAM_SUPER & & Collision ( ) - > GetSwitchNumber ( MapIndex ) > 0 )
2010-11-22 20:43:22 +00:00
{
2022-06-30 22:36:32 +00:00
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] = true ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aEndTick [ Team ( ) ] = 0 ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aType [ Team ( ) ] = TILE_SWITCHOPEN ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aLastUpdateTick [ Team ( ) ] = Server ( ) - > Tick ( ) ;
2010-11-22 20:43:22 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_SWITCHTIMEDOPEN & & Team ( ) ! = TEAM_SUPER & & Collision ( ) - > GetSwitchNumber ( MapIndex ) > 0 )
2010-11-22 20:43:22 +00:00
{
2022-06-30 22:36:32 +00:00
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] = true ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aEndTick [ Team ( ) ] = Server ( ) - > Tick ( ) + 1 + Collision ( ) - > GetSwitchDelay ( MapIndex ) * Server ( ) - > TickSpeed ( ) ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aType [ Team ( ) ] = TILE_SWITCHTIMEDOPEN ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aLastUpdateTick [ Team ( ) ] = Server ( ) - > Tick ( ) ;
2010-11-22 20:43:22 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_SWITCHTIMEDCLOSE & & Team ( ) ! = TEAM_SUPER & & Collision ( ) - > GetSwitchNumber ( MapIndex ) > 0 )
2010-11-22 20:43:22 +00:00
{
2022-06-30 22:36:32 +00:00
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] = false ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aEndTick [ Team ( ) ] = Server ( ) - > Tick ( ) + 1 + Collision ( ) - > GetSwitchDelay ( MapIndex ) * Server ( ) - > TickSpeed ( ) ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aType [ Team ( ) ] = TILE_SWITCHTIMEDCLOSE ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aLastUpdateTick [ Team ( ) ] = Server ( ) - > Tick ( ) ;
2010-11-22 20:43:22 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_SWITCHCLOSE & & Team ( ) ! = TEAM_SUPER & & Collision ( ) - > GetSwitchNumber ( MapIndex ) > 0 )
2010-11-22 20:43:22 +00:00
{
2022-06-30 22:36:32 +00:00
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] = false ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aEndTick [ Team ( ) ] = 0 ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aType [ Team ( ) ] = TILE_SWITCHCLOSE ;
Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aLastUpdateTick [ Team ( ) ] = Server ( ) - > Tick ( ) ;
2010-11-22 20:43:22 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_FREEZE & & Team ( ) ! = TEAM_SUPER )
2011-01-25 09:34:14 +00:00
{
2022-06-30 22:36:32 +00:00
if ( Collision ( ) - > GetSwitchNumber ( MapIndex ) = = 0 | | Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] )
2022-03-27 16:18:53 +00:00
{
2022-05-28 18:24:24 +00:00
Freeze ( Collision ( ) - > GetSwitchDelay ( MapIndex ) ) ;
2022-03-27 16:18:53 +00:00
}
2011-01-25 09:34:14 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_DFREEZE & & Team ( ) ! = TEAM_SUPER )
2011-01-25 09:34:14 +00:00
{
2022-06-30 22:36:32 +00:00
if ( Collision ( ) - > GetSwitchNumber ( MapIndex ) = = 0 | | Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] )
2022-06-30 17:29:58 +00:00
m_Core . m_DeepFrozen = true ;
2011-01-25 09:34:14 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_DUNFREEZE & & Team ( ) ! = TEAM_SUPER )
2011-01-25 09:34:14 +00:00
{
2022-06-30 22:36:32 +00:00
if ( Collision ( ) - > GetSwitchNumber ( MapIndex ) = = 0 | | Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] )
2022-06-30 17:29:58 +00:00
m_Core . m_DeepFrozen = false ;
2011-01-25 09:34:14 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_LFREEZE & & Team ( ) ! = TEAM_SUPER )
2022-01-07 15:53:40 +00:00
{
2022-06-30 22:36:32 +00:00
if ( Collision ( ) - > GetSwitchNumber ( MapIndex ) = = 0 | | Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] )
2022-01-08 11:30:51 +00:00
{
2022-01-07 15:53:40 +00:00
m_Core . m_LiveFrozen = true ;
}
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_LUNFREEZE & & Team ( ) ! = TEAM_SUPER )
2022-01-07 15:53:40 +00:00
{
2022-06-30 22:36:32 +00:00
if ( Collision ( ) - > GetSwitchNumber ( MapIndex ) = = 0 | | Switchers ( ) [ Collision ( ) - > GetSwitchNumber ( MapIndex ) ] . m_aStatus [ Team ( ) ] )
2022-01-07 15:53:40 +00:00
{
m_Core . m_LiveFrozen = false ;
}
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_ENABLE & & m_Core . m_HammerHitDisabled & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_HAMMER )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can hammer hit others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_HammerHitDisabled = false ;
2011-07-25 20:16:20 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_DISABLE & & ! ( m_Core . m_HammerHitDisabled ) & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_HAMMER )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can't hammer hit others " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_HammerHitDisabled = true ;
2011-07-25 20:16:20 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_ENABLE & & m_Core . m_ShotgunHitDisabled & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_SHOTGUN )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can shoot others with shotgun " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_ShotgunHitDisabled = false ;
2011-07-25 20:16:20 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_DISABLE & & ! ( m_Core . m_ShotgunHitDisabled ) & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_SHOTGUN )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can't shoot others with shotgun " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_ShotgunHitDisabled = true ;
2011-07-25 20:16:20 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_ENABLE & & m_Core . m_GrenadeHitDisabled & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_GRENADE )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can shoot others with grenade " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_GrenadeHitDisabled = false ;
2011-07-25 20:16:20 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_DISABLE & & ! ( m_Core . m_GrenadeHitDisabled ) & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_GRENADE )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can't shoot others with grenade " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_GrenadeHitDisabled = true ;
2011-07-25 20:16:20 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_ENABLE & & m_Core . m_LaserHitDisabled & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_LASER )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can shoot others with laser " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_LaserHitDisabled = false ;
2011-07-25 20:16:20 +00:00
}
2022-07-08 13:31:58 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_HIT_DISABLE & & ! ( m_Core . m_LaserHitDisabled ) & & Collision ( ) - > GetSwitchDelay ( MapIndex ) = = WEAPON_LASER )
2011-07-25 20:16:20 +00:00
{
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , " You can't shoot others with laser " ) ;
2022-07-08 13:31:58 +00:00
m_Core . m_LaserHitDisabled = true ;
2011-07-25 20:16:20 +00:00
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_JUMP )
2013-08-23 23:03:45 +00:00
{
2022-05-28 18:24:24 +00:00
int NewJumps = Collision ( ) - > GetSwitchDelay ( MapIndex ) ;
2022-01-31 14:43:49 +00:00
if ( NewJumps = = 255 )
{
NewJumps = - 1 ;
}
2013-08-23 23:03:45 +00:00
2022-01-31 14:43:03 +00:00
if ( NewJumps ! = m_Core . m_Jumps )
2013-08-23 23:03:45 +00:00
{
2022-06-29 12:46:23 +00:00
char aBuf [ 256 ] ;
if ( NewJumps = = - 1 )
2023-01-28 13:18:02 +00:00
str_copy ( aBuf , " You only have your ground jump now " ) ;
2022-06-29 12:46:23 +00:00
else if ( NewJumps = = 1 )
str_format ( aBuf , sizeof ( aBuf ) , " You can jump %d time " , NewJumps ) ;
else
str_format ( aBuf , sizeof ( aBuf ) , " You can jump %d times " , NewJumps ) ;
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , aBuf ) ;
2022-01-31 14:43:03 +00:00
m_Core . m_Jumps = NewJumps ;
2013-08-23 23:03:45 +00:00
}
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_ADD_TIME & & ! m_LastPenalty )
2014-02-09 22:31:29 +00:00
{
2022-05-28 18:24:24 +00:00
int min = Collision ( ) - > GetSwitchDelay ( MapIndex ) ;
int sec = Collision ( ) - > GetSwitchNumber ( MapIndex ) ;
2014-02-09 23:17:00 +00:00
int Team = Teams ( ) - > m_Core . Team ( m_Core . m_Id ) ;
2014-02-09 22:31:29 +00:00
m_StartTime - = ( min * 60 + sec ) * Server ( ) - > TickSpeed ( ) ;
2014-02-09 23:17:00 +00:00
2022-02-19 14:20:32 +00:00
if ( ( g_Config . m_SvTeam = = SV_TEAM_FORCED_SOLO | | Team ! = TEAM_FLOCK ) & & Team ! = TEAM_SUPER )
2014-02-09 23:17:00 +00:00
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2014-02-09 23:17:00 +00:00
{
2014-05-18 23:57:52 +00:00
if ( Teams ( ) - > m_Core . Team ( i ) = = Team & & i ! = m_Core . m_Id & & GameServer ( ) - > m_apPlayers [ i ] )
2014-02-09 23:17:00 +00:00
{
2020-09-26 19:41:58 +00:00
CCharacter * pChar = GameServer ( ) - > m_apPlayers [ i ] - > GetCharacter ( ) ;
2014-02-09 23:17:00 +00:00
2020-09-26 19:41:58 +00:00
if ( pChar )
2014-02-09 23:17:00 +00:00
pChar - > m_StartTime = m_StartTime ;
}
}
}
2014-02-09 22:31:29 +00:00
m_LastPenalty = true ;
}
2022-05-28 18:24:24 +00:00
else if ( Collision ( ) - > GetSwitchType ( MapIndex ) = = TILE_SUBTRACT_TIME & & ! m_LastBonus )
2015-03-10 21:57:40 +00:00
{
2022-05-28 18:24:24 +00:00
int min = Collision ( ) - > GetSwitchDelay ( MapIndex ) ;
int sec = Collision ( ) - > GetSwitchNumber ( MapIndex ) ;
2015-03-10 21:57:40 +00:00
int Team = Teams ( ) - > m_Core . Team ( m_Core . m_Id ) ;
m_StartTime + = ( min * 60 + sec ) * Server ( ) - > TickSpeed ( ) ;
2020-09-26 19:41:58 +00:00
if ( m_StartTime > Server ( ) - > Tick ( ) )
2015-03-10 21:57:40 +00:00
m_StartTime = Server ( ) - > Tick ( ) ;
2022-02-19 14:20:32 +00:00
if ( ( g_Config . m_SvTeam = = SV_TEAM_FORCED_SOLO | | Team ! = TEAM_FLOCK ) & & Team ! = TEAM_SUPER )
2015-03-10 21:57:40 +00:00
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2015-03-10 21:57:40 +00:00
{
if ( Teams ( ) - > m_Core . Team ( i ) = = Team & & i ! = m_Core . m_Id & & GameServer ( ) - > m_apPlayers [ i ] )
{
2020-09-26 19:41:58 +00:00
CCharacter * pChar = GameServer ( ) - > m_apPlayers [ i ] - > GetCharacter ( ) ;
2015-03-10 21:57:40 +00:00
2020-09-26 19:41:58 +00:00
if ( pChar )
2015-03-10 21:57:40 +00:00
pChar - > m_StartTime = m_StartTime ;
}
}
}
m_LastBonus = true ;
}
2014-02-09 22:31:29 +00:00
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > GetSwitchType ( MapIndex ) ! = TILE_ADD_TIME )
2014-02-09 22:31:29 +00:00
{
m_LastPenalty = false ;
}
2013-08-23 23:03:45 +00:00
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > GetSwitchType ( MapIndex ) ! = TILE_SUBTRACT_TIME )
2015-03-10 21:57:40 +00:00
{
m_LastBonus = false ;
}
2022-05-28 18:24:24 +00:00
int z = Collision ( ) - > IsTeleport ( MapIndex ) ;
2022-01-22 12:54:25 +00:00
if ( ! g_Config . m_SvOldTeleportHook & & ! g_Config . m_SvOldTeleportWeapons & & z & & ! ( * m_pTeleOuts ) [ z - 1 ] . empty ( ) )
2010-10-08 13:33:42 +00:00
{
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Super )
2014-01-13 16:00:49 +00:00
return ;
2023-09-05 22:07:40 +00:00
int TeleOut = GameWorld ( ) - > m_Core . RandomOr0 ( ( * m_pTeleOuts ) [ z - 1 ] . size ( ) ) ;
2021-01-12 23:12:08 +00:00
m_Core . m_Pos = ( * m_pTeleOuts ) [ z - 1 ] [ TeleOut ] ;
2014-04-04 22:35:18 +00:00
if ( ! g_Config . m_SvTeleportHoldHook )
{
2021-04-08 14:36:43 +00:00
ResetHook ( ) ;
2014-04-04 22:35:18 +00:00
}
2015-08-22 17:24:10 +00:00
if ( g_Config . m_SvTeleportLoseWeapons )
2021-01-12 22:10:02 +00:00
ResetPickups ( ) ;
2010-10-10 23:46:13 +00:00
return ;
2010-10-08 13:33:42 +00:00
}
2022-05-28 18:24:24 +00:00
int evilz = Collision ( ) - > IsEvilTeleport ( MapIndex ) ;
2022-01-22 12:54:25 +00:00
if ( evilz & & ! ( * m_pTeleOuts ) [ evilz - 1 ] . empty ( ) )
2010-10-08 13:33:42 +00:00
{
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Super )
2014-01-13 16:00:49 +00:00
return ;
2023-09-05 22:07:40 +00:00
int TeleOut = GameWorld ( ) - > m_Core . RandomOr0 ( ( * m_pTeleOuts ) [ evilz - 1 ] . size ( ) ) ;
2021-01-12 23:12:08 +00:00
m_Core . m_Pos = ( * m_pTeleOuts ) [ evilz - 1 ] [ TeleOut ] ;
2020-09-26 19:41:58 +00:00
if ( ! g_Config . m_SvOldTeleportHook & & ! g_Config . m_SvOldTeleportWeapons )
2013-07-22 15:37:14 +00:00
{
2020-09-26 19:41:58 +00:00
m_Core . m_Vel = vec2 ( 0 , 0 ) ;
2014-04-04 22:35:18 +00:00
if ( ! g_Config . m_SvTeleportHoldHook )
{
2021-04-08 14:36:43 +00:00
ResetHook ( ) ;
2021-04-10 15:29:20 +00:00
GameWorld ( ) - > ReleaseHooked ( GetPlayer ( ) - > GetCID ( ) ) ;
2014-04-04 22:35:18 +00:00
}
2015-08-22 17:24:10 +00:00
if ( g_Config . m_SvTeleportLoseWeapons )
{
2021-01-12 22:10:02 +00:00
ResetPickups ( ) ;
2015-08-22 17:24:10 +00:00
}
2013-07-22 15:37:14 +00:00
}
2010-10-10 23:46:13 +00:00
return ;
2010-10-08 13:33:42 +00:00
}
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > IsCheckEvilTeleport ( MapIndex ) )
2014-02-01 21:20:41 +00:00
{
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Super )
2014-02-01 21:20:41 +00:00
return ;
// first check if there is a TeleCheckOut for the current recorded checkpoint, if not check previous checkpoints
2020-09-26 19:41:58 +00:00
for ( int k = m_TeleCheckpoint - 1 ; k > = 0 ; k - - )
2014-02-01 21:20:41 +00:00
{
2022-01-22 12:54:25 +00:00
if ( ! ( * m_pTeleCheckOuts ) [ k ] . empty ( ) )
2014-02-01 21:20:41 +00:00
{
2023-09-05 22:07:40 +00:00
int TeleOut = GameWorld ( ) - > m_Core . RandomOr0 ( ( * m_pTeleCheckOuts ) [ k ] . size ( ) ) ;
2021-01-12 23:12:08 +00:00
m_Core . m_Pos = ( * m_pTeleCheckOuts ) [ k ] [ TeleOut ] ;
2020-09-26 19:41:58 +00:00
m_Core . m_Vel = vec2 ( 0 , 0 ) ;
2017-06-15 13:49:07 +00:00
2017-06-15 14:07:27 +00:00
if ( ! g_Config . m_SvTeleportHoldHook )
2017-06-15 13:49:07 +00:00
{
2021-04-08 14:36:43 +00:00
ResetHook ( ) ;
2021-04-10 15:29:20 +00:00
GameWorld ( ) - > ReleaseHooked ( GetPlayer ( ) - > GetCID ( ) ) ;
2017-06-15 13:49:07 +00:00
}
2014-02-01 21:20:41 +00:00
return ;
}
}
// if no checkpointout have been found (or if there no recorded checkpoint), teleport to start
vec2 SpawnPos ;
2022-02-05 23:01:47 +00:00
if ( GameServer ( ) - > m_pController - > CanSpawn ( m_pPlayer - > GetTeam ( ) , & SpawnPos , GameServer ( ) - > GetDDRaceTeam ( GetPlayer ( ) - > GetCID ( ) ) ) )
2014-02-01 21:20:41 +00:00
{
m_Core . m_Pos = SpawnPos ;
2020-09-26 19:41:58 +00:00
m_Core . m_Vel = vec2 ( 0 , 0 ) ;
2017-06-15 13:49:07 +00:00
2017-06-15 14:07:27 +00:00
if ( ! g_Config . m_SvTeleportHoldHook )
2017-06-15 13:49:07 +00:00
{
2021-04-08 14:36:43 +00:00
ResetHook ( ) ;
2021-04-10 15:29:20 +00:00
GameWorld ( ) - > ReleaseHooked ( GetPlayer ( ) - > GetCID ( ) ) ;
2017-06-15 13:49:07 +00:00
}
2014-02-01 21:20:41 +00:00
}
return ;
}
2022-05-28 18:24:24 +00:00
if ( Collision ( ) - > IsCheckTeleport ( MapIndex ) )
2011-05-17 23:12:39 +00:00
{
2022-06-30 17:29:58 +00:00
if ( m_Core . m_Super )
2014-01-13 16:00:49 +00:00
return ;
2011-09-02 22:42:01 +00:00
// first check if there is a TeleCheckOut for the current recorded checkpoint, if not check previous checkpoints
2020-09-26 19:41:58 +00:00
for ( int k = m_TeleCheckpoint - 1 ; k > = 0 ; k - - )
2011-05-17 23:12:39 +00:00
{
2022-01-22 12:54:25 +00:00
if ( ! ( * m_pTeleCheckOuts ) [ k ] . empty ( ) )
2011-09-02 22:42:01 +00:00
{
2023-09-05 22:07:40 +00:00
int TeleOut = GameWorld ( ) - > m_Core . RandomOr0 ( ( * m_pTeleCheckOuts ) [ k ] . size ( ) ) ;
2021-01-12 23:12:08 +00:00
m_Core . m_Pos = ( * m_pTeleCheckOuts ) [ k ] [ TeleOut ] ;
2017-06-15 13:49:07 +00:00
2017-06-15 14:07:27 +00:00
if ( ! g_Config . m_SvTeleportHoldHook )
2017-06-15 13:49:07 +00:00
{
2021-04-08 14:36:43 +00:00
ResetHook ( ) ;
2017-06-15 13:49:07 +00:00
}
2011-09-02 22:42:01 +00:00
return ;
}
2011-05-17 23:12:39 +00:00
}
2011-09-02 22:42:01 +00:00
// if no checkpointout have been found (or if there no recorded checkpoint), teleport to start
2011-05-17 23:12:39 +00:00
vec2 SpawnPos ;
2022-02-05 23:01:47 +00:00
if ( GameServer ( ) - > m_pController - > CanSpawn ( m_pPlayer - > GetTeam ( ) , & SpawnPos , GameServer ( ) - > GetDDRaceTeam ( GetPlayer ( ) - > GetCID ( ) ) ) )
2011-05-17 23:12:39 +00:00
{
m_Core . m_Pos = SpawnPos ;
2017-06-15 13:49:07 +00:00
2017-06-15 14:07:27 +00:00
if ( ! g_Config . m_SvTeleportHoldHook )
2017-06-15 13:49:07 +00:00
{
2021-04-08 14:36:43 +00:00
ResetHook ( ) ;
2017-06-15 13:49:07 +00:00
}
2011-05-17 23:12:39 +00:00
}
2011-09-02 22:42:01 +00:00
return ;
2011-05-17 23:12:39 +00:00
}
2010-10-08 13:33:42 +00:00
}
2014-03-12 23:49:07 +00:00
void CCharacter : : HandleTuneLayer ( )
{
2014-04-13 14:49:58 +00:00
m_TuneZoneOld = m_TuneZone ;
2022-05-28 18:24:24 +00:00
int CurrentIndex = Collision ( ) - > GetMapIndex ( m_Pos ) ;
m_TuneZone = Collision ( ) - > IsTune ( CurrentIndex ) ;
2014-04-13 14:49:58 +00:00
if ( m_TuneZone )
2023-10-03 18:18:06 +00:00
m_Core . m_Tuning = TuningList ( ) [ m_TuneZone ] ; // throw tunings from specific zone into gamecore
2014-03-12 23:49:07 +00:00
else
2023-10-03 18:18:06 +00:00
m_Core . m_Tuning = * Tuning ( ) ;
2014-04-13 14:49:58 +00:00
2020-09-26 19:41:58 +00:00
if ( m_TuneZone ! = m_TuneZoneOld ) // don't send tunigs all the time
2014-03-12 23:49:07 +00:00
{
2014-04-18 12:27:58 +00:00
// send zone msgs
SendZoneMsgs ( ) ;
}
}
2014-04-13 23:34:50 +00:00
2014-04-18 12:27:58 +00:00
void CCharacter : : SendZoneMsgs ( )
{
// send zone leave msg
2017-07-26 01:58:00 +00:00
// (m_TuneZoneOld >= 0: avoid zone leave msgs on spawn)
2022-05-14 09:18:06 +00:00
if ( m_TuneZoneOld > = 0 & & GameServer ( ) - > m_aaZoneLeaveMsg [ m_TuneZoneOld ] [ 0 ] )
2014-04-18 12:27:58 +00:00
{
2017-07-26 01:58:00 +00:00
const char * pCur = GameServer ( ) - > m_aaZoneLeaveMsg [ m_TuneZoneOld ] ;
const char * pPos ;
2020-09-26 19:41:58 +00:00
while ( ( pPos = str_find ( pCur , " \\ n " ) ) )
2014-04-13 17:27:08 +00:00
{
2014-04-18 12:27:58 +00:00
char aBuf [ 256 ] ;
2017-07-26 01:58:00 +00:00
str_copy ( aBuf , pCur , pPos - pCur + 1 ) ;
aBuf [ pPos - pCur + 1 ] = ' \0 ' ;
pCur = pPos + 2 ;
2014-04-18 12:27:58 +00:00
GameServer ( ) - > SendChatTarget ( m_pPlayer - > GetCID ( ) , aBuf ) ;
2014-04-13 17:27:08 +00:00
}
2017-07-26 01:58:00 +00:00
GameServer ( ) - > SendChatTarget ( m_pPlayer - > GetCID ( ) , pCur ) ;
2014-04-18 12:27:58 +00:00
}
// send zone enter msg
2022-05-14 09:18:06 +00:00
if ( GameServer ( ) - > m_aaZoneEnterMsg [ m_TuneZone ] [ 0 ] )
2014-04-18 12:27:58 +00:00
{
2020-09-26 19:41:58 +00:00
const char * pCur = GameServer ( ) - > m_aaZoneEnterMsg [ m_TuneZone ] ;
const char * pPos ;
while ( ( pPos = str_find ( pCur , " \\ n " ) ) )
2014-04-13 17:27:08 +00:00
{
2014-04-18 12:27:58 +00:00
char aBuf [ 256 ] ;
2017-07-26 01:58:00 +00:00
str_copy ( aBuf , pCur , pPos - pCur + 1 ) ;
aBuf [ pPos - pCur + 1 ] = ' \0 ' ;
pCur = pPos + 2 ;
2014-04-18 12:27:58 +00:00
GameServer ( ) - > SendChatTarget ( m_pPlayer - > GetCID ( ) , aBuf ) ;
2014-04-13 17:27:08 +00:00
}
2017-07-26 01:58:00 +00:00
GameServer ( ) - > SendChatTarget ( m_pPlayer - > GetCID ( ) , pCur ) ;
2014-03-12 23:49:07 +00:00
}
}
2020-05-13 20:27:49 +00:00
IAntibot * CCharacter : : Antibot ( )
2020-03-11 00:58:50 +00:00
{
return GameServer ( ) - > Antibot ( ) ;
}
2021-01-12 23:29:20 +00:00
void CCharacter : : SetTeams ( CGameTeams * pTeams )
{
m_pTeams = pTeams ;
m_Core . SetTeamsCore ( & m_pTeams - > m_Core ) ;
}
2020-06-24 19:19:46 +00:00
void CCharacter : : SetRescue ( )
{
2021-02-16 17:15:50 +00:00
m_RescueTee . Save ( this ) ;
2020-06-24 19:19:46 +00:00
m_SetSavePos = true ;
}
2011-01-29 00:59:50 +00:00
void CCharacter : : DDRaceTick ( )
2010-08-24 14:32:46 +00:00
{
2016-08-27 15:06:52 +00:00
mem_copy ( & m_Input , & m_SavedInput , sizeof ( m_Input ) ) ;
2023-01-05 19:24:06 +00:00
m_Armor = clamp ( 10 - ( m_FreezeTime / 15 ) , 0 , 10 ) ;
2011-01-29 00:59:50 +00:00
if ( m_Input . m_Direction ! = 0 | | m_Input . m_Jump ! = 0 )
m_LastMove = Server ( ) - > Tick ( ) ;
2010-08-24 14:32:46 +00:00
2022-06-30 17:29:58 +00:00
if ( m_Core . m_LiveFrozen & & ! m_Core . m_Super )
2022-01-07 15:53:40 +00:00
{
m_Input . m_Direction = 0 ;
m_Input . m_Jump = 0 ;
// Hook is possible in live freeze
}
2023-01-05 19:24:06 +00:00
if ( m_FreezeTime > 0 )
2010-05-29 07:25:38 +00:00
{
2023-01-05 19:24:06 +00:00
if ( m_FreezeTime % Server ( ) - > TickSpeed ( ) = = Server ( ) - > TickSpeed ( ) - 1 )
2010-06-09 16:24:38 +00:00
{
2022-06-25 09:16:59 +00:00
GameServer ( ) - > CreateDamageInd ( m_Pos , 0 , ( m_FreezeTime + 1 ) / Server ( ) - > TickSpeed ( ) , TeamMask ( ) & GameServer ( ) - > ClientsMaskExcludeClientVersionAndHigher ( VERSION_DDNET_NEW_HUD ) ) ;
2011-01-29 00:59:50 +00:00
}
2023-01-05 19:24:06 +00:00
m_FreezeTime - - ;
2011-01-29 00:59:50 +00:00
m_Input . m_Direction = 0 ;
m_Input . m_Jump = 0 ;
m_Input . m_Hook = 0 ;
2020-09-26 19:41:58 +00:00
if ( m_FreezeTime = = 1 )
2011-01-29 00:59:50 +00:00
UnFreeze ( ) ;
2008-09-23 07:43:41 +00:00
}
2015-07-09 00:08:14 +00:00
2014-03-12 23:49:07 +00:00
HandleTuneLayer ( ) ; // need this before coretick
2015-04-16 15:28:03 +00:00
2022-03-29 21:24:39 +00:00
// check if the tee is in any type of freeze
2022-05-28 18:24:24 +00:00
int Index = Collision ( ) - > GetPureMapIndex ( m_Pos ) ;
2022-03-29 21:24:39 +00:00
const int aTiles [ ] = {
2022-05-28 18:24:24 +00:00
Collision ( ) - > GetTileIndex ( Index ) ,
Collision ( ) - > GetFTileIndex ( Index ) ,
Collision ( ) - > GetSwitchType ( Index ) } ;
2022-03-29 21:24:39 +00:00
m_Core . m_IsInFreeze = false ;
for ( const int Tile : aTiles )
{
if ( Tile = = TILE_FREEZE | | Tile = = TILE_DFREEZE | | Tile = = TILE_LFREEZE )
{
m_Core . m_IsInFreeze = true ;
break ;
}
}
2023-05-06 20:32:36 +00:00
// check for nearby health pickups (also freeze)
bool InHealthPickup = false ;
if ( ! m_Core . m_IsInFreeze )
{
CEntity * apEnts [ 9 ] ;
int Num = GameWorld ( ) - > FindEntities ( m_Pos , GetProximityRadius ( ) + CPickup : : ms_CollisionExtraSize , apEnts , std : : size ( apEnts ) , CGameWorld : : ENTTYPE_PICKUP ) ;
for ( int i = 0 ; i < Num ; + + i )
{
CPickup * pPickup = static_cast < CPickup * > ( apEnts [ i ] ) ;
if ( pPickup - > Type ( ) = = POWERUP_HEALTH )
{
// This uses a separate variable InHealthPickup instead of setting m_Core.m_IsInFreeze
// as the latter causes freezebars to flicker when standing in the freeze range of a
// health pickup. When the same code for client prediction is added, the freezebars
// still flicker, but only when standing at the edge of the health pickup's freeze range.
InHealthPickup = true ;
break ;
}
}
}
2015-04-16 15:28:03 +00:00
// look for save position for rescue feature
2022-02-19 14:20:32 +00:00
if ( g_Config . m_SvRescue | | ( ( g_Config . m_SvTeam = = SV_TEAM_FORCED_SOLO | | Team ( ) > TEAM_FLOCK ) & & Team ( ) > = TEAM_FLOCK & & Team ( ) < TEAM_SUPER ) )
2020-09-26 19:41:58 +00:00
{
2023-05-06 20:32:36 +00:00
if ( ! m_Core . m_IsInFreeze & & IsGrounded ( ) & & ! m_Core . m_DeepFrozen & & ! InHealthPickup )
2021-01-26 13:44:01 +00:00
{
2022-03-29 21:24:39 +00:00
SetRescue ( ) ;
2021-01-26 13:44:01 +00:00
}
2015-04-16 15:28:03 +00:00
}
2011-01-29 00:59:50 +00:00
m_Core . m_Id = GetPlayer ( ) - > GetCID ( ) ;
2008-07-06 11:21:21 +00:00
}
2011-01-29 23:58:47 +00:00
void CCharacter : : DDRacePostCoreTick ( )
{
2013-03-18 11:58:29 +00:00
m_Time = ( float ) ( Server ( ) - > Tick ( ) - m_StartTime ) / ( ( float ) Server ( ) - > TickSpeed ( ) ) ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_EndlessHook | | ( m_Core . m_Super & & g_Config . m_SvEndlessSuperHook ) )
2014-06-21 22:50:11 +00:00
m_Core . m_HookTick = 0 ;
2011-01-29 23:58:47 +00:00
2019-07-31 19:08:36 +00:00
m_FrozenLastTick = false ;
2022-06-30 17:29:58 +00:00
if ( m_Core . m_DeepFrozen & & ! m_Core . m_Super )
2014-06-21 22:50:11 +00:00
Freeze ( ) ;
2011-01-29 23:58:47 +00:00
2022-05-20 19:37:05 +00:00
// following jump rules can be overridden by tiles, like Refill Jumps, Stopper and Wall Jump
2022-05-16 21:17:19 +00:00
if ( m_Core . m_Jumps = = - 1 )
{
// The player has only one ground jump, so his feet are always dark
2022-01-31 14:43:49 +00:00
m_Core . m_Jumped | = 2 ;
2022-05-16 21:17:19 +00:00
}
else if ( m_Core . m_Jumps = = 0 )
{
// The player has no jumps at all, so his feet are always dark
2022-01-31 14:43:49 +00:00
m_Core . m_Jumped | = 2 ;
2022-05-16 21:17:19 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( m_Core . m_Jumps = = 1 & & m_Core . m_Jumped > 0 )
2022-05-16 21:17:19 +00:00
{
// If the player has only one jump, each jump is the last one
m_Core . m_Jumped | = 2 ;
}
2020-09-26 19:41:58 +00:00
else if ( m_Core . m_JumpedTotal < m_Core . m_Jumps - 1 & & m_Core . m_Jumped > 1 )
2022-05-16 21:17:19 +00:00
{
// The player has not yet used up all his jumps, so his feet remain light
2014-06-21 22:50:11 +00:00
m_Core . m_Jumped = 1 ;
2022-05-16 21:17:19 +00:00
}
2013-08-24 00:25:58 +00:00
2022-06-30 17:29:58 +00:00
if ( ( m_Core . m_Super | | m_Core . m_EndlessJump ) & & m_Core . m_Jumped > 1 )
2022-05-16 21:17:19 +00:00
{
// Super players and players with infinite jumps always have light feet
2014-06-21 22:50:11 +00:00
m_Core . m_Jumped = 1 ;
2022-05-16 21:17:19 +00:00
}
2011-01-29 23:58:47 +00:00
2022-05-28 18:24:24 +00:00
int CurrentIndex = Collision ( ) - > GetMapIndex ( m_Pos ) ;
2014-06-21 22:50:11 +00:00
HandleSkippableTiles ( CurrentIndex ) ;
2019-03-28 22:29:34 +00:00
if ( ! m_Alive )
return ;
2011-01-29 23:58:47 +00:00
2014-06-21 22:50:11 +00:00
// handle Anti-Skip tiles
2023-06-28 20:14:51 +00:00
std : : vector < int > vIndices = Collision ( ) - > GetMapIndices ( m_PrevPos , m_Pos ) ;
if ( ! vIndices . empty ( ) )
2019-03-28 22:29:34 +00:00
{
2023-06-28 20:14:51 +00:00
for ( int & Index : vIndices )
2019-03-28 22:29:34 +00:00
{
2020-10-26 14:14:07 +00:00
HandleTiles ( Index ) ;
2019-03-28 22:29:34 +00:00
if ( ! m_Alive )
return ;
}
}
2014-06-21 22:50:11 +00:00
else
{
HandleTiles ( CurrentIndex ) ;
2019-03-28 22:29:34 +00:00
if ( ! m_Alive )
return ;
2014-06-21 22:50:11 +00:00
}
2011-01-29 23:58:47 +00:00
2018-07-15 09:58:12 +00:00
// teleport gun
2020-09-26 19:41:58 +00:00
if ( m_TeleGunTeleport )
2018-07-15 09:58:12 +00:00
{
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateDeath ( m_Pos , m_pPlayer - > GetCID ( ) , TeamMask ( ) ) ;
2018-07-15 09:58:12 +00:00
m_Core . m_Pos = m_TeleGunPos ;
2018-11-02 23:02:20 +00:00
if ( ! m_IsBlueTeleGunTeleport )
m_Core . m_Vel = vec2 ( 0 , 0 ) ;
2022-05-04 12:10:58 +00:00
GameServer ( ) - > CreateDeath ( m_TeleGunPos , m_pPlayer - > GetCID ( ) , TeamMask ( ) ) ;
GameServer ( ) - > CreateSound ( m_TeleGunPos , SOUND_WEAPON_SPAWN , TeamMask ( ) ) ;
2018-07-15 09:58:12 +00:00
m_TeleGunTeleport = false ;
2018-11-02 23:02:20 +00:00
m_IsBlueTeleGunTeleport = false ;
2018-07-15 09:58:12 +00:00
}
2014-06-21 22:50:11 +00:00
HandleBroadcast ( ) ;
2011-01-29 23:58:47 +00:00
}
2011-01-25 09:34:14 +00:00
bool CCharacter : : Freeze ( int Seconds )
2010-08-24 14:32:46 +00:00
{
2023-01-05 19:24:06 +00:00
if ( Seconds < = 0 | | m_Core . m_Super | | m_FreezeTime > Seconds * Server ( ) - > TickSpeed ( ) )
2020-09-26 19:41:58 +00:00
return false ;
2023-01-05 19:24:06 +00:00
if ( m_Core . m_FreezeStart < Server ( ) - > Tick ( ) - Server ( ) - > TickSpeed ( ) )
2010-07-29 05:21:18 +00:00
{
2011-01-25 09:34:14 +00:00
m_Armor = 0 ;
2023-01-05 19:24:06 +00:00
m_FreezeTime = Seconds * Server ( ) - > TickSpeed ( ) ;
2022-05-24 15:26:49 +00:00
m_Core . m_FreezeStart = Server ( ) - > Tick ( ) ;
2010-08-22 02:23:18 +00:00
return true ;
2010-08-24 14:32:46 +00:00
}
return false ;
}
bool CCharacter : : Freeze ( )
{
2011-01-25 09:34:14 +00:00
return Freeze ( g_Config . m_SvFreezeDelay ) ;
2010-08-24 14:32:46 +00:00
}
bool CCharacter : : UnFreeze ( )
{
2020-09-26 19:41:58 +00:00
if ( m_FreezeTime > 0 )
2010-08-22 02:23:18 +00:00
{
2020-09-26 19:41:58 +00:00
m_Armor = 10 ;
2022-03-21 22:50:41 +00:00
if ( ! m_Core . m_aWeapons [ m_Core . m_ActiveWeapon ] . m_Got )
2014-04-14 08:56:14 +00:00
m_Core . m_ActiveWeapon = WEAPON_GUN ;
2010-11-04 23:52:37 +00:00
m_FreezeTime = 0 ;
2022-05-24 15:26:49 +00:00
m_Core . m_FreezeStart = 0 ;
2019-07-31 19:08:36 +00:00
m_FrozenLastTick = true ;
2014-02-19 21:30:34 +00:00
return true ;
2010-08-22 02:23:18 +00:00
}
2010-08-24 14:32:46 +00:00
return false ;
}
2016-10-08 17:42:42 +00:00
void CCharacter : : GiveWeapon ( int Weapon , bool Remove )
{
2020-09-26 19:41:58 +00:00
if ( Weapon = = WEAPON_NINJA )
2016-10-08 17:42:42 +00:00
{
2020-09-26 19:41:58 +00:00
if ( Remove )
2016-10-08 17:42:42 +00:00
RemoveNinja ( ) ;
else
GiveNinja ( ) ;
return ;
}
2017-02-21 16:10:08 +00:00
2020-09-26 19:41:58 +00:00
if ( Remove )
2016-10-08 17:42:42 +00:00
{
2020-09-26 19:41:58 +00:00
if ( GetActiveWeapon ( ) = = Weapon )
2016-10-08 17:42:42 +00:00
SetActiveWeapon ( WEAPON_GUN ) ;
}
else
{
2022-03-21 22:50:41 +00:00
m_Core . m_aWeapons [ Weapon ] . m_Ammo = - 1 ;
2016-10-08 17:42:42 +00:00
}
2022-03-21 22:50:41 +00:00
m_Core . m_aWeapons [ Weapon ] . m_Got = ! Remove ;
2016-10-08 17:42:42 +00:00
}
2010-08-24 14:32:46 +00:00
void CCharacter : : GiveAllWeapons ( )
{
2020-09-26 19:41:58 +00:00
for ( int i = WEAPON_GUN ; i < NUM_WEAPONS - 1 ; i + + )
2014-12-15 19:48:58 +00:00
{
2016-10-08 17:42:42 +00:00
GiveWeapon ( i ) ;
2014-12-15 19:48:58 +00:00
}
2010-08-24 14:32:46 +00:00
}
2010-07-29 05:21:18 +00:00
2021-01-12 22:10:02 +00:00
void CCharacter : : ResetPickups ( )
{
for ( int i = WEAPON_SHOTGUN ; i < NUM_WEAPONS - 1 ; i + + )
{
2022-03-21 22:50:41 +00:00
m_Core . m_aWeapons [ i ] . m_Got = false ;
2021-01-12 22:10:02 +00:00
if ( m_Core . m_ActiveWeapon = = i )
m_Core . m_ActiveWeapon = WEAPON_GUN ;
}
}
2020-12-26 22:09:33 +00:00
void CCharacter : : SetEndlessHook ( bool Enable )
{
2022-06-30 17:29:58 +00:00
if ( m_Core . m_EndlessHook = = Enable )
2020-12-26 22:09:33 +00:00
{
return ;
}
2022-06-29 12:46:23 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , Enable ? " Endless hook has been activated " : " Endless hook has been deactivated " ) ;
2020-12-26 22:09:33 +00:00
m_Core . m_EndlessHook = Enable ;
}
2011-12-29 13:58:39 +00:00
void CCharacter : : Pause ( bool Pause )
{
m_Paused = Pause ;
if ( Pause )
{
GameServer ( ) - > m_World . m_Core . m_apCharacters [ m_pPlayer - > GetCID ( ) ] = 0 ;
GameServer ( ) - > m_World . RemoveEntity ( this ) ;
2014-12-15 19:49:16 +00:00
2023-09-05 21:53:03 +00:00
if ( m_Core . HookedPlayer ( ) ! = - 1 ) // Keeping hook would allow cheats
2014-12-15 19:49:16 +00:00
{
2021-04-08 14:36:43 +00:00
ResetHook ( ) ;
2021-04-10 15:29:20 +00:00
GameWorld ( ) - > ReleaseHooked ( GetPlayer ( ) - > GetCID ( ) ) ;
2014-12-15 19:49:16 +00:00
}
2011-12-29 13:58:39 +00:00
}
else
{
2020-09-26 19:41:58 +00:00
m_Core . m_Vel = vec2 ( 0 , 0 ) ;
2011-12-29 13:58:39 +00:00
GameServer ( ) - > m_World . m_Core . m_apCharacters [ m_pPlayer - > GetCID ( ) ] = & m_Core ;
GameServer ( ) - > m_World . InsertEntity ( this ) ;
}
}
2011-01-29 00:59:50 +00:00
void CCharacter : : DDRaceInit ( )
2008-07-06 11:21:21 +00:00
{
2011-12-29 13:58:39 +00:00
m_Paused = false ;
2011-01-29 00:59:50 +00:00
m_DDRaceState = DDRACE_NONE ;
m_PrevPos = m_Pos ;
2015-04-16 15:28:03 +00:00
m_SetSavePos = false ;
2011-01-29 00:59:50 +00:00
m_LastBroadcast = 0 ;
m_TeamBeforeSuper = 0 ;
m_Core . m_Id = GetPlayer ( ) - > GetCID ( ) ;
2011-05-17 23:12:39 +00:00
m_TeleCheckpoint = 0 ;
2022-06-30 17:29:58 +00:00
m_Core . m_EndlessHook = g_Config . m_SvEndlessDrag ;
if ( g_Config . m_SvHit )
{
2022-07-08 13:31:58 +00:00
m_Core . m_HammerHitDisabled = false ;
m_Core . m_ShotgunHitDisabled = false ;
m_Core . m_GrenadeHitDisabled = false ;
m_Core . m_LaserHitDisabled = false ;
2022-06-30 17:29:58 +00:00
}
else
{
2022-07-08 13:31:58 +00:00
m_Core . m_HammerHitDisabled = true ;
m_Core . m_ShotgunHitDisabled = true ;
m_Core . m_GrenadeHitDisabled = true ;
m_Core . m_LaserHitDisabled = true ;
2022-06-30 17:29:58 +00:00
}
2013-08-23 23:03:45 +00:00
m_Core . m_Jumps = 2 ;
2014-07-16 00:59:39 +00:00
m_FreezeHammer = false ;
2013-11-15 23:44:49 +00:00
int Team = Teams ( ) - > m_Core . Team ( m_Core . m_Id ) ;
if ( Teams ( ) - > TeamLocked ( Team ) )
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2013-11-15 23:44:49 +00:00
{
2014-05-18 23:57:52 +00:00
if ( Teams ( ) - > m_Core . Team ( i ) = = Team & & i ! = m_Core . m_Id & & GameServer ( ) - > m_apPlayers [ i ] )
2013-11-15 23:44:49 +00:00
{
2020-09-26 19:41:58 +00:00
CCharacter * pChar = GameServer ( ) - > m_apPlayers [ i ] - > GetCharacter ( ) ;
2013-11-15 23:44:49 +00:00
2020-09-26 19:41:58 +00:00
if ( pChar )
2013-11-15 23:44:49 +00:00
{
m_DDRaceState = pChar - > m_DDRaceState ;
m_StartTime = pChar - > m_StartTime ;
}
}
}
}
2019-03-20 13:01:29 +00:00
2022-02-19 14:20:32 +00:00
if ( g_Config . m_SvTeam = = SV_TEAM_MANDATORY & & Team = = TEAM_FLOCK )
2019-03-20 13:01:29 +00:00
{
2021-12-21 22:22:26 +00:00
GameServer ( ) - > SendStartWarning ( GetPlayer ( ) - > GetCID ( ) , " Please join a team before you start " ) ;
2019-03-20 13:01:29 +00:00
}
2011-02-14 18:36:30 +00:00
}
2015-04-16 15:28:03 +00:00
void CCharacter : : Rescue ( )
{
2022-06-30 17:29:58 +00:00
if ( m_SetSavePos & & ! m_Core . m_Super )
2020-07-02 12:02:19 +00:00
{
2021-06-23 05:05:49 +00:00
if ( m_LastRescue + ( int64_t ) g_Config . m_SvRescueDelay * Server ( ) - > TickSpeed ( ) > Server ( ) - > Tick ( ) )
2015-06-30 16:46:36 +00:00
{
char aBuf [ 256 ] ;
2021-06-23 05:05:49 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " You have to wait %d seconds until you can rescue yourself " , ( int ) ( ( m_LastRescue + ( int64_t ) g_Config . m_SvRescueDelay * Server ( ) - > TickSpeed ( ) - Server ( ) - > Tick ( ) ) / Server ( ) - > TickSpeed ( ) ) ) ;
2015-06-30 16:46:36 +00:00
GameServer ( ) - > SendChatTarget ( GetPlayer ( ) - > GetCID ( ) , aBuf ) ;
return ;
}
2020-06-01 09:40:11 +00:00
float StartTime = m_StartTime ;
2021-02-16 17:15:50 +00:00
m_RescueTee . Load ( this , Team ( ) ) ;
2020-06-01 09:40:11 +00:00
// Don't load these from saved tee:
m_Core . m_Vel = vec2 ( 0 , 0 ) ;
m_Core . m_HookState = HOOK_IDLE ;
m_StartTime = StartTime ;
2020-07-02 12:02:19 +00:00
m_SavedInput . m_Direction = 0 ;
2020-07-02 14:24:23 +00:00
m_SavedInput . m_Jump = 0 ;
// simulate releasing the fire button
2020-09-26 19:41:58 +00:00
if ( ( m_SavedInput . m_Fire & 1 ) ! = 0 )
2020-07-02 14:24:23 +00:00
m_SavedInput . m_Fire + + ;
m_SavedInput . m_Fire & = INPUT_STATE_MASK ;
m_SavedInput . m_Hook = 0 ;
2020-07-02 12:02:19 +00:00
m_pPlayer - > Pause ( CPlayer : : PAUSE_NONE , true ) ;
2015-04-16 15:28:03 +00:00
}
}
2021-08-14 14:11:57 +00:00
2023-01-24 08:27:29 +00:00
CClientMask CCharacter : : TeamMask ( )
2021-08-14 14:11:57 +00:00
{
return Teams ( ) - > TeamMask ( Team ( ) , - 1 , GetPlayer ( ) - > GetCID ( ) ) ;
}
2022-04-30 08:21:38 +00:00
void CCharacter : : SwapClients ( int Client1 , int Client2 )
{
2023-09-05 21:53:03 +00:00
const int HookedPlayer = m_Core . HookedPlayer ( ) ;
m_Core . SetHookedPlayer ( HookedPlayer = = Client1 ? Client2 : HookedPlayer = = Client2 ? Client1 : HookedPlayer ) ;
2022-05-14 09:18:06 +00:00
}