move DDNetCharacterDisplayInfo to DDNetCharacter

- add default value option to NetworkValues
- rename m_FreezeTick to m_FreezeStart
This commit is contained in:
c0d3d3v 2022-05-24 17:26:49 +02:00
parent 3e54b35955
commit df52df9d4a
No known key found for this signature in database
GPG key ID: 068AF680530DFF31
17 changed files with 129 additions and 127 deletions

View file

@ -225,17 +225,22 @@ class NetObject:
def emit_validate(self, base_item):
lines = ["case %s:" % self.enum_name]
lines += ["{"]
if self.validate_size:
lines += ["\t%s *pObj = (%s *)pData;"%(self.struct_name, self.struct_name)]
lines += ["\tif((int)sizeof(*pObj) > Size) return -1;"]
prev_len = len(lines)
variables = self.variables
if base_item:
variables += base_item.variables
validate_variables_lines = []
for v in variables:
lines += ["\t"+line for line in v.emit_validate()]
if not self.validate_size and prev_len != len(lines):
raise ValueError("Can't use members that need validation in a struct whose size isn't validated")
validate_variable_lines = ["\t"+line for line in v.emit_validate()]
if not self.validate_size and len(validate_variable_lines) > 0 and v.default is None:
raise ValueError("Members that require validation and do not have a default value cannot be used in a structure whose size is not validated")
validate_variables_lines += validate_variable_lines
if self.validate_size or validate_variables_lines:
lines += ["\t%s *pObj = (%s *)pData;"%(self.struct_name, self.struct_name)]
if self.validate_size:
lines += ["\tif((int)sizeof(*pObj) > Size) return -1;"]
lines += validate_variables_lines
lines += ["\treturn 0;"]
lines += ["}"]
return lines
@ -297,8 +302,9 @@ class NetMessageEx(NetMessage):
class NetVariable:
def __init__(self, name):
def __init__(self, name, default=None):
self.name = name
self.default = None if default is None else str(default)
def emit_declaration(self):
return []
def emit_validate(self):
@ -338,13 +344,15 @@ class NetIntAny(NetVariable):
def emit_declaration(self):
return ["int %s;"%self.name]
def emit_unpack(self):
return ["pMsg->%s = pUnpacker->GetInt();" % self.name]
if self.default is None:
return ["pMsg->%s = pUnpacker->GetInt();" % self.name]
return ["pMsg->%s = pUnpacker->GetIntOrDefault(%s);" % (self.name, self.default)]
def emit_pack(self):
return ["pPacker->AddInt(%s);" % self.name]
class NetIntRange(NetIntAny):
def __init__(self, name, min_val, max_val):
NetIntAny.__init__(self,name)
def __init__(self, name, min_val, max_val, default=None):
NetIntAny.__init__(self,name,default=default)
self.min = str(min_val)
self.max = str(max_val)
def emit_validate(self):
@ -353,12 +361,13 @@ class NetIntRange(NetIntAny):
return ["if(pMsg->%s < %s || pMsg->%s > %s) { m_pMsgFailedOn = \"%s\"; break; }" % (self.name, self.min, self.name, self.max, self.name)]
class NetBool(NetIntRange):
def __init__(self, name):
NetIntRange.__init__(self,name,0,1)
def __init__(self, name, default=None):
default = None if default is None else int(default)
NetIntRange.__init__(self,name,0,1,default=default)
class NetTick(NetIntAny):
def __init__(self, name):
NetIntAny.__init__(self,name)
def __init__(self, name, default=None):
NetIntAny.__init__(self,name,default=default)
class NetArray(NetVariable):
def __init__(self, var, size):

View file

