6244: Minor base refactoring r=def- a=Robyt3


## Checklist

- [ ] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


6245: Add ingame and browser buttons to copy server info to clipboard r=def- a=Robyt3

Add "Copy info" buttons to server browser and ingame menu to copy the server info of the selected/current server to the clipboard.

The margins around the server browser details are improved.

Closes #5440.

Screenshots:
- browser (old):
![browser old](https://user-images.githubusercontent.com/23437060/211093742-b877f1e2-6be0-4827-b1c8-0fd209f697aa.png)
- browser (new):
![browser new](https://user-images.githubusercontent.com/23437060/211093750-f0b3e2c2-8f95-42e1-94bf-ec8b9da4132f.png)
- ingame: 
![ingame](https://user-images.githubusercontent.com/23437060/211093736-04569b8e-96d6-40ab-a37e-8c581f2d8aea.png)


## Checklist

- [X] Tested the change ingame
- [X] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


6246: Remove dead freeze code r=def- a=Zwelf

Remove unused `m_FreezeTime == -1` state

Reduces code complexity. Both `g_Config.m_SvFreezeDelay`[[1]] and `GetSwitchDelay(int Index)`[[2]] can only return non-negative numbers, therefore this is currently dead code and can be removed.

The last time it was possible to pass a negative number was removed in 561ce64666 (diff-29ffe32916052e1066eed938021aadfeb29f855d7c63d9c1ca3350aceffb79f3L1624)

[1]: c8ea372d98/src/engine/shared/config_variables.h (L213)
[2]: c8ea372d98/src/game/mapitems.h (L467)

## Checklist

- [ ] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Robert Müller <robytemueller@gmail.com>
Co-authored-by: Zwelf <zwelf@strct.cc>
This commit is contained in:
bors[bot] 2023-01-06 22:56:49 +00:00 committed by GitHub
commit f79412c59c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 84 additions and 61 deletions

View file

@ -2505,15 +2505,6 @@ int secure_rand();
*/ */
int secure_rand_below(int below); int secure_rand_below(int below);
/*
Function: set_console_msg_color
Sets the console color.
Parameters:
rgb - If NULL it will reset the console color to default, else it will transform the rgb color to a console color
*/
void set_console_msg_color(const void *rgbvoid);
/* /*
Function: os_version_str Function: os_version_str
Returns a human-readable version string of the operating system Returns a human-readable version string of the operating system

View file

@ -84,7 +84,7 @@ public:
}; };
template<typename T> template<typename T>
inline vector2_base<T> rotate(const vector2_base<T> &a, float angle) constexpr inline vector2_base<T> rotate(const vector2_base<T> &a, float angle)
{ {
angle = angle * pi / 180.0f; angle = angle * pi / 180.0f;
float s = sinf(angle); float s = sinf(angle);
@ -99,17 +99,17 @@ inline T distance(const vector2_base<T> a, const vector2_base<T> &b)
} }
template<typename T> template<typename T>
inline T dot(const vector2_base<T> a, const vector2_base<T> &b) constexpr inline T dot(const vector2_base<T> a, const vector2_base<T> &b)
{ {
return a.x * b.x + a.y * b.y; return a.x * b.x + a.y * b.y;
} }
inline float length(const vector2_base<float> &a) inline float length(const vector2_base<float> &a)
{ {
return sqrtf(a.x * a.x + a.y * a.y); return sqrtf(dot(a, a));
} }
inline float angle(const vector2_base<float> &a) constexpr inline float angle(const vector2_base<float> &a)
{ {
if(a.x == 0 && a.y == 0) if(a.x == 0 && a.y == 0)
return 0.0f; return 0.0f;
@ -122,7 +122,7 @@ inline float angle(const vector2_base<float> &a)
} }
template<typename T> template<typename T>
inline vector2_base<T> normalize_pre_length(const vector2_base<T> &v, T len) constexpr inline vector2_base<T> normalize_pre_length(const vector2_base<T> &v, T len)
{ {
if(len == 0) if(len == 0)
return vector2_base<T>(); return vector2_base<T>();
@ -131,14 +131,14 @@ inline vector2_base<T> normalize_pre_length(const vector2_base<T> &v, T len)
inline vector2_base<float> normalize(const vector2_base<float> &v) inline vector2_base<float> normalize(const vector2_base<float> &v)
{ {
float divisor = sqrtf(v.x * v.x + v.y * v.y); float divisor = length(v);
if(divisor == 0.0f) if(divisor == 0.0f)
return vector2_base<float>(0.0f, 0.0f); return vector2_base<float>(0.0f, 0.0f);
float l = (float)(1.0f / divisor); float l = (float)(1.0f / divisor);
return vector2_base<float>(v.x * l, v.y * l); return vector2_base<float>(v.x * l, v.y * l);
} }
inline vector2_base<float> direction(float angle) constexpr inline vector2_base<float> direction(float angle)
{ {
return vector2_base<float>(cosf(angle), sinf(angle)); return vector2_base<float>(cosf(angle), sinf(angle));
} }
@ -148,7 +148,7 @@ typedef vector2_base<bool> bvec2;
typedef vector2_base<int> ivec2; typedef vector2_base<int> ivec2;
template<typename T> template<typename T>
inline bool closest_point_on_line(vector2_base<T> line_pointA, vector2_base<T> line_pointB, vector2_base<T> target_point, vector2_base<T> &out_pos) constexpr inline bool closest_point_on_line(vector2_base<T> line_pointA, vector2_base<T> line_pointB, vector2_base<T> target_point, vector2_base<T> &out_pos)
{ {
vector2_base<T> AB = line_pointB - line_pointA; vector2_base<T> AB = line_pointB - line_pointA;
T SquaredMagnitudeAB = dot(AB, AB); T SquaredMagnitudeAB = dot(AB, AB);
@ -182,12 +182,12 @@ public:
T z, b, l, w; T z, b, l, w;
}; };
vector3_base() : constexpr vector3_base() :
x(T()), y(T()), z(T()) x(T()), y(T()), z(T())
{ {
} }
vector3_base(T nx, T ny, T nz) : constexpr vector3_base(T nx, T ny, T nz) :
x(nx), y(ny), z(nz) x(nx), y(ny), z(nz)
{ {
} }
@ -254,13 +254,13 @@ inline T distance(const vector3_base<T> &a, const vector3_base<T> &b)
} }
template<typename T> template<typename T>
inline T dot(const vector3_base<T> &a, const vector3_base<T> &b) constexpr inline T dot(const vector3_base<T> &a, const vector3_base<T> &b)
{ {
return a.x * b.x + a.y * b.y + a.z * b.z; return a.x * b.x + a.y * b.y + a.z * b.z;
} }
template<typename T> template<typename T>
inline vector3_base<T> cross(const vector3_base<T> &a, const vector3_base<T> &b) constexpr inline vector3_base<T> cross(const vector3_base<T> &a, const vector3_base<T> &b)
{ {
return vector3_base<T>( return vector3_base<T>(
a.y * b.z - a.z * b.y, a.y * b.z - a.z * b.y,
@ -271,12 +271,12 @@ inline vector3_base<T> cross(const vector3_base<T> &a, const vector3_base<T> &b)
// //
inline float length(const vector3_base<float> &a) inline float length(const vector3_base<float> &a)
{ {
return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z); return sqrtf(dot(a, a));
} }
inline vector3_base<float> normalize(const vector3_base<float> &v) inline vector3_base<float> normalize(const vector3_base<float> &v)
{ {
float divisor = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); float divisor = length(v);
if(divisor == 0.0f) if(divisor == 0.0f)
return vector3_base<float>(0.0f, 0.0f, 0.0f); return vector3_base<float>(0.0f, 0.0f, 0.0f);
float l = (float)(1.0f / divisor); float l = (float)(1.0f / divisor);
@ -310,12 +310,12 @@ public:
T w, a; T w, a;
}; };
vector4_base() : constexpr vector4_base() :
x(T()), y(T()), z(T()), w(T()) x(T()), y(T()), z(T()), w(T())
{ {
} }
vector4_base(T nx, T ny, T nz, T nw) : constexpr vector4_base(T nx, T ny, T nz, T nw) :
x(nx), y(ny), z(nz), w(nw) x(nx), y(ny), z(nz), w(nw)
{ {
} }
@ -378,6 +378,7 @@ public:
} }
bool operator==(const vector4_base &vec) const { return x == vec.x && y == vec.y && z == vec.z && w == vec.w; } //TODO: do this with an eps instead bool operator==(const vector4_base &vec) const { return x == vec.x && y == vec.y && z == vec.z && w == vec.w; } //TODO: do this with an eps instead
bool operator!=(const vector4_base &vec) const { return x != vec.x || y != vec.y || z != vec.z || w != vec.w; }
}; };
typedef vector4_base<float> vec4; typedef vector4_base<float> vec4;

View file

@ -1505,6 +1505,7 @@ int CServerInfo::EstimateLatency(int Loc1, int Loc2)
} }
return 99; return 99;
} }
bool CServerInfo::ParseLocation(int *pResult, const char *pString) bool CServerInfo::ParseLocation(int *pResult, const char *pString)
{ {
*pResult = LOC_UNKNOWN; *pResult = LOC_UNKNOWN;
@ -1534,3 +1535,16 @@ bool CServerInfo::ParseLocation(int *pResult, const char *pString)
} }
return true; return true;
} }
void CServerInfo::InfoToString(char *pBuffer, int BufferSize) const
{
str_format(
pBuffer,
BufferSize,
"%s\n"
"Address: ddnet://%s\n"
"My IGN: %s\n",
m_aName,
m_aAddress,
g_Config.m_PlayerName);
}

View file

@ -83,6 +83,7 @@ public:
static int EstimateLatency(int Loc1, int Loc2); static int EstimateLatency(int Loc1, int Loc2);
static bool ParseLocation(int *pResult, const char *pString); static bool ParseLocation(int *pResult, const char *pString);
void InfoToString(char *pBuffer, int BufferSize) const;
}; };
class IServerBrowser : public IInterface class IServerBrowser : public IInterface

View file

@ -1030,8 +1030,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
const CServerInfo *pSelectedServer = ServerBrowser()->SortedGet(m_SelectedIndex); const CServerInfo *pSelectedServer = ServerBrowser()->SortedGet(m_SelectedIndex);
// split off a piece to use for scoreboard // split off a piece to use for scoreboard
ServerDetails.HSplitTop(90.0f, &ServerDetails, &ServerScoreBoard); ServerDetails.HSplitTop(110.0f, &ServerDetails, &ServerScoreBoard);
ServerDetails.HSplitBottom(2.5f, &ServerDetails, 0x0);
// server details // server details
CTextCursor Cursor; CTextCursor Cursor;
@ -1043,8 +1042,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
if(pSelectedServer) if(pSelectedServer)
{ {
ServerDetails.VSplitLeft(5.0f, 0, &ServerDetails); ServerDetails.Margin(5.0f, &ServerDetails);
ServerDetails.Margin(3.0f, &ServerDetails);
CUIRect Row; CUIRect Row;
static CLocConstString s_aLabels[] = { static CLocConstString s_aLabels[] = {
@ -1052,17 +1050,28 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
"Game type", "Game type",
"Ping"}; "Ping"};
CUIRect LeftColumn; // copy info button
CUIRect RightColumn; {
CUIRect Button;
ServerDetails.HSplitBottom(15.0f, &ServerDetails, &Button);
static CButtonContainer s_CopyButton;
if(DoButton_Menu(&s_CopyButton, Localize("Copy info"), 0, &Button))
{
char aInfo[256];
pSelectedServer->InfoToString(aInfo, sizeof(aInfo));
Input()->SetClipboardText(aInfo);
}
}
// ServerDetails.HSplitBottom(2.5f, &ServerDetails, nullptr);
// favorite checkbox
{ {
CUIRect Button; CUIRect Button;
ServerDetails.HSplitBottom(20.0f, &ServerDetails, &Button); ServerDetails.HSplitBottom(20.0f, &ServerDetails, &Button);
CUIRect ButtonAddFav; CUIRect ButtonAddFav;
CUIRect ButtonLeakIp; CUIRect ButtonLeakIp;
Button.VSplitMid(&ButtonAddFav, &ButtonLeakIp); Button.VSplitMid(&ButtonAddFav, &ButtonLeakIp);
ButtonAddFav.VSplitLeft(5.0f, 0, &ButtonAddFav);
static int s_AddFavButton = 0; static int s_AddFavButton = 0;
static int s_LeakIpButton = 0; static int s_LeakIpButton = 0;
if(DoButton_CheckBox_Tristate(&s_AddFavButton, Localize("Favorite"), pSelectedServer->m_Favorite, &ButtonAddFav)) if(DoButton_CheckBox_Tristate(&s_AddFavButton, Localize("Favorite"), pSelectedServer->m_Favorite, &ButtonAddFav))
@ -1091,7 +1100,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
} }
} }
ServerDetails.VSplitLeft(5.0f, 0x0, &ServerDetails); CUIRect LeftColumn, RightColumn;
ServerDetails.VSplitLeft(80.0f, &LeftColumn, &RightColumn); ServerDetails.VSplitLeft(80.0f, &LeftColumn, &RightColumn);
for(auto &Label : s_aLabels) for(auto &Label : s_aLabels)

View file

@ -415,6 +415,21 @@ void CMenus::RenderServerInfo(CUIRect MainView)
TextRender()->Text(0, ServerInfo.x + x, ServerInfo.y + y, 20, aBuf, 250.0f); TextRender()->Text(0, ServerInfo.x + x, ServerInfo.y + y, 20, aBuf, 250.0f);
// copy info button
{
CUIRect Button;
ServerInfo.HSplitBottom(20.0f, &ServerInfo, &Button);
Button.VSplitRight(200.0f, &ServerInfo, &Button);
static CButtonContainer s_CopyButton;
if(DoButton_Menu(&s_CopyButton, Localize("Copy info"), 0, &Button))
{
char aInfo[256];
CurrentServerInfo.InfoToString(aInfo, sizeof(aInfo));
Input()->SetClipboardText(aInfo);
}
}
// favorite checkbox
{ {
CUIRect Button; CUIRect Button;
NETADDR ServerAddr = Client()->ServerAddress(); NETADDR ServerAddr = Client()->ServerAddress();

View file

@ -489,7 +489,7 @@ void CCharacter::GiveNinja()
{ {
m_Core.m_Ninja.m_ActivationTick = GameWorld()->GameTick(); m_Core.m_Ninja.m_ActivationTick = GameWorld()->GameTick();
m_Core.m_aWeapons[WEAPON_NINJA].m_Got = true; m_Core.m_aWeapons[WEAPON_NINJA].m_Got = true;
if(!m_FreezeTime) if(m_FreezeTime > 0)
m_Core.m_aWeapons[WEAPON_NINJA].m_Ammo = -1; m_Core.m_aWeapons[WEAPON_NINJA].m_Ammo = -1;
if(m_Core.m_ActiveWeapon != WEAPON_NINJA) if(m_Core.m_ActiveWeapon != WEAPON_NINJA)
m_LastWeapon = m_Core.m_ActiveWeapon; m_LastWeapon = m_Core.m_ActiveWeapon;
@ -952,12 +952,9 @@ void CCharacter::DDRaceTick()
m_Input.m_Jump = 0; m_Input.m_Jump = 0;
//Hook and weapons are possible in live freeze //Hook and weapons are possible in live freeze
} }
if(m_FreezeTime > 0 || m_FreezeTime == -1)
{
if(m_FreezeTime > 0) if(m_FreezeTime > 0)
{
m_FreezeTime--; m_FreezeTime--;
else
m_Core.m_Ninja.m_ActivationTick = GameWorld()->GameTick();
if(!m_CanMoveInFreeze) if(!m_CanMoveInFreeze)
{ {
m_Input.m_Direction = 0; m_Input.m_Direction = 0;
@ -1046,11 +1043,11 @@ bool CCharacter::Freeze(int Seconds)
{ {
if(!GameWorld()->m_WorldConfig.m_PredictFreeze) if(!GameWorld()->m_WorldConfig.m_PredictFreeze)
return false; return false;
if((Seconds <= 0 || m_Core.m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * GameWorld()->GameTickSpeed()) && Seconds != -1) if(Seconds <= 0 || m_Core.m_Super || m_FreezeTime > Seconds * GameWorld()->GameTickSpeed())
return false; return false;
if(m_Core.m_FreezeStart < GameWorld()->GameTick() - GameWorld()->GameTickSpeed() || Seconds == -1) if(m_Core.m_FreezeStart < GameWorld()->GameTick() - GameWorld()->GameTickSpeed())
{ {
m_FreezeTime = Seconds == -1 ? Seconds : Seconds * GameWorld()->GameTickSpeed(); m_FreezeTime = Seconds * GameWorld()->GameTickSpeed();
m_Core.m_FreezeStart = GameWorld()->GameTick(); m_Core.m_FreezeStart = GameWorld()->GameTick();
return true; return true;
} }

View file

@ -251,7 +251,6 @@ void CCharacterCore::Tick(bool UseInput, bool DoDeferredTick)
if(m_HookState == HOOK_IDLE) if(m_HookState == HOOK_IDLE)
{ {
SetHookedPlayer(-1); SetHookedPlayer(-1);
m_HookState = HOOK_IDLE;
m_HookPos = m_Pos; m_HookPos = m_Pos;
} }
else if(m_HookState >= HOOK_RETRACT_START && m_HookState < HOOK_RETRACT_END) else if(m_HookState >= HOOK_RETRACT_START && m_HookState < HOOK_RETRACT_END)

View file

@ -976,12 +976,12 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
} }
// change eyes and use ninja graphic if player is frozen // change eyes and use ninja graphic if player is frozen
if(m_Core.m_DeepFrozen || m_FreezeTime > 0 || m_FreezeTime == -1 || m_Core.m_LiveFrozen) if(m_Core.m_DeepFrozen || m_FreezeTime > 0 || m_Core.m_LiveFrozen)
{ {
if(Emote == EMOTE_NORMAL) if(Emote == EMOTE_NORMAL)
Emote = (m_Core.m_DeepFrozen || m_Core.m_LiveFrozen) ? EMOTE_PAIN : EMOTE_BLINK; Emote = (m_Core.m_DeepFrozen || m_Core.m_LiveFrozen) ? EMOTE_PAIN : EMOTE_BLINK;
if((m_Core.m_DeepFrozen || m_FreezeTime > 0 || m_FreezeTime == -1) && SnappingClientVersion < VERSION_DDNET_NEW_HUD) if((m_Core.m_DeepFrozen || m_FreezeTime > 0) && SnappingClientVersion < VERSION_DDNET_NEW_HUD)
Weapon = WEAPON_NINJA; Weapon = WEAPON_NINJA;
} }
@ -1008,8 +1008,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
} }
// change eyes, use ninja graphic and set ammo count if player has ninjajetpack // change eyes, use ninja graphic and set ammo count if player has ninjajetpack
if(m_pPlayer->m_NinjaJetpack && m_Core.m_Jetpack && m_Core.m_ActiveWeapon == WEAPON_GUN && !m_Core.m_DeepFrozen && 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)
!(m_FreezeTime > 0 || m_FreezeTime == -1) && !m_Core.m_HasTelegunGun)
{ {
if(Emote == EMOTE_NORMAL) if(Emote == EMOTE_NORMAL)
Emote = EMOTE_HAPPY; Emote = EMOTE_HAPPY;
@ -1023,12 +1022,12 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
Health = m_Health; Health = m_Health;
Armor = m_Armor; Armor = m_Armor;
if(m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo > 0) if(m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo > 0)
AmmoCount = (!m_FreezeTime) ? m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo : 0; AmmoCount = (m_FreezeTime > 0) ? m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo : 0;
} }
if(GetPlayer()->IsAfk() || GetPlayer()->IsPaused()) if(GetPlayer()->IsAfk() || GetPlayer()->IsPaused())
{ {
if(m_FreezeTime > 0 || m_FreezeTime == -1 || m_Core.m_DeepFrozen || m_Core.m_LiveFrozen) if(m_FreezeTime > 0 || m_Core.m_DeepFrozen || m_Core.m_LiveFrozen)
Emote = EMOTE_NORMAL; Emote = EMOTE_NORMAL;
else else
Emote = EMOTE_BLINK; Emote = EMOTE_BLINK;
@ -1084,7 +1083,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
pCharacter->m_Weapon = Weapon; pCharacter->m_Weapon = Weapon;
pCharacter->m_AmmoCount = AmmoCount; pCharacter->m_AmmoCount = AmmoCount;
if(m_FreezeTime > 0 || m_FreezeTime == -1 || m_Core.m_DeepFrozen) if(m_FreezeTime > 0 || m_Core.m_DeepFrozen)
pCharacter->m_AmmoCount = m_Core.m_FreezeStart + g_Config.m_SvFreezeDelay * Server()->TickSpeed(); pCharacter->m_AmmoCount = m_Core.m_FreezeStart + g_Config.m_SvFreezeDelay * Server()->TickSpeed();
else if(Weapon == WEAPON_NINJA) else if(Weapon == WEAPON_NINJA)
pCharacter->m_AmmoCount = m_Core.m_Ninja.m_ActivationTick + g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000; pCharacter->m_AmmoCount = m_Core.m_Ninja.m_ActivationTick + g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000;
@ -1999,7 +1998,7 @@ void CCharacter::SetRescue()
void CCharacter::DDRaceTick() void CCharacter::DDRaceTick()
{ {
mem_copy(&m_Input, &m_SavedInput, sizeof(m_Input)); mem_copy(&m_Input, &m_SavedInput, sizeof(m_Input));
m_Armor = (m_FreezeTime >= 0) ? clamp(10 - (m_FreezeTime / 15), 0, 10) : 0; m_Armor = clamp(10 - (m_FreezeTime / 15), 0, 10);
if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0) if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0)
m_LastMove = Server()->Tick(); m_LastMove = Server()->Tick();
@ -2009,16 +2008,13 @@ void CCharacter::DDRaceTick()
m_Input.m_Jump = 0; m_Input.m_Jump = 0;
// Hook is possible in live freeze // Hook is possible in live freeze
} }
if(m_FreezeTime > 0 || m_FreezeTime == -1) if(m_FreezeTime > 0)
{ {
if(m_FreezeTime % Server()->TickSpeed() == Server()->TickSpeed() - 1 || m_FreezeTime == -1) if(m_FreezeTime % Server()->TickSpeed() == Server()->TickSpeed() - 1)
{ {
GameServer()->CreateDamageInd(m_Pos, 0, (m_FreezeTime + 1) / Server()->TickSpeed(), TeamMask() & GameServer()->ClientsMaskExcludeClientVersionAndHigher(VERSION_DDNET_NEW_HUD)); GameServer()->CreateDamageInd(m_Pos, 0, (m_FreezeTime + 1) / Server()->TickSpeed(), TeamMask() & GameServer()->ClientsMaskExcludeClientVersionAndHigher(VERSION_DDNET_NEW_HUD));
} }
if(m_FreezeTime > 0)
m_FreezeTime--; m_FreezeTime--;
else
m_Core.m_Ninja.m_ActivationTick = Server()->Tick();
m_Input.m_Direction = 0; m_Input.m_Direction = 0;
m_Input.m_Jump = 0; m_Input.m_Jump = 0;
m_Input.m_Hook = 0; m_Input.m_Hook = 0;
@ -2137,12 +2133,12 @@ void CCharacter::DDRacePostCoreTick()
bool CCharacter::Freeze(int Seconds) bool CCharacter::Freeze(int Seconds)
{ {
if((Seconds <= 0 || m_Core.m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * Server()->TickSpeed()) && Seconds != -1) if(Seconds <= 0 || m_Core.m_Super || m_FreezeTime > Seconds * Server()->TickSpeed())
return false; return false;
if(m_Core.m_FreezeStart < Server()->Tick() - Server()->TickSpeed() || Seconds == -1) if(m_Core.m_FreezeStart < Server()->Tick() - Server()->TickSpeed())
{ {
m_Armor = 0; m_Armor = 0;
m_FreezeTime = Seconds == -1 ? Seconds : Seconds * Server()->TickSpeed(); m_FreezeTime = Seconds * Server()->TickSpeed();
m_Core.m_FreezeStart = Server()->Tick(); m_Core.m_FreezeStart = Server()->Tick();
return true; return true;
} }