ddnet/src/game/gamecore.cpp

709 lines
20 KiB
C++
Raw Normal View History

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. */
2010-05-29 07:25:38 +00:00
#include "gamecore.h"
2022-06-16 16:06:35 +00:00
#include "collision.h"
2022-05-29 12:11:29 +00:00
#include "mapitems.h"
2022-06-16 16:06:35 +00:00
#include "teamscore.h"
2007-09-22 18:55:00 +00:00
2010-10-31 17:47:10 +00:00
#include <engine/shared/config.h>
2017-03-21 10:24:44 +00:00
const char *CTuningParams::ms_apNames[] =
{
#define MACRO_TUNING_PARAM(Name, ScriptName, Value, Description) #ScriptName,
#include "tuning.h"
#undef MACRO_TUNING_PARAM
};
2010-05-29 07:25:38 +00:00
bool CTuningParams::Set(int Index, float Value)
{
2010-05-29 07:25:38 +00:00
if(Index < 0 || Index >= Num())
return false;
2010-05-29 07:25:38 +00:00
((CTuneParam *)this)[Index] = Value;
return true;
}
bool CTuningParams::Get(int Index, float *pValue) const
{
2010-05-29 07:25:38 +00:00
if(Index < 0 || Index >= Num())
return false;
2010-05-29 07:25:38 +00:00
*pValue = (float)((CTuneParam *)this)[Index];
return true;
}
2010-05-29 07:25:38 +00:00
bool CTuningParams::Set(const char *pName, float Value)
{
2010-05-29 07:25:38 +00:00
for(int i = 0; i < Num(); i++)
if(str_comp_nocase(pName, Name(i)) == 0)
2010-05-29 07:25:38 +00:00
return Set(i, Value);
return false;
}
bool CTuningParams::Get(const char *pName, float *pValue) const
{
2010-05-29 07:25:38 +00:00
for(int i = 0; i < Num(); i++)
if(str_comp_nocase(pName, Name(i)) == 0)
2010-05-29 07:25:38 +00:00
return Get(i, pValue);
return false;
}
int CTuningParams::PossibleTunings(const char *pStr, IConsole::FPossibleCallback pfnCallback, void *pUser)
{
int Index = 0;
for(int i = 0; i < Num(); i++)
{
if(str_find_nocase(Name(i), pStr))
{
pfnCallback(Index, Name(i), pUser);
Index++;
}
}
return Index;
}
2022-09-03 07:59:39 +00:00
float CTuningParams::GetWeaponFireDelay(int Weapon) const
{
switch(Weapon)
{
case WEAPON_HAMMER: return (float)m_HammerHitFireDelay / 1000.0f;
case WEAPON_GUN: return (float)m_GunFireDelay / 1000.0f;
case WEAPON_SHOTGUN: return (float)m_ShotgunFireDelay / 1000.0f;
case WEAPON_GRENADE: return (float)m_GrenadeFireDelay / 1000.0f;
case WEAPON_LASER: return (float)m_LaserFireDelay / 1000.0f;
case WEAPON_NINJA: return (float)m_NinjaFireDelay / 1000.0f;
default: dbg_assert(false, "invalid weapon"); return 0.0f; // this value should not be reached
}
}
2010-05-29 07:25:38 +00:00
float VelocityRamp(float Value, float Start, float Range, float Curvature)
{
2010-05-29 07:25:38 +00:00
if(Value < Start)
return 1.0f;
return 1.0f / powf(Curvature, (Value - Start) / Range);
}
void CCharacterCore::Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore *pTeams, std::map<int, std::vector<vec2>> *pTeleOuts)
{
2010-05-29 07:25:38 +00:00
m_pWorld = pWorld;
m_pCollision = pCollision;
2013-07-18 22:27:17 +00:00
m_pTeleOuts = pTeleOuts;
m_pTeams = pTeams;
m_Id = -1;
2021-05-12 16:57:50 +00:00
// fail safe, if core's tuning didn't get updated at all, just fallback to world tuning.
m_Tuning = m_pWorld->m_aTuning[g_Config.m_ClDummy];
Reset CCharacterCore at start Hopefully fixes these by initializing m_Pos: src/game/collision.cpp:345:10: runtime error: -nan is outside the range of representable values of type 'int' #0 0x55e85a8f0967 in CCollision::IntersectLineTeleHook(vector2_base<float>, vector2_base<float>, vector2_base<float>*, vector2_base<float>*, int*) /media/ddnet/src/game/collision.cpp:345:10 #1 0x55e85a90767b in CCharacterCore::Tick(bool) /media/ddnet/src/game/gamecore.cpp:255:27 #2 0x55e85af8e477 in CCharacter::Tick() /media/ddnet/src/game/client/prediction/entities/character.cpp:562:9 #3 0x55e85afc867f in CGameWorld::Tick() /media/ddnet/src/game/client/prediction/gameworld.cpp:193:10 #4 0x55e85af500b8 in CGameClient::UpdatePrediction() /media/ddnet/src/game/client/gameclient.cpp:2279:16 #5 0x55e85af48b9b in CGameClient::OnNewSnapshot() /media/ddnet/src/game/client/gameclient.cpp:1675:3 #6 0x55e85a9fdf8c in CClient::Update() /media/ddnet/src/engine/client/client.cpp:2767:22 #7 0x55e85aa0cefe in CClient::Run() /media/ddnet/src/engine/client/client.cpp:3237:4 #8 0x55e85aa2eb2e in main /media/ddnet/src/engine/client/client.cpp:4341:11 #9 0x7feedbc65151 in __libc_start_main (/usr/lib/libc.so.6+0x28151) #10 0x55e85a77be0d in _start (/media/ddnet/DDNet+0x705e0d) src/base/math.h:22:40: runtime error: -nan is outside the range of representable values of type 'int' #0 0x55e85a900c2f in round_to_int(float) /media/ddnet/src/base/math.h:22:40 #1 0x55e85a90cac1 in CCharacterCore::Write(CNetObj_CharacterCore*) /media/ddnet/src/game/gamecore.cpp:515:22 #2 0x55e85a90e171 in CCharacterCore::Quantize() /media/ddnet/src/game/gamecore.cpp:574:2 #3 0x55e85af90be9 in CCharacter::TickDefered() /media/ddnet/src/game/client/prediction/entities/character.cpp:580:9 #4 0x55e85afc8a1b in CGameWorld::Tick() /media/ddnet/src/game/client/prediction/gameworld.cpp:201:10 #5 0x55e85af500b8 in CGameClient::UpdatePrediction() /media/ddnet/src/game/client/gameclient.cpp:2279:16 #6 0x55e85af48b9b in CGameClient::OnNewSnapshot() /media/ddnet/src/game/client/gameclient.cpp:1675:3 #7 0x55e85a9fdf8c in CClient::Update() /media/ddnet/src/engine/client/client.cpp:2767:22 #8 0x55e85aa0cefe in CClient::Run() /media/ddnet/src/engine/client/client.cpp:3237:4 #9 0x55e85aa2eb2e in main /media/ddnet/src/engine/client/client.cpp:4341:11 #10 0x7feedbc65151 in __libc_start_main (/usr/lib/libc.so.6+0x28151) #11 0x55e85a77be0d in _start (/media/ddnet/DDNet+0x705e0d)
2020-10-10 11:10:02 +00:00
Reset();
}
2010-05-29 07:25:38 +00:00
void CCharacterCore::Reset()
{
m_Pos = vec2(0, 0);
m_Vel = vec2(0, 0);
2013-07-18 22:27:17 +00:00
m_NewHook = false;
m_HookPos = vec2(0, 0);
m_HookDir = vec2(0, 0);
2010-05-29 07:25:38 +00:00
m_HookTick = 0;
m_HookState = HOOK_IDLE;
SetHookedPlayer(-1);
m_AttachedPlayers.clear();
2010-05-29 07:25:38 +00:00
m_Jumped = 0;
m_JumpedTotal = 0;
m_Jumps = 2;
2010-05-29 07:25:38 +00:00
m_TriggeredEvents = 0;
// DDNet Character
2019-04-12 14:29:13 +00:00
m_Solo = false;
m_Jetpack = false;
m_CollisionDisabled = false;
m_EndlessHook = false;
m_EndlessJump = false;
m_HammerHitDisabled = false;
m_GrenadeHitDisabled = false;
m_LaserHitDisabled = false;
m_ShotgunHitDisabled = false;
m_HookHitDisabled = false;
m_Super = false;
m_HasTelegunGun = false;
m_HasTelegunGrenade = false;
m_HasTelegunLaser = false;
m_FreezeStart = 0;
m_FreezeEnd = 0;
m_IsInFreeze = false;
m_DeepFrozen = false;
m_LiveFrozen = false;
2020-10-17 16:17:13 +00:00
// never initialize both to 0
m_Input.m_TargetX = 0;
m_Input.m_TargetY = -1;
}
void CCharacterCore::Tick(bool UseInput, bool DoDeferredTick)
2007-09-22 18:55:00 +00:00
{
m_MoveRestrictions = m_pCollision->GetMoveRestrictions(UseInput ? IsSwitchActiveCb : 0, this, m_Pos);
2010-05-29 07:25:38 +00:00
m_TriggeredEvents = 0;
2008-09-23 07:43:41 +00:00
// get ground state
2022-08-09 14:59:52 +00:00
const bool Grounded = m_pCollision->CheckPoint(m_Pos.x + PhysicalSize() / 2, m_Pos.y + PhysicalSize() / 2 + 5) || m_pCollision->CheckPoint(m_Pos.x - PhysicalSize() / 2, m_Pos.y + PhysicalSize() / 2 + 5);
2010-05-29 07:25:38 +00:00
vec2 TargetDirection = normalize(vec2(m_Input.m_TargetX, m_Input.m_TargetY));
2007-09-22 18:55:00 +00:00
2021-05-12 16:57:50 +00:00
m_Vel.y += m_Tuning.m_Gravity;
2021-05-12 16:57:50 +00:00
float MaxSpeed = Grounded ? m_Tuning.m_GroundControlSpeed : m_Tuning.m_AirControlSpeed;
float Accel = Grounded ? m_Tuning.m_GroundControlAccel : m_Tuning.m_AirControlAccel;
float Friction = Grounded ? m_Tuning.m_GroundFriction : m_Tuning.m_AirFriction;
2008-09-23 07:43:41 +00:00
// handle input
2010-05-29 07:25:38 +00:00
if(UseInput)
2008-09-23 07:43:41 +00:00
{
2010-05-29 07:25:38 +00:00
m_Direction = m_Input.m_Direction;
2008-09-23 07:43:41 +00:00
// setup angle
float TmpAngle = atan2f(m_Input.m_TargetY, m_Input.m_TargetX);
if(TmpAngle < -(pi / 2.0f))
{
m_Angle = (int)((TmpAngle + (2.0f * pi)) * 256.0f);
}
2008-09-23 07:43:41 +00:00
else
{
m_Angle = (int)(TmpAngle * 256.0f);
}
2008-09-23 07:43:41 +00:00
// Special jump cases:
// m_Jumps == -1: A tee may only make one ground jump. Second jumped bit is always set
// m_Jumps == 0: A tee may not make a jump. Second jumped bit is always set
// m_Jumps == 1: A tee may do either a ground jump or an air jump. Second jumped bit is set after the first jump
2022-05-20 20:55:01 +00:00
// The second jumped bit can be overridden by special tiles so that the tee can nevertheless jump.
2008-09-23 07:43:41 +00:00
// handle jump
2010-05-29 07:25:38 +00:00
if(m_Input.m_Jump)
2008-09-23 07:43:41 +00:00
{
if(!(m_Jumped & 1))
2008-09-23 07:43:41 +00:00
{
2022-05-20 20:55:01 +00:00
if(Grounded && (!(m_Jumped & 2) || m_Jumps != 0))
2008-09-23 07:43:41 +00:00
{
2013-08-24 00:25:58 +00:00
m_TriggeredEvents |= COREEVENT_GROUND_JUMP;
2021-05-12 16:57:50 +00:00
m_Vel.y = -m_Tuning.m_GroundJumpImpulse;
2022-05-16 21:17:19 +00:00
if(m_Jumps > 1)
{
m_Jumped |= 1;
}
else
{
m_Jumped |= 3;
}
m_JumpedTotal = 0;
2013-08-24 00:25:58 +00:00
}
else if(!(m_Jumped & 2))
2013-08-24 00:25:58 +00:00
{
m_TriggeredEvents |= COREEVENT_AIR_JUMP;
2021-05-12 16:57:50 +00:00
m_Vel.y = -m_Tuning.m_AirJumpImpulse;
2013-08-24 00:25:58 +00:00
m_Jumped |= 3;
m_JumpedTotal++;
2008-09-23 07:43:41 +00:00
}
}
}
else
2022-05-16 21:17:19 +00:00
{
2010-05-29 07:25:38 +00:00
m_Jumped &= ~1;
2022-05-16 21:17:19 +00:00
}
2008-09-23 07:43:41 +00:00
// handle hook
2010-05-29 07:25:38 +00:00
if(m_Input.m_Hook)
2008-09-23 07:43:41 +00:00
{
2010-05-29 07:25:38 +00:00
if(m_HookState == HOOK_IDLE)
2008-09-23 07:43:41 +00:00
{
2010-05-29 07:25:38 +00:00
m_HookState = HOOK_FLYING;
m_HookPos = m_Pos + TargetDirection * PhysicalSize() * 1.5f;
2010-05-29 07:25:38 +00:00
m_HookDir = TargetDirection;
SetHookedPlayer(-1);
m_HookTick = (float)SERVER_TICK_SPEED * (1.25f - m_Tuning.m_HookDuration);
2010-05-29 07:25:38 +00:00
m_TriggeredEvents |= COREEVENT_HOOK_LAUNCH;
}
2008-09-23 07:43:41 +00:00
}
else
{
SetHookedPlayer(-1);
2010-05-29 07:25:38 +00:00
m_HookState = HOOK_IDLE;
m_HookPos = m_Pos;
}
2008-09-23 07:43:41 +00:00
}
// handle jumping
// 1 bit = to keep track if a jump has been made on this input (player is holding space bar)
// 2 bit = to track if all air-jumps have been used up (tee gets dark feet)
if(Grounded)
{
m_Jumped &= ~2;
m_JumpedTotal = 0;
}
2008-09-23 07:43:41 +00:00
// add the speed modification according to players wanted direction
2010-05-29 07:25:38 +00:00
if(m_Direction < 0)
m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, -Accel);
2010-05-29 07:25:38 +00:00
if(m_Direction > 0)
m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, Accel);
2010-05-29 07:25:38 +00:00
if(m_Direction == 0)
m_Vel.x *= Friction;
2008-09-23 07:43:41 +00:00
// do hook
2010-05-29 07:25:38 +00:00
if(m_HookState == HOOK_IDLE)
2007-09-22 18:55:00 +00:00
{
SetHookedPlayer(-1);
2010-05-29 07:25:38 +00:00
m_HookPos = m_Pos;
2007-09-22 18:55:00 +00:00
}
2010-05-29 07:25:38 +00:00
else if(m_HookState >= HOOK_RETRACT_START && m_HookState < HOOK_RETRACT_END)
2007-09-22 18:55:00 +00:00
{
2010-05-29 07:25:38 +00:00
m_HookState++;
2008-09-23 07:43:41 +00:00
}
2010-05-29 07:25:38 +00:00
else if(m_HookState == HOOK_RETRACT_END)
2008-09-23 07:43:41 +00:00
{
2010-05-29 07:25:38 +00:00
m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_HookState = HOOK_RETRACTED;
2008-09-23 07:43:41 +00:00
}
2010-05-29 07:25:38 +00:00
else if(m_HookState == HOOK_FLYING)
2008-09-23 07:43:41 +00:00
{
2021-05-12 16:57:50 +00:00
vec2 NewPos = m_HookPos + m_HookDir * m_Tuning.m_HookFireSpeed;
if((!m_NewHook && distance(m_Pos, NewPos) > m_Tuning.m_HookLength) || (m_NewHook && distance(m_HookTeleBase, NewPos) > m_Tuning.m_HookLength))
2008-03-22 13:03:52 +00:00
{
2010-05-29 07:25:38 +00:00
m_HookState = HOOK_RETRACT_START;
2021-05-12 16:57:50 +00:00
NewPos = m_Pos + normalize(NewPos - m_Pos) * m_Tuning.m_HookLength;
m_Reset = true;
}
2008-09-23 07:43:41 +00:00
// make sure that the hook doesn't go though the ground
2010-05-29 07:25:38 +00:00
bool GoingToHitGround = false;
bool GoingToRetract = false;
2013-07-18 22:27:17 +00:00
bool GoingThroughTele = false;
int teleNr = 0;
2015-11-08 09:20:44 +00:00
int Hit = m_pCollision->IntersectLineTeleHook(m_HookPos, NewPos, &NewPos, 0, &teleNr);
2013-07-18 22:27:17 +00:00
2022-09-03 07:59:39 +00:00
// m_NewHook = false;
2013-07-18 22:27:17 +00:00
2010-05-29 07:25:38 +00:00
if(Hit)
2008-09-23 14:38:13 +00:00
{
2015-11-08 09:20:10 +00:00
if(Hit == TILE_NOHOOK)
2010-05-29 07:25:38 +00:00
GoingToRetract = true;
else if(Hit == TILE_TELEINHOOK)
2013-07-18 22:27:17 +00:00
GoingThroughTele = true;
2008-09-23 14:38:13 +00:00
else
2010-05-29 07:25:38 +00:00
GoingToHitGround = true;
m_Reset = true;
2008-09-23 14:38:13 +00:00
}
2007-09-22 18:55:00 +00:00
2008-09-23 07:43:41 +00:00
// Check against other players first
if(!this->m_HookHitDisabled && m_pWorld && m_Tuning.m_PlayerHooking)
2008-09-23 07:43:41 +00:00
{
float Distance = 0.0f;
2007-09-22 18:55:00 +00:00
for(int i = 0; i < MAX_CLIENTS; i++)
{
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[i];
CCharacterCore::Tick caused out of bounds src/game/teamscore.cpp:27:78: runtime error: index -1 out of bounds for type 'int const[64]' #0 0xf5b948 in CTeamsCore::CanKeepHook(int, int) const src/game/teamscore.cpp:27 #1 0xf46fe1 in CCharacterCore::Tick(bool) src/game/gamecore.cpp:325 #2 0xaf7366 in CGameClient::DetectStrongHook() src/game/client/gameclient.cpp:2441 #3 0xadd734 in CGameClient::UpdatePrediction() src/game/client/gameclient.cpp:2249 #4 0xad6e17 in CGameClient::OnNewSnapshot() src/game/client/gameclient.cpp:1675 #5 0x522d55 in CClient::Update() src/engine/client/client.cpp:2767 #6 0x5333e4 in CClient::Run() src/engine/client/client.cpp:3237 #7 0x557fda in main src/engine/client/client.cpp:4341 #8 0x7f55e8c75cc9 in __libc_start_main ../csu/libc-start.c:308 #9 0x433e29 in _start (build/DDNet+0x433e29) src/game/teamscore.cpp:34:78: runtime error: index -1 out of bounds for type 'int const[64]' #0 0xf5be68 in CTeamsCore::CanCollide(int, int) const src/game/teamscore.cpp:34 #1 0xf46458 in CCharacterCore::Tick(bool) src/game/gamecore.cpp:271 #2 0xaf7374 in CGameClient::DetectStrongHook() src/game/client/gameclient.cpp:2442 #3 0xadd734 in CGameClient::UpdatePrediction() src/game/client/gameclient.cpp:2249 #4 0xad6e17 in CGameClient::OnNewSnapshot() src/game/client/gameclient.cpp:1675 #5 0x522d55 in CClient::Update() src/engine/client/client.cpp:2767 #6 0x5333e4 in CClient::Run() src/engine/client/client.cpp:3237 #7 0x557fda in main src/engine/client/client.cpp:4341 #8 0x7f55e8c75cc9 in __libc_start_main ../csu/libc-start.c:308 #9 0x433e29 in _start (build/DDNet+0x433e29)
2020-10-10 21:46:01 +00:00
if(!pCharCore || pCharCore == this || (!(m_Super || pCharCore->m_Super) && ((m_Id != -1 && !m_pTeams->CanCollide(i, m_Id)) || pCharCore->m_Solo || m_Solo)))
2007-09-22 18:55:00 +00:00
continue;
vec2 ClosestPoint;
if(closest_point_on_line(m_HookPos, NewPos, pCharCore->m_Pos, ClosestPoint))
2007-09-22 18:55:00 +00:00
{
if(distance(pCharCore->m_Pos, ClosestPoint) < PhysicalSize() + 2.0f)
2009-01-09 22:41:26 +00:00
{
if(m_HookedPlayer == -1 || distance(m_HookPos, pCharCore->m_Pos) < Distance)
{
m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_PLAYER;
m_HookState = HOOK_GRABBED;
SetHookedPlayer(i);
Distance = distance(m_HookPos, pCharCore->m_Pos);
}
2009-01-09 22:41:26 +00:00
}
2007-09-22 18:55:00 +00:00
}
}
2008-09-23 07:43:41 +00:00
}
2010-05-29 07:25:38 +00:00
if(m_HookState == HOOK_FLYING)
2008-09-23 07:43:41 +00:00
{
// check against ground
2010-05-29 07:25:38 +00:00
if(GoingToHitGround)
2007-09-22 18:55:00 +00:00
{
2010-05-29 07:25:38 +00:00
m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_GROUND;
m_HookState = HOOK_GRABBED;
2007-09-22 18:55:00 +00:00
}
2010-05-29 07:25:38 +00:00
else if(GoingToRetract)
2008-09-23 14:38:13 +00:00
{
2010-05-29 07:25:38 +00:00
m_TriggeredEvents |= COREEVENT_HOOK_HIT_NOHOOK;
m_HookState = HOOK_RETRACT_START;
2008-09-23 14:38:13 +00:00
}
2022-01-22 12:54:25 +00:00
if(GoingThroughTele && m_pWorld && m_pTeleOuts && !m_pTeleOuts->empty() && !(*m_pTeleOuts)[teleNr - 1].empty())
2013-07-18 22:27:17 +00:00
{
m_TriggeredEvents = 0;
SetHookedPlayer(-1);
2013-07-18 22:27:17 +00:00
m_NewHook = true;
int RandomOut = m_pWorld->RandomOr0((*m_pTeleOuts)[teleNr - 1].size());
m_HookPos = (*m_pTeleOuts)[teleNr - 1][RandomOut] + TargetDirection * PhysicalSize() * 1.5f;
2013-07-18 22:27:17 +00:00
m_HookDir = TargetDirection;
2014-01-27 04:06:23 +00:00
m_HookTeleBase = m_HookPos;
2013-07-18 22:27:17 +00:00
}
else
{
m_HookPos = NewPos;
}
2007-09-22 18:55:00 +00:00
}
}
2010-05-29 07:25:38 +00:00
if(m_HookState == HOOK_GRABBED)
2007-09-22 18:55:00 +00:00
{
if(m_HookedPlayer != -1 && m_pWorld)
2007-09-22 18:55:00 +00:00
{
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[m_HookedPlayer];
CCharacterCore::Tick caused out of bounds src/game/teamscore.cpp:27:78: runtime error: index -1 out of bounds for type 'int const[64]' #0 0xf5b948 in CTeamsCore::CanKeepHook(int, int) const src/game/teamscore.cpp:27 #1 0xf46fe1 in CCharacterCore::Tick(bool) src/game/gamecore.cpp:325 #2 0xaf7366 in CGameClient::DetectStrongHook() src/game/client/gameclient.cpp:2441 #3 0xadd734 in CGameClient::UpdatePrediction() src/game/client/gameclient.cpp:2249 #4 0xad6e17 in CGameClient::OnNewSnapshot() src/game/client/gameclient.cpp:1675 #5 0x522d55 in CClient::Update() src/engine/client/client.cpp:2767 #6 0x5333e4 in CClient::Run() src/engine/client/client.cpp:3237 #7 0x557fda in main src/engine/client/client.cpp:4341 #8 0x7f55e8c75cc9 in __libc_start_main ../csu/libc-start.c:308 #9 0x433e29 in _start (build/DDNet+0x433e29) src/game/teamscore.cpp:34:78: runtime error: index -1 out of bounds for type 'int const[64]' #0 0xf5be68 in CTeamsCore::CanCollide(int, int) const src/game/teamscore.cpp:34 #1 0xf46458 in CCharacterCore::Tick(bool) src/game/gamecore.cpp:271 #2 0xaf7374 in CGameClient::DetectStrongHook() src/game/client/gameclient.cpp:2442 #3 0xadd734 in CGameClient::UpdatePrediction() src/game/client/gameclient.cpp:2249 #4 0xad6e17 in CGameClient::OnNewSnapshot() src/game/client/gameclient.cpp:1675 #5 0x522d55 in CClient::Update() src/engine/client/client.cpp:2767 #6 0x5333e4 in CClient::Run() src/engine/client/client.cpp:3237 #7 0x557fda in main src/engine/client/client.cpp:4341 #8 0x7f55e8c75cc9 in __libc_start_main ../csu/libc-start.c:308 #9 0x433e29 in _start (build/DDNet+0x433e29)
2020-10-10 21:46:01 +00:00
if(pCharCore && m_Id != -1 && m_pTeams->CanKeepHook(m_Id, pCharCore->m_Id))
2015-02-23 23:04:16 +00:00
m_HookPos = pCharCore->m_Pos;
else
{
// release hook
SetHookedPlayer(-1);
2010-05-29 07:25:38 +00:00
m_HookState = HOOK_RETRACTED;
m_HookPos = m_Pos;
}
2007-09-22 18:55:00 +00:00
// keep players hooked for a max of 1.5sec
2022-09-03 07:59:39 +00:00
// if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2)
// release_hooked();
2007-09-22 18:55:00 +00:00
}
// don't do this hook rutine when we are hook to a player
2010-05-29 07:25:38 +00:00
if(m_HookedPlayer == -1 && distance(m_HookPos, m_Pos) > 46.0f)
2007-09-22 18:55:00 +00:00
{
2021-05-12 16:57:50 +00:00
vec2 HookVel = normalize(m_HookPos - m_Pos) * m_Tuning.m_HookDragAccel;
2007-09-22 18:55:00 +00:00
// the hook as more power to drag you up then down.
// this makes it easier to get on top of an platform
2010-05-29 07:25:38 +00:00
if(HookVel.y > 0)
HookVel.y *= 0.3f;
2007-09-22 18:55:00 +00:00
// the hook will boost it's power if the player wants to move
// in that direction. otherwise it will dampen everything abit
if((HookVel.x < 0 && m_Direction < 0) || (HookVel.x > 0 && m_Direction > 0))
2010-05-29 07:25:38 +00:00
HookVel.x *= 0.95f;
2007-09-22 18:55:00 +00:00
else
2010-05-29 07:25:38 +00:00
HookVel.x *= 0.75f;
vec2 NewVel = m_Vel + HookVel;
2007-09-22 18:55:00 +00:00
// check if we are under the legal limit for the hook
2021-05-12 16:57:50 +00:00
if(length(NewVel) < m_Tuning.m_HookDragSpeed || length(NewVel) < length(m_Vel))
2010-05-29 07:25:38 +00:00
m_Vel = NewVel; // no problem. apply
2007-09-22 18:55:00 +00:00
}
2014-12-27 11:05:02 +00:00
// release hook (max default hook time is 1.25 s)
2010-05-29 07:25:38 +00:00
m_HookTick++;
if(m_HookedPlayer != -1 && (m_HookTick > SERVER_TICK_SPEED + SERVER_TICK_SPEED / 5 || (m_pWorld && !m_pWorld->m_apCharacters[m_HookedPlayer])))
{
SetHookedPlayer(-1);
2010-05-29 07:25:38 +00:00
m_HookState = HOOK_RETRACTED;
m_HookPos = m_Pos;
}
2007-09-22 18:55:00 +00:00
}
if(DoDeferredTick)
TickDeferred();
}
void CCharacterCore::TickDeferred()
{
if(m_pWorld)
2007-09-22 18:55:00 +00:00
{
for(int i = 0; i < MAX_CLIENTS; i++)
{
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[i];
if(!pCharCore)
2007-09-22 18:55:00 +00:00
continue;
2022-09-03 07:59:39 +00:00
// player *p = (player*)ent;
// if(pCharCore == this) // || !(p->flags&FLAG_ALIVE)
2019-04-21 12:57:45 +00:00
if(pCharCore == this || (m_Id != -1 && !m_pTeams->CanCollide(m_Id, i)))
2007-09-22 18:55:00 +00:00
continue; // make sure that we don't nudge our self
2019-04-21 12:57:45 +00:00
if(!(m_Super || pCharCore->m_Super) && (m_Solo || pCharCore->m_Solo))
continue;
// handle player <-> player collision
float Distance = distance(m_Pos, pCharCore->m_Pos);
if(Distance > 0)
{
vec2 Dir = normalize(m_Pos - pCharCore->m_Pos);
2019-04-21 12:57:45 +00:00
bool CanCollide = (m_Super || pCharCore->m_Super) || (!m_CollisionDisabled && !pCharCore->m_CollisionDisabled && m_Tuning.m_PlayerCollision);
2019-04-21 12:57:45 +00:00
if(CanCollide && Distance < PhysicalSize() * 1.25f && Distance > 0.0f)
{
float a = (PhysicalSize() * 1.45f - Distance);
float Velocity = 0.5f;
// make sure that we don't add excess force by checking the
// direction against the current velocity. if not zero.
2022-03-21 06:10:44 +00:00
if(length(m_Vel) > 0.0001f)
2022-03-23 17:30:18 +00:00
Velocity = 1 - (dot(normalize(m_Vel), Dir) + 1) / 2; // Wdouble-promotion don't fix this as this might change game physics
m_Vel += Dir * a * (Velocity * 0.75f);
m_Vel *= 0.85f;
}
// handle hook influence
if(!m_HookHitDisabled && m_HookedPlayer == i && m_Tuning.m_PlayerHooking)
{
if(Distance > PhysicalSize() * 1.50f) // TODO: fix tweakable variable
{
float HookAccel = m_Tuning.m_HookDragAccel * (Distance / m_Tuning.m_HookLength);
2021-05-12 16:57:50 +00:00
float DragSpeed = m_Tuning.m_HookDragSpeed;
vec2 Temp;
// add force to the hooked player
Temp.x = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.x, HookAccel * Dir.x * 1.5f);
Temp.y = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.y, HookAccel * Dir.y * 1.5f);
pCharCore->m_Vel = ClampVel(pCharCore->m_MoveRestrictions, Temp);
// add a little bit force to the guy who has the grip
Temp.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, -HookAccel * Dir.x * 0.25f);
Temp.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, -HookAccel * Dir.y * 0.25f);
m_Vel = ClampVel(m_MoveRestrictions, Temp);
}
}
}
}
if(m_HookState != HOOK_FLYING)
{
m_NewHook = false;
}
}
// clamp the velocity to something sane
2010-05-29 07:25:38 +00:00
if(length(m_Vel) > 6000)
m_Vel = normalize(m_Vel) * 6000;
2007-09-22 18:55:00 +00:00
}
void CCharacterCore::Move()
2007-09-22 18:55:00 +00:00
{
2021-05-12 16:57:50 +00:00
float RampValue = VelocityRamp(length(m_Vel) * 50, m_Tuning.m_VelrampStart, m_Tuning.m_VelrampRange, m_Tuning.m_VelrampCurvature);
m_Vel.x = m_Vel.x * RampValue;
vec2 NewPos = m_Pos;
2014-06-21 22:50:11 +00:00
vec2 OldVel = m_Vel;
m_pCollision->MoveBox(&NewPos, &m_Vel, PhysicalSizeVec2(), 0);
2014-06-22 16:07:28 +00:00
m_Colliding = 0;
2019-07-08 21:08:42 +00:00
if(m_Vel.x < 0.001f && m_Vel.x > -0.001f)
2014-06-21 22:50:11 +00:00
{
if(OldVel.x > 0)
m_Colliding = 1;
else if(OldVel.x < 0)
m_Colliding = 2;
}
2014-06-23 12:46:27 +00:00
else
m_LeftWall = true;
2014-06-21 22:50:11 +00:00
m_Vel.x = m_Vel.x * (1.0f / RampValue);
if(m_pWorld && (m_Super || (m_Tuning.m_PlayerCollision && !m_CollisionDisabled && !m_Solo)))
{
// check player collision
float Distance = distance(m_Pos, NewPos);
if(Distance > 0)
{
int End = Distance + 1;
vec2 LastPos = m_Pos;
for(int i = 0; i < End; i++)
{
float a = i / Distance;
vec2 Pos = mix(m_Pos, NewPos, a);
for(int p = 0; p < MAX_CLIENTS; p++)
2011-12-26 13:31:05 +00:00
{
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[p];
if(!pCharCore || pCharCore == this)
continue;
if((!(pCharCore->m_Super || m_Super) && (m_Solo || pCharCore->m_Solo || pCharCore->m_CollisionDisabled || (m_Id != -1 && !m_pTeams->CanCollide(m_Id, p)))))
continue;
float D = distance(Pos, pCharCore->m_Pos);
if(D < PhysicalSize() && D >= 0.0f)
{
if(a > 0.0f)
m_Pos = LastPos;
else if(distance(NewPos, pCharCore->m_Pos) > D)
m_Pos = NewPos;
return;
}
2011-12-26 13:31:05 +00:00
}
LastPos = Pos;
}
}
}
m_Pos = NewPos;
2007-09-22 18:55:00 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacterCore::Write(CNetObj_CharacterCore *pObjCore)
2007-09-22 18:55:00 +00:00
{
pObjCore->m_X = round_to_int(m_Pos.x);
pObjCore->m_Y = round_to_int(m_Pos.y);
pObjCore->m_VelX = round_to_int(m_Vel.x * 256.0f);
pObjCore->m_VelY = round_to_int(m_Vel.y * 256.0f);
2010-05-29 07:25:38 +00:00
pObjCore->m_HookState = m_HookState;
pObjCore->m_HookTick = m_HookTick;
pObjCore->m_HookX = round_to_int(m_HookPos.x);
pObjCore->m_HookY = round_to_int(m_HookPos.y);
pObjCore->m_HookDx = round_to_int(m_HookDir.x * 256.0f);
pObjCore->m_HookDy = round_to_int(m_HookDir.y * 256.0f);
2010-05-29 07:25:38 +00:00
pObjCore->m_HookedPlayer = m_HookedPlayer;
pObjCore->m_Jumped = m_Jumped;
pObjCore->m_Direction = m_Direction;
pObjCore->m_Angle = m_Angle;
2007-09-22 18:55:00 +00:00
}
void CCharacterCore::Read(const CNetObj_CharacterCore *pObjCore)
2007-09-22 18:55:00 +00:00
{
2010-05-29 07:25:38 +00:00
m_Pos.x = pObjCore->m_X;
m_Pos.y = pObjCore->m_Y;
m_Vel.x = pObjCore->m_VelX / 256.0f;
m_Vel.y = pObjCore->m_VelY / 256.0f;
2010-05-29 07:25:38 +00:00
m_HookState = pObjCore->m_HookState;
m_HookTick = pObjCore->m_HookTick;
m_HookPos.x = pObjCore->m_HookX;
m_HookPos.y = pObjCore->m_HookY;
m_HookDir.x = pObjCore->m_HookDx / 256.0f;
m_HookDir.y = pObjCore->m_HookDy / 256.0f;
SetHookedPlayer(pObjCore->m_HookedPlayer);
2010-05-29 07:25:38 +00:00
m_Jumped = pObjCore->m_Jumped;
m_Direction = pObjCore->m_Direction;
m_Angle = pObjCore->m_Angle;
2007-09-22 18:55:00 +00:00
}
void CCharacterCore::ReadDDNet(const CNetObj_DDNetCharacter *pObjDDNet)
{
// Collision
m_Solo = pObjDDNet->m_Flags & CHARACTERFLAG_SOLO;
2021-08-08 10:36:25 +00:00
m_Jetpack = pObjDDNet->m_Flags & CHARACTERFLAG_JETPACK;
m_CollisionDisabled = pObjDDNet->m_Flags & CHARACTERFLAG_COLLISION_DISABLED;
m_HammerHitDisabled = pObjDDNet->m_Flags & CHARACTERFLAG_HAMMER_HIT_DISABLED;
m_ShotgunHitDisabled = pObjDDNet->m_Flags & CHARACTERFLAG_SHOTGUN_HIT_DISABLED;
m_GrenadeHitDisabled = pObjDDNet->m_Flags & CHARACTERFLAG_GRENADE_HIT_DISABLED;
m_LaserHitDisabled = pObjDDNet->m_Flags & CHARACTERFLAG_LASER_HIT_DISABLED;
m_HookHitDisabled = pObjDDNet->m_Flags & CHARACTERFLAG_HOOK_HIT_DISABLED;
m_Super = pObjDDNet->m_Flags & CHARACTERFLAG_SUPER;
// Endless
m_EndlessHook = pObjDDNet->m_Flags & CHARACTERFLAG_ENDLESS_HOOK;
m_EndlessJump = pObjDDNet->m_Flags & CHARACTERFLAG_ENDLESS_JUMP;
// Freeze
m_FreezeEnd = pObjDDNet->m_FreezeEnd;
m_DeepFrozen = pObjDDNet->m_FreezeEnd == -1;
m_LiveFrozen = (pObjDDNet->m_Flags & CHARACTERFLAG_MOVEMENTS_DISABLED) != 0;
// Telegun
m_HasTelegunGrenade = pObjDDNet->m_Flags & CHARACTERFLAG_TELEGUN_GRENADE;
m_HasTelegunGun = pObjDDNet->m_Flags & CHARACTERFLAG_TELEGUN_GUN;
m_HasTelegunLaser = pObjDDNet->m_Flags & CHARACTERFLAG_TELEGUN_LASER;
// Weapons
m_aWeapons[WEAPON_HAMMER].m_Got = (pObjDDNet->m_Flags & CHARACTERFLAG_WEAPON_HAMMER) != 0;
m_aWeapons[WEAPON_GUN].m_Got = (pObjDDNet->m_Flags & CHARACTERFLAG_WEAPON_GUN) != 0;
m_aWeapons[WEAPON_SHOTGUN].m_Got = (pObjDDNet->m_Flags & CHARACTERFLAG_WEAPON_SHOTGUN) != 0;
m_aWeapons[WEAPON_GRENADE].m_Got = (pObjDDNet->m_Flags & CHARACTERFLAG_WEAPON_GRENADE) != 0;
m_aWeapons[WEAPON_LASER].m_Got = (pObjDDNet->m_Flags & CHARACTERFLAG_WEAPON_LASER) != 0;
2022-03-24 00:05:41 +00:00
m_aWeapons[WEAPON_NINJA].m_Got = (pObjDDNet->m_Flags & CHARACTERFLAG_WEAPON_NINJA) != 0;
// Available jumps
m_Jumps = pObjDDNet->m_Jumps;
// Display Information
// We only accept the display information when it is received, which means it is not -1 in each case.
if(pObjDDNet->m_JumpedTotal != -1)
{
m_JumpedTotal = pObjDDNet->m_JumpedTotal;
}
if(pObjDDNet->m_NinjaActivationTick != -1)
{
m_Ninja.m_ActivationTick = pObjDDNet->m_NinjaActivationTick;
}
if(pObjDDNet->m_FreezeStart != -1)
{
m_FreezeStart = pObjDDNet->m_FreezeStart;
m_IsInFreeze = pObjDDNet->m_Flags & CHARACTERFLAG_IN_FREEZE;
}
}
2010-05-29 07:25:38 +00:00
void CCharacterCore::Quantize()
2007-09-22 18:55:00 +00:00
{
2010-05-29 07:25:38 +00:00
CNetObj_CharacterCore Core;
Write(&Core);
Read(&Core);
2007-09-22 18:55:00 +00:00
}
2011-01-06 03:46:10 +00:00
void CCharacterCore::SetHookedPlayer(int HookedPlayer)
{
if(HookedPlayer != m_HookedPlayer)
{
if(m_HookedPlayer != -1 && m_Id != -1 && m_pWorld)
{
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[m_HookedPlayer];
if(pCharCore)
{
pCharCore->m_AttachedPlayers.erase(m_Id);
}
}
if(HookedPlayer != -1 && m_Id != -1 && m_pWorld)
{
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[HookedPlayer];
if(pCharCore)
{
pCharCore->m_AttachedPlayers.insert(m_Id);
}
}
m_HookedPlayer = HookedPlayer;
}
}
// DDRace
2011-01-06 03:46:10 +00:00
void CCharacterCore::SetTeamsCore(CTeamsCore *pTeams)
{
m_pTeams = pTeams;
}
void CCharacterCore::SetTeleOuts(std::map<int, std::vector<vec2>> *pTeleOuts)
{
m_pTeleOuts = pTeleOuts;
}
bool CCharacterCore::IsSwitchActiveCb(int Number, void *pUser)
2011-01-06 03:46:10 +00:00
{
CCharacterCore *pThis = (CCharacterCore *)pUser;
if(pThis->m_pWorld && !pThis->m_pWorld->m_vSwitchers.empty())
CCharacterCore::Tick caused out of bounds src/game/teamscore.cpp:27:78: runtime error: index -1 out of bounds for type 'int const[64]' #0 0xf5b948 in CTeamsCore::CanKeepHook(int, int) const src/game/teamscore.cpp:27 #1 0xf46fe1 in CCharacterCore::Tick(bool) src/game/gamecore.cpp:325 #2 0xaf7366 in CGameClient::DetectStrongHook() src/game/client/gameclient.cpp:2441 #3 0xadd734 in CGameClient::UpdatePrediction() src/game/client/gameclient.cpp:2249 #4 0xad6e17 in CGameClient::OnNewSnapshot() src/game/client/gameclient.cpp:1675 #5 0x522d55 in CClient::Update() src/engine/client/client.cpp:2767 #6 0x5333e4 in CClient::Run() src/engine/client/client.cpp:3237 #7 0x557fda in main src/engine/client/client.cpp:4341 #8 0x7f55e8c75cc9 in __libc_start_main ../csu/libc-start.c:308 #9 0x433e29 in _start (build/DDNet+0x433e29) src/game/teamscore.cpp:34:78: runtime error: index -1 out of bounds for type 'int const[64]' #0 0xf5be68 in CTeamsCore::CanCollide(int, int) const src/game/teamscore.cpp:34 #1 0xf46458 in CCharacterCore::Tick(bool) src/game/gamecore.cpp:271 #2 0xaf7374 in CGameClient::DetectStrongHook() src/game/client/gameclient.cpp:2442 #3 0xadd734 in CGameClient::UpdatePrediction() src/game/client/gameclient.cpp:2249 #4 0xad6e17 in CGameClient::OnNewSnapshot() src/game/client/gameclient.cpp:1675 #5 0x522d55 in CClient::Update() src/engine/client/client.cpp:2767 #6 0x5333e4 in CClient::Run() src/engine/client/client.cpp:3237 #7 0x557fda in main src/engine/client/client.cpp:4341 #8 0x7f55e8c75cc9 in __libc_start_main ../csu/libc-start.c:308 #9 0x433e29 in _start (build/DDNet+0x433e29)
2020-10-10 21:46:01 +00:00
if(pThis->m_Id != -1 && pThis->m_pTeams->Team(pThis->m_Id) != (pThis->m_pTeams->m_IsDDRace16 ? VANILLA_TEAM_SUPER : TEAM_SUPER))
return pThis->m_pWorld->m_vSwitchers[Number].m_aStatus[pThis->m_pTeams->Team(pThis->m_Id)];
return false;
2011-01-06 03:46:10 +00:00
}
2022-02-13 19:57:27 +00:00
void CWorldCore::InitSwitchers(int HighestSwitchNumber)
2022-02-13 19:57:27 +00:00
{
if(HighestSwitchNumber > 0)
m_vSwitchers.resize(HighestSwitchNumber + 1);
else
m_vSwitchers.clear();
2022-02-13 19:57:27 +00:00
for(auto &Switcher : m_vSwitchers)
2022-02-13 19:57:27 +00:00
{
Switcher.m_Initial = true;
2022-02-13 19:57:27 +00:00
for(int j = 0; j < MAX_CLIENTS; j++)
{
Switcher.m_aStatus[j] = true;
Switcher.m_aEndTick[j] = 0;
Switcher.m_aType[j] = 0;
Switcher.m_aLastUpdateTick[j] = 0;
2022-02-13 19:57:27 +00:00
}
}
}