@ -11,7 +11,7 @@ CharacterFlags = ["SOLO", "JETPACK", "NO_COLLISION", "ENDLESS_HOOK", "ENDLESS_JU
"NO_HAMMER_HIT", "NO_SHOTGUN_HIT", "NO_GRENADE_HIT", "NO_LASER_HIT", "NO_HOOK",
"TELEGUN_GUN", "TELEGUN_GRENADE", "TELEGUN_LASER",
"WEAPON_HAMMER", "WEAPON_GUN", "WEAPON_SHOTGUN", "WEAPON_GRENADE", "WEAPON_LASER", "WEAPON_NINJA",
"NO_MOVEMENTS"]
"NO_MOVEMENTS", "IN_FREEZE", "PRACTICE_MODE"]
GameInfoFlags = [
"TIMESCORE", "GAMETYPE_RACE", "GAMETYPE_FASTCAP", "GAMETYPE_FNG",
"GAMETYPE_DDRACE", "GAMETYPE_DDNET", "GAMETYPE_BLOCK_WORLDS",
@ -237,21 +237,20 @@ Objects = [
NetObjectEx("DDNetCharacter", "character@netobj.ddnet.tw", [
NetIntAny("m_Flags"),
NetTick("m_FreezeEnd"),
NetIntRange("m_Jumps", -1, 255),
NetIntRange("m_Jumps", -1, 255, 2),
NetIntAny("m_TeleCheckpoint"),
NetIntRange("m_StrongWeakID", 0, 'MAX_CLIENTS-1'),
]),
NetIntRange("m_StrongWeakID", 0, 'MAX_CLIENTS-1', 0),
NetObjectEx("DDNetCharacterDisplayInfo", "character-display-info@netobj.ddnet.tw", [
NetIntRange("m_JumpedTotal", 0, 255),
NetTick("m_NinjaActivationTick"),
NetTick("m_FreezeTick"),
NetBool("m_IsInFreeze"),
NetBool("m_IsInPracticeMode"),
NetIntAny("m_TargetX"),
NetIntAny("m_TargetY"),
NetIntAny("m_RampValue"),
]),
# New data fields for jump display, freeze bar and ninja bar
# Default values indicate that these values should not be used
NetIntRange("m_JumpedTotal", -1, 255, -1),
NetTick("m_NinjaActivationTick", -1),
NetTick("m_FreezeStart", -1),
# New data fields for improved target accuracy and speed display
NetIntAny("m_TargetX", 0),
NetIntAny("m_TargetY", 0),
NetIntAny("m_RampValue", 1),
], validate_size=False),
NetObjectEx("DDNetPlayer", "player@netobj.ddnet.tw", [
NetIntAny("m_Flags"),

View file

@ -974,11 +974,11 @@ void CServer::DoSnapshot()
int Crc = pData->Crc();
// remove old snapshos
// remove old snapshots
// keep 3 seconds worth of snapshots
m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentGameTick - SERVER_TICK_SPEED * 3);
// save it the snapshot
// save the snapshot
m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, pData, 0);
// find snapshot that we can perform delta against

View file

@ -10,13 +10,14 @@ void CFreezeBars::RenderFreezeBar(const int ClientID)
// pCharacter contains the predicted character for local players or the last snap for players who are spectated
CCharacterCore *pCharacter = &m_pClient->m_aClients[ClientID].m_Predicted;
if(pCharacter->m_FreezeEnd <= 0.0f || pCharacter->m_FreezeTick == 0 || !m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo || (pCharacter->m_IsInFreeze && g_Config.m_ClFreezeBarsAlphaInsideFreeze == 0))
if(pCharacter->m_FreezeEnd <= 0.0f || pCharacter->m_FreezeStart == 0 || !m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo || (pCharacter->m_IsInFreeze && g_Config.m_ClFreezeBarsAlphaInsideFreeze == 0))
{
return;
}
const int Max = pCharacter->m_FreezeEnd - pCharacter->m_FreezeTick;
float FreezeProgress = clamp(Max - (Client()->GameTick(g_Config.m_ClDummy) - pCharacter->m_FreezeTick), 0, Max) / (float)Max;
const int Max = pCharacter->m_FreezeEnd - pCharacter->m_FreezeStart;
float FreezeProgress = clamp(Max - (Client()->GameTick(g_Config.m_ClDummy) - pCharacter->m_FreezeStart), 0, Max) / (float)Max;
if(FreezeProgress <= 0.0f)
{
return;

View file

@ -1126,7 +1126,7 @@ void CHud::RenderPlayerState(const int ClientID)
{
y += 12;
}
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo && m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo.m_IsInPracticeMode)
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo && m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedData.m_Flags & CHARACTERFLAG_PRACTICE_MODE)
{
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudPracticeMode);
Graphics()->RenderQuadContainerAsSprite(m_HudQuadContainerIndex, m_PracticeModeOffset, x, y);
@ -1424,15 +1424,15 @@ void CHud::RenderMovementInformation(const int ClientID)
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo)
{
// On DDNet servers the actual speed on X axis is displayed, i.e. VelspeedX * Ramp
DisplaySpeedX *= (m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo.m_RampValue / 1000.0f);
DisplaySpeedX *= (m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedData.m_RampValue / 1000.0f);
}
float Angle = 0.0f;
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo)
{
// On DDNet servers the more accurate angle is displayed, calculated from the target coordinates
CNetObj_DDNetCharacterDisplayInfo *CharacterDisplayInfo = &m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo;
Angle = atan2f(CharacterDisplayInfo->m_TargetY, CharacterDisplayInfo->m_TargetX);
CNetObj_DDNetCharacter *ExtendedData = &m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedData;
Angle = atan2f(ExtendedData->m_TargetY, ExtendedData->m_TargetX);
}
else
{

View file

@ -84,19 +84,19 @@ float CPlayers::GetPlayerTargetAngle(
AngleIntraTick = Client()->IntraGameTick(g_Config.m_ClDummy);
if(ClientID >= 0 && m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo)
{
CNetObj_DDNetCharacterDisplayInfo *CharacterDisplayInfo = &m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo;
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_PrevExtendedDisplayInfo)
CNetObj_DDNetCharacter *ExtendedData = &m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedData;
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_PrevExtendedData)
{
const CNetObj_DDNetCharacterDisplayInfo *PrevCharacterDisplayInfo = m_pClient->m_Snap.m_aCharacters[ClientID].m_PrevExtendedDisplayInfo;
const CNetObj_DDNetCharacter *PrevExtendedData = m_pClient->m_Snap.m_aCharacters[ClientID].m_PrevExtendedData;
float MixX = mix((float)PrevCharacterDisplayInfo->m_TargetX, (float)CharacterDisplayInfo->m_TargetX, AngleIntraTick);
float MixY = mix((float)PrevCharacterDisplayInfo->m_TargetY, (float)CharacterDisplayInfo->m_TargetY, AngleIntraTick);
float MixX = mix((float)PrevExtendedData->m_TargetX, (float)ExtendedData->m_TargetX, AngleIntraTick);
float MixY = mix((float)PrevExtendedData->m_TargetY, (float)ExtendedData->m_TargetY, AngleIntraTick);
return angle(vec2(MixX, MixY));
}
else
{
return angle(vec2(CharacterDisplayInfo->m_TargetX, CharacterDisplayInfo->m_TargetY));
return angle(vec2(ExtendedData->m_TargetX, ExtendedData->m_TargetY));
}
}
else

View file

@ -1321,8 +1321,13 @@ void CGameClient::OnNewSnapshot()
if(Item.m_ID < MAX_CLIENTS)
{
m_Snap.m_aCharacters[Item.m_ID].m_ExtendedData = *pCharacterData;
m_Snap.m_aCharacters[Item.m_ID].m_PrevExtendedData = (const CNetObj_DDNetCharacter *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_DDNETCHARACTER, Item.m_ID);
m_Snap.m_aCharacters[Item.m_ID].m_HasExtendedData = true;
m_Snap.m_aCharacters[Item.m_ID].m_HasExtendedDisplayInfo = false;
if(Item.m_DataSize >= 44)
{
m_Snap.m_aCharacters[Item.m_ID].m_HasExtendedDisplayInfo = true;
}
CClientData *pClient = &m_aClients[Item.m_ID];
// Collision
pClient->m_Solo = pCharacterData->m_Flags & CHARACTERFLAG_SOLO;
@ -1352,20 +1357,6 @@ void CGameClient::OnNewSnapshot()
pClient->m_Predicted.ReadDDNet(pCharacterData);
}
}
else if(Item.m_Type == NETOBJTYPE_DDNETCHARACTERDISPLAYINFO)
{
const CNetObj_DDNetCharacterDisplayInfo *pCharacterDisplayInfo = (const CNetObj_DDNetCharacterDisplayInfo *)pData;
if(Item.m_ID < MAX_CLIENTS)
{
m_Snap.m_aCharacters[Item.m_ID].m_ExtendedDisplayInfo = *pCharacterDisplayInfo;
m_Snap.m_aCharacters[Item.m_ID].m_PrevExtendedDisplayInfo = (const CNetObj_DDNetCharacterDisplayInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_DDNETCHARACTERDISPLAYINFO, Item.m_ID);
m_Snap.m_aCharacters[Item.m_ID].m_HasExtendedDisplayInfo = true;
CClientData *pClient = &m_aClients[Item.m_ID];
pClient->m_Predicted.ReadDDNetDisplayInfo(pCharacterDisplayInfo);
}
}
else if(Item.m_Type == NETOBJTYPE_SPECCHAR)
{
const CNetObj_SpecChar *pSpecCharData = (const CNetObj_SpecChar *)pData;
@ -2432,7 +2423,6 @@ void CGameClient::UpdatePrediction()
int GameTeam = (m_Snap.m_pGameInfoObj->m_GameFlags & GAMEFLAG_TEAMS) ? m_aClients[i].m_Team : i;
m_GameWorld.NetCharAdd(i, &m_Snap.m_aCharacters[i].m_Cur,
m_Snap.m_aCharacters[i].m_HasExtendedData ? &m_Snap.m_aCharacters[i].m_ExtendedData : 0,
m_Snap.m_aCharacters[i].m_HasExtendedDisplayInfo ? &m_Snap.m_aCharacters[i].m_ExtendedDisplayInfo : 0,
GameTeam, IsLocal);
}

View file

@ -305,10 +305,8 @@ public:
CNetObj_Character m_Cur;
CNetObj_DDNetCharacter m_ExtendedData;
const CNetObj_DDNetCharacter *m_PrevExtendedData;
bool m_HasExtendedData;
const CNetObj_DDNetCharacterDisplayInfo *m_PrevExtendedDisplayInfo;
CNetObj_DDNetCharacterDisplayInfo m_ExtendedDisplayInfo;
bool m_HasExtendedDisplayInfo;
// interpolated position

View file

@ -1050,10 +1050,10 @@ bool CCharacter::Freeze(int Seconds)
return false;
if((Seconds <= 0 || m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * GameWorld()->GameTickSpeed()) && Seconds != -1)
return false;
if(m_Core.m_FreezeTick < GameWorld()->GameTick() - GameWorld()->GameTickSpeed() || Seconds == -1)
if(m_Core.m_FreezeStart < GameWorld()->GameTick() - GameWorld()->GameTickSpeed() || Seconds == -1)
{
m_FreezeTime = Seconds == -1 ? Seconds : Seconds * GameWorld()->GameTickSpeed();
m_Core.m_FreezeTick = GameWorld()->GameTick();
m_Core.m_FreezeStart = GameWorld()->GameTick();
return true;
}
return false;
@ -1071,7 +1071,7 @@ bool CCharacter::UnFreeze()
if(!m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Got)
m_Core.m_ActiveWeapon = WEAPON_GUN;
m_FreezeTime = 0;
m_Core.m_FreezeTick = 0;
m_Core.m_FreezeStart = 0;
m_FrozenLastTick = true;
return true;
}
@ -1115,7 +1115,7 @@ CTeamsCore *CCharacter::TeamsCore()
return m_Core.m_pTeams;
}
CCharacter::CCharacter(CGameWorld *pGameWorld, int ID, CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, CNetObj_DDNetCharacterDisplayInfo *pExtendedDisplayInfo) :
CCharacter::CCharacter(CGameWorld *pGameWorld, int ID, CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended) :
CEntity(pGameWorld, CGameWorld::ENTTYPE_CHARACTER, vec2(0, 0), CCharacterCore::PhysicalSize())
{
m_ID = ID;
@ -1148,7 +1148,7 @@ CCharacter::CCharacter(CGameWorld *pGameWorld, int ID, CNetObj_Character *pChar,
m_LatestPrevInput = m_LatestInput = m_PrevInput = m_SavedInput = m_Input;
ResetPrediction();
Read(pChar, pExtended, pExtendedDisplayInfo, false);
Read(pChar, pExtended, false);
}
void CCharacter::ResetPrediction()
@ -1164,7 +1164,7 @@ void CCharacter::ResetPrediction()
m_Core.m_NoCollision = false;
m_NumInputs = 0;
m_FreezeTime = 0;
m_Core.m_FreezeTick = 0;
m_Core.m_FreezeStart = 0;
m_Core.m_IsInFreeze = false;
m_DeepFreeze = false;
m_LiveFreeze = false;
@ -1184,15 +1184,13 @@ void CCharacter::ResetPrediction()
m_LastTuneZoneTick = 0;
}
void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, CNetObj_DDNetCharacterDisplayInfo *pExtendedDisplayInfo, bool IsLocal)
void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, bool IsLocal)
{
m_Core.ReadCharacterCore((const CNetObj_CharacterCore *)pChar);
m_IsLocal = IsLocal;
if(pExtended)
{
m_Core.ReadDDNet(pExtended);
SetSolo(pExtended->m_Flags & CHARACTERFLAG_SOLO);
m_Super = pExtended->m_Flags & CHARACTERFLAG_SUPER;
if(m_Super)
@ -1235,6 +1233,8 @@ void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtende
}
else
UnFreeze();
m_Core.ReadDDNet(pExtended);
}
else
{
@ -1306,7 +1306,7 @@ void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtende
// detect unfreeze (in case the player was frozen in the tile prediction and not correctly unfrozen)
if(pChar->m_Emote != EMOTE_PAIN && pChar->m_Emote != EMOTE_NORMAL)
m_DeepFreeze = false;
if(pChar->m_Weapon != WEAPON_NINJA || pChar->m_AttackTick > m_Core.m_FreezeTick || absolute(pChar->m_VelX) == 256 * 10 || !GameWorld()->m_WorldConfig.m_PredictFreeze)
if(pChar->m_Weapon != WEAPON_NINJA || pChar->m_AttackTick > m_Core.m_FreezeStart || absolute(pChar->m_VelX) == 256 * 10 || !GameWorld()->m_WorldConfig.m_PredictFreeze)
{
m_DeepFreeze = false;
UnFreeze();
@ -1344,8 +1344,17 @@ void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtende
mem_zero(&m_SavedInput, sizeof(m_SavedInput));
m_Input.m_Direction = m_SavedInput.m_Direction = m_Core.m_Direction;
m_Input.m_Hook = m_SavedInput.m_Hook = (m_Core.m_HookState != HOOK_IDLE);
m_Input.m_TargetX = m_SavedInput.m_TargetX = cosf(pChar->m_Angle / 256.0f) * 256.0f;
m_Input.m_TargetY = m_SavedInput.m_TargetY = sinf(pChar->m_Angle / 256.0f) * 256.0f;
if(pExtended)
{
m_Input.m_TargetX = m_SavedInput.m_TargetX = pExtended->m_TargetX;
m_Input.m_TargetY = m_SavedInput.m_TargetY = pExtended->m_TargetY;
}
else
{
m_Input.m_TargetX = m_SavedInput.m_TargetX = cosf(pChar->m_Angle / 256.0f) * 256.0f;
m_Input.m_TargetY = m_SavedInput.m_TargetY = sinf(pChar->m_Angle / 256.0f) * 256.0f;
}
}
// in most cases the reload timer can be determined from the last attack tick
@ -1360,22 +1369,6 @@ void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtende
m_ReloadTimer = maximum(0, m_AttackTick + FireDelayTicks - GameWorld()->GameTick());
}
}
if(pExtendedDisplayInfo)
{
if(GameWorld()->m_WorldConfig.m_PredictFreeze)
{
m_Core.m_FreezeTick = pExtendedDisplayInfo->m_FreezeTick;
}
m_Core.m_IsInFreeze = pExtendedDisplayInfo->m_IsInFreeze;
m_Core.m_Ninja.m_ActivationTick = pExtendedDisplayInfo->m_NinjaActivationTick;
m_Core.m_JumpedTotal = pExtendedDisplayInfo->m_JumpedTotal;
if(!IsLocal)
{
m_Input.m_TargetX = pExtendedDisplayInfo->m_TargetX;
m_Input.m_TargetY = pExtendedDisplayInfo->m_TargetY;
}
}
}
void CCharacter::SetCoreWorld(CGameWorld *pGameWorld)

View file

@ -129,8 +129,8 @@ public:
int GetAttackTick() { return m_AttackTick; }
int GetStrongWeakID() { return m_StrongWeakID; }
CCharacter(CGameWorld *pGameWorld, int ID, CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended = 0, CNetObj_DDNetCharacterDisplayInfo *pExtendedDisplayInfo = 0);
void Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, CNetObj_DDNetCharacterDisplayInfo *pExtendedDisplayInfo, bool IsLocal);
CCharacter(CGameWorld *pGameWorld, int ID, CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended = 0);
void Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, bool IsLocal);
void SetCoreWorld(CGameWorld *pGameWorld);
int m_LastSnapWeapon;

View file

@ -371,17 +371,17 @@ void CGameWorld::NetObjBegin()
OnModified();
}
void CGameWorld::NetCharAdd(int ObjID, CNetObj_Character *pCharObj, CNetObj_DDNetCharacter *pExtended, CNetObj_DDNetCharacterDisplayInfo *pExtendedDisplayInfo, int GameTeam, bool IsLocal)
void CGameWorld::NetCharAdd(int ObjID, CNetObj_Character *pCharObj, CNetObj_DDNetCharacter *pExtended, int GameTeam, bool IsLocal)
{
CCharacter *pChar;
if((pChar = (CCharacter *)GetEntity(ObjID, ENTTYPE_CHARACTER)))
{
pChar->Read(pCharObj, pExtended, pExtendedDisplayInfo, IsLocal);
pChar->Read(pCharObj, pExtended, IsLocal);
pChar->Keep();
}
else
{
pChar = new CCharacter(this, ObjID, pCharObj, pExtended, pExtendedDisplayInfo);
pChar = new CCharacter(this, ObjID, pCharObj, pExtended);
InsertEntity(pChar);
}

View file

@ -85,7 +85,7 @@ public:
void OnModified();
void NetObjBegin();
void NetCharAdd(int ObjID, CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, CNetObj_DDNetCharacterDisplayInfo *pExtendedDisplayInfo, int GameTeam, bool IsLocal);
void NetCharAdd(int ObjID, CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, int GameTeam, bool IsLocal);
void NetObjAdd(int ObjID, int ObjType, const void *pObjData, const CNetObj_EntityEx *pDataEx);
void NetObjEnd(int LocalID);
void CopyWorld(CGameWorld *pFrom);

View file

@ -105,7 +105,7 @@ void CCharacterCore::Reset()
m_HasTelegunGun = false;
m_HasTelegunGrenade = false;
m_HasTelegunLaser = false;
m_FreezeTick = 0;
m_FreezeStart = 0;
m_FreezeEnd = 0;
m_IsInFreeze = false;
m_DeepFrozen = false;
@ -599,14 +599,22 @@ void CCharacterCore::ReadDDNet(const CNetObj_DDNetCharacter *pObjDDNet)
// Available jumps
m_Jumps = pObjDDNet->m_Jumps;
}
void CCharacterCore::ReadDDNetDisplayInfo(const CNetObj_DDNetCharacterDisplayInfo *pObjDDNet)
{
m_JumpedTotal = pObjDDNet->m_JumpedTotal;
m_Ninja.m_ActivationTick = pObjDDNet->m_NinjaActivationTick;
m_FreezeTick = pObjDDNet->m_FreezeTick;
m_IsInFreeze = pObjDDNet->m_IsInFreeze;
// 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;
}
}
void CCharacterCore::Quantize()

View file

@ -291,7 +291,6 @@ public:
void SetTeamsCore(CTeamsCore *pTeams);
void SetTeleOuts(std::map<int, std::vector<vec2>> *pTeleOuts);
void ReadDDNet(const CNetObj_DDNetCharacter *pObjDDNet);
void ReadDDNetDisplayInfo(const CNetObj_DDNetCharacterDisplayInfo *pObjDDNet);
bool m_Solo;
bool m_Jetpack;
bool m_NoCollision;
@ -306,7 +305,7 @@ public:
bool m_HasTelegunGun;
bool m_HasTelegunGrenade;
bool m_HasTelegunLaser;
int m_FreezeTick;
int m_FreezeStart;
int m_FreezeEnd;
bool m_IsInFreeze;
bool m_DeepFrozen;

View file

@ -12,6 +12,7 @@
#include <game/server/player.h>
#include "character.h"
#include "game/generated/protocol.h"
#include "laser.h"
#include "projectile.h"
@ -1045,7 +1046,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
pCharacter->m_AmmoCount = AmmoCount;
if(m_FreezeTime > 0 || m_FreezeTime == -1 || m_DeepFreeze)
pCharacter->m_AmmoCount = m_Core.m_FreezeTick + g_Config.m_SvFreezeDelay * Server()->TickSpeed();
pCharacter->m_AmmoCount = m_Core.m_FreezeStart + g_Config.m_SvFreezeDelay * Server()->TickSpeed();
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;
@ -1166,17 +1167,21 @@ void CCharacter::Snap(int SnappingClient)
pDDNetCharacter->m_TeleCheckpoint = m_TeleCheckpoint;
pDDNetCharacter->m_StrongWeakID = m_StrongWeakID;
CNetObj_DDNetCharacterDisplayInfo *pDDNetCharacterDisplayInfo = static_cast<CNetObj_DDNetCharacterDisplayInfo *>(Server()->SnapNewItem(NETOBJTYPE_DDNETCHARACTERDISPLAYINFO, ID, sizeof(CNetObj_DDNetCharacterDisplayInfo)));
if(!pDDNetCharacterDisplayInfo)
return;
pDDNetCharacterDisplayInfo->m_JumpedTotal = m_Core.m_JumpedTotal;
pDDNetCharacterDisplayInfo->m_NinjaActivationTick = m_Core.m_Ninja.m_ActivationTick;
pDDNetCharacterDisplayInfo->m_FreezeTick = m_Core.m_FreezeTick;
pDDNetCharacterDisplayInfo->m_IsInFreeze = m_Core.m_IsInFreeze;
pDDNetCharacterDisplayInfo->m_IsInPracticeMode = Teams()->IsPractice(Team());
pDDNetCharacterDisplayInfo->m_TargetX = m_Core.m_Input.m_TargetX;
pDDNetCharacterDisplayInfo->m_TargetY = m_Core.m_Input.m_TargetY;
pDDNetCharacterDisplayInfo->m_RampValue = round_to_int(VelocityRamp(length(m_Core.m_Vel) * 50, m_Core.m_Tuning.m_VelrampStart, m_Core.m_Tuning.m_VelrampRange, m_Core.m_Tuning.m_VelrampCurvature) * 1000.0f);
// Display Informations
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;
pDDNetCharacter->m_RampValue = round_to_int(VelocityRamp(length(m_Core.m_Vel) * 50, m_Core.m_Tuning.m_VelrampStart, m_Core.m_Tuning.m_VelrampRange, m_Core.m_Tuning.m_VelrampCurvature) * 1000.0f);
}
// DDRace
@ -2207,11 +2212,11 @@ bool CCharacter::Freeze(int Seconds)
{
if((Seconds <= 0 || m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * Server()->TickSpeed()) && Seconds != -1)
return false;
if(m_Core.m_FreezeTick < Server()->Tick() - Server()->TickSpeed() || Seconds == -1)
if(m_Core.m_FreezeStart < Server()->Tick() - Server()->TickSpeed() || Seconds == -1)
{
m_Armor = 0;
m_FreezeTime = Seconds == -1 ? Seconds : Seconds * Server()->TickSpeed();
m_Core.m_FreezeTick = Server()->Tick();
m_Core.m_FreezeStart = Server()->Tick();
return true;
}
return false;
@ -2230,7 +2235,7 @@ bool CCharacter::UnFreeze()
if(!m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Got)
m_Core.m_ActiveWeapon = WEAPON_GUN;
m_FreezeTime = 0;
m_Core.m_FreezeTick = 0;
m_Core.m_FreezeStart = 0;
m_FrozenLastTick = true;
return true;
}

View file

@ -38,7 +38,7 @@ void CSaveTee::Save(CCharacter *pChr)
m_Jetpack = pChr->m_Jetpack;
m_NinjaJetpack = pChr->m_NinjaJetpack;
m_FreezeTime = pChr->m_FreezeTime;
m_FreezeTick = pChr->Server()->Tick() - pChr->m_Core.m_FreezeTick;
m_FreezeStart = pChr->Server()->Tick() - pChr->m_Core.m_FreezeStart;
m_DeepFreeze = pChr->m_DeepFreeze;
m_LiveFreeze = pChr->m_LiveFreeze;
@ -133,7 +133,7 @@ void CSaveTee::Load(CCharacter *pChr, int Team, bool IsSwap)
pChr->m_Jetpack = m_Jetpack;
pChr->m_NinjaJetpack = m_NinjaJetpack;
pChr->m_FreezeTime = m_FreezeTime;
pChr->m_Core.m_FreezeTick = pChr->Server()->Tick() - m_FreezeTick;
pChr->m_Core.m_FreezeStart = pChr->Server()->Tick() - m_FreezeStart;
pChr->m_DeepFreeze = m_DeepFreeze;
pChr->m_LiveFreeze = m_LiveFreeze;
@ -269,7 +269,7 @@ char *CSaveTee::GetString(const CSaveTeam *pTeam)
m_aWeapons[5].m_AmmoRegenStart, m_aWeapons[5].m_Ammo, m_aWeapons[5].m_Ammocost, m_aWeapons[5].m_Got,
m_LastWeapon, m_QueuedWeapon,
// tee states
m_SuperJump, m_Jetpack, m_NinjaJetpack, m_FreezeTime, m_FreezeTick, m_DeepFreeze, m_EndlessHook,
m_SuperJump, m_Jetpack, m_NinjaJetpack, m_FreezeTime, m_FreezeStart, m_DeepFreeze, m_EndlessHook,
m_DDRaceState, m_Hit, m_Collision, m_TuneZone, m_TuneZoneOld, m_Hook, m_Time,
(int)m_Pos.x, (int)m_Pos.y, (int)m_PrevPos.x, (int)m_PrevPos.y,
m_TeleCheckpoint, m_LastPenalty,
@ -342,7 +342,7 @@ int CSaveTee::FromString(const char *String)
&m_aWeapons[5].m_AmmoRegenStart, &m_aWeapons[5].m_Ammo, &m_aWeapons[5].m_Ammocost, &m_aWeapons[5].m_Got,
&m_LastWeapon, &m_QueuedWeapon,
// tee states
&m_SuperJump, &m_Jetpack, &m_NinjaJetpack, &m_FreezeTime, &m_FreezeTick, &m_DeepFreeze, &m_EndlessHook,
&m_SuperJump, &m_Jetpack, &m_NinjaJetpack, &m_FreezeTime, &m_FreezeStart, &m_DeepFreeze, &m_EndlessHook,
&m_DDRaceState, &m_Hit, &m_Collision, &m_TuneZone, &m_TuneZoneOld, &m_Hook, &m_Time,
&m_Pos.x, &m_Pos.y, &m_PrevPos.x, &m_PrevPos.y,
&m_TeleCheckpoint, &m_LastPenalty,

View file

@ -57,7 +57,7 @@ private:
int m_Jetpack;
int m_NinjaJetpack;
int m_FreezeTime;
int m_FreezeTick;
int m_FreezeStart;
int m_DeepFreeze;
int m_LiveFreeze;
int m_EndlessHook;