mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 14:38:18 +00:00
1316: code improvement on gameclient.cpp r=def- a=Ryozuki 1341: Mark unused envelopes r=def- a=Learath2 Thought I'd do this one as well while looking at the editor code. 1349: Don't ignore CONNECT packets with data that we don't know r=def- a=heinrich5991 This specifically affects 0.6.5. Just treat them the same way as those without any data. Co-authored-by: Ryozuki <edgar@ryobyte.com> Co-authored-by: Learath <learath2@gmail.com> Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
commit
1b0b36c6eb
|
@ -508,45 +508,38 @@ void CNetServer::OnConnCtrlMsg(NETADDR &Addr, int ClientID, int ControlMsg, cons
|
||||||
|
|
||||||
void CNetServer::OnTokenCtrlMsg(NETADDR &Addr, int ControlMsg, const CNetPacketConstruct &Packet)
|
void CNetServer::OnTokenCtrlMsg(NETADDR &Addr, int ControlMsg, const CNetPacketConstruct &Packet)
|
||||||
{
|
{
|
||||||
if (ClientExists(Addr))
|
if(ClientExists(Addr))
|
||||||
return; // silently ignore
|
return; // silently ignore
|
||||||
|
|
||||||
|
|
||||||
if (Addr.type == NETTYPE_WEBSOCKET_IPV4)
|
if(Addr.type == NETTYPE_WEBSOCKET_IPV4)
|
||||||
{
|
{
|
||||||
// websocket client doesn't send token
|
// websocket client doesn't send token
|
||||||
// direct accept
|
// direct accept
|
||||||
SendControl(Addr, NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC), NET_SECURITY_TOKEN_UNSUPPORTED);
|
SendControl(Addr, NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC), NET_SECURITY_TOKEN_UNSUPPORTED);
|
||||||
TryAcceptClient(Addr, NET_SECURITY_TOKEN_UNSUPPORTED);
|
TryAcceptClient(Addr, NET_SECURITY_TOKEN_UNSUPPORTED);
|
||||||
}
|
}
|
||||||
else if (ControlMsg == NET_CTRLMSG_CONNECT)
|
else if(ControlMsg == NET_CTRLMSG_CONNECT)
|
||||||
{
|
|
||||||
bool SupportsToken = Packet.m_DataSize >=
|
|
||||||
(int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(SECURITY_TOKEN)) &&
|
|
||||||
!mem_comp(&Packet.m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
|
||||||
|
|
||||||
if (SupportsToken)
|
|
||||||
{
|
{
|
||||||
// response connection request with token
|
// response connection request with token
|
||||||
SECURITY_TOKEN Token = GetToken(Addr);
|
SECURITY_TOKEN Token = GetToken(Addr);
|
||||||
SendControl(Addr, NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC), Token);
|
SendControl(Addr, NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC), Token);
|
||||||
}
|
}
|
||||||
}
|
else if(ControlMsg == NET_CTRLMSG_ACCEPT)
|
||||||
else if (ControlMsg == NET_CTRLMSG_ACCEPT && Packet.m_DataSize == 1 + sizeof(SECURITY_TOKEN))
|
|
||||||
{
|
{
|
||||||
SECURITY_TOKEN Token = ToSecurityToken(&Packet.m_aChunkData[1]);
|
SECURITY_TOKEN Token = ToSecurityToken(&Packet.m_aChunkData[1]);
|
||||||
if (Token == GetToken(Addr))
|
if(Token == GetToken(Addr))
|
||||||
{
|
{
|
||||||
// correct token
|
// correct token
|
||||||
// try to accept client
|
// try to accept client
|
||||||
if (g_Config.m_Debug)
|
if(g_Config.m_Debug)
|
||||||
dbg_msg("security", "new client (ddnet token)");
|
dbg_msg("security", "new client (ddnet token)");
|
||||||
TryAcceptClient(Addr, Token);
|
TryAcceptClient(Addr, Token);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// invalid token
|
// invalid token
|
||||||
if (g_Config.m_Debug)
|
if(g_Config.m_Debug)
|
||||||
dbg_msg("security", "invalid token");
|
dbg_msg("security", "invalid token");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,6 +563,29 @@ int CNetServer::GetClientSlot(const NETADDR &Addr)
|
||||||
return Slot;
|
return Slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsDDNetControlMsg(const CNetPacketConstruct *pPacket)
|
||||||
|
{
|
||||||
|
if(!(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)
|
||||||
|
|| pPacket->m_DataSize < 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(pPacket->m_aChunkData[0] == NET_CTRLMSG_CONNECT
|
||||||
|
&& pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(SECURITY_TOKEN))
|
||||||
|
&& mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)) == 0)
|
||||||
|
{
|
||||||
|
// DDNet CONNECT
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(pPacket->m_aChunkData[0] == NET_CTRLMSG_ACCEPT
|
||||||
|
&& pPacket->m_DataSize >= 1 + (int)sizeof(SECURITY_TOKEN))
|
||||||
|
{
|
||||||
|
// DDNet ACCEPT
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: chopp up this function into smaller working parts
|
TODO: chopp up this function into smaller working parts
|
||||||
*/
|
*/
|
||||||
|
@ -643,9 +659,8 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
||||||
{
|
{
|
||||||
// not found, client that wants to connect
|
// not found, client that wants to connect
|
||||||
|
|
||||||
if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL &&
|
if(IsDDNetControlMsg(&m_RecvUnpacker.m_Data))
|
||||||
m_RecvUnpacker.m_Data.m_DataSize > 1)
|
// got ddnet control msg
|
||||||
// got control msg with extra size (should support token)
|
|
||||||
OnTokenCtrlMsg(Addr, m_RecvUnpacker.m_Data.m_aChunkData[0], m_RecvUnpacker.m_Data);
|
OnTokenCtrlMsg(Addr, m_RecvUnpacker.m_Data.m_aChunkData[0], m_RecvUnpacker.m_Data);
|
||||||
else
|
else
|
||||||
// got connection-less ctrl or sys msg
|
// got connection-less ctrl or sys msg
|
||||||
|
|
|
@ -345,9 +345,9 @@ void CGameClient::OnInit()
|
||||||
for(unsigned int i = 0; i < 16; i++)
|
for(unsigned int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
if(rand() % 2)
|
if(rand() % 2)
|
||||||
g_Config.m_ClTimeoutCode[i] = (rand() % 26) + 97;
|
g_Config.m_ClTimeoutCode[i] =(char)((rand() % 26) + 97);
|
||||||
else
|
else
|
||||||
g_Config.m_ClTimeoutCode[i] = (rand() % 26) + 65;
|
g_Config.m_ClTimeoutCode[i] = (char)((rand() % 26) + 65);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,9 +356,9 @@ void CGameClient::OnInit()
|
||||||
for(unsigned int i = 0; i < 16; i++)
|
for(unsigned int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
if(rand() % 2)
|
if(rand() % 2)
|
||||||
g_Config.m_ClDummyTimeoutCode[i] = (rand() % 26) + 97;
|
g_Config.m_ClDummyTimeoutCode[i] = (char)((rand() % 26) + 97);
|
||||||
else
|
else
|
||||||
g_Config.m_ClDummyTimeoutCode[i] = (rand() % 26) + 65;
|
g_Config.m_ClDummyTimeoutCode[i] = (char)((rand() % 26) + 65);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,8 +446,8 @@ int CGameClient::OnSnapInput(int *pData, bool Dummy, bool Force)
|
||||||
vec2 Main = m_LocalCharacterPos;
|
vec2 Main = m_LocalCharacterPos;
|
||||||
vec2 Dummy = m_aClients[m_LocalIDs[!g_Config.m_ClDummy]].m_Predicted.m_Pos;
|
vec2 Dummy = m_aClients[m_LocalIDs[!g_Config.m_ClDummy]].m_Predicted.m_Pos;
|
||||||
vec2 Dir = Main - Dummy;
|
vec2 Dir = Main - Dummy;
|
||||||
m_HammerInput.m_TargetX = Dir.x;
|
m_HammerInput.m_TargetX = (int)(Dir.x);
|
||||||
m_HammerInput.m_TargetY = Dir.y;
|
m_HammerInput.m_TargetY = (int)(Dir.y);
|
||||||
|
|
||||||
mem_copy(pData, &m_HammerInput, sizeof(m_HammerInput));
|
mem_copy(pData, &m_HammerInput, sizeof(m_HammerInput));
|
||||||
return sizeof(m_HammerInput);
|
return sizeof(m_HammerInput);
|
||||||
|
@ -1019,7 +1019,7 @@ void CGameClient::OnNewSnapshot()
|
||||||
char aMessage[64];
|
char aMessage[64];
|
||||||
int MsgLen = rand()%(sizeof(aMessage)-1);
|
int MsgLen = rand()%(sizeof(aMessage)-1);
|
||||||
for(int i = 0; i < MsgLen; i++)
|
for(int i = 0; i < MsgLen; i++)
|
||||||
aMessage[i] = 'a'+(rand()%('z'-'a'));
|
aMessage[i] = (char)('a' + (rand() % ('z' - 'a')));
|
||||||
aMessage[MsgLen] = 0;
|
aMessage[MsgLen] = 0;
|
||||||
|
|
||||||
CNetMsg_Cl_Say Msg;
|
CNetMsg_Cl_Say Msg;
|
||||||
|
@ -1135,7 +1135,7 @@ void CGameClient::OnNewSnapshot()
|
||||||
static bool s_GameOver = 0;
|
static bool s_GameOver = 0;
|
||||||
static bool s_GamePaused = 0;
|
static bool s_GamePaused = 0;
|
||||||
m_Snap.m_pGameInfoObj = (const CNetObj_GameInfo *)pData;
|
m_Snap.m_pGameInfoObj = (const CNetObj_GameInfo *)pData;
|
||||||
bool CurrentTickGameOver = m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER;
|
bool CurrentTickGameOver = (bool)(m_Snap.m_pGameInfoObj->m_GameStateFlags & GAMESTATEFLAG_GAMEOVER);
|
||||||
if(!s_GameOver && CurrentTickGameOver)
|
if(!s_GameOver && CurrentTickGameOver)
|
||||||
OnGameOver();
|
OnGameOver();
|
||||||
else if(s_GameOver && !CurrentTickGameOver)
|
else if(s_GameOver && !CurrentTickGameOver)
|
||||||
|
@ -1150,7 +1150,7 @@ void CGameClient::OnNewSnapshot()
|
||||||
m_pStatboard->OnReset();
|
m_pStatboard->OnReset();
|
||||||
m_LastRoundStartTick = m_Snap.m_pGameInfoObj->m_RoundStartTick;
|
m_LastRoundStartTick = m_Snap.m_pGameInfoObj->m_RoundStartTick;
|
||||||
s_GameOver = CurrentTickGameOver;
|
s_GameOver = CurrentTickGameOver;
|
||||||
s_GamePaused = m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED;
|
s_GamePaused = (bool)(m_Snap.m_pGameInfoObj->m_GameStateFlags & GAMESTATEFLAG_PAUSED);
|
||||||
}
|
}
|
||||||
else if(Item.m_Type == NETOBJTYPE_GAMEDATA)
|
else if(Item.m_Type == NETOBJTYPE_GAMEDATA)
|
||||||
{
|
{
|
||||||
|
@ -1225,22 +1225,17 @@ void CGameClient::OnNewSnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update friend state
|
|
||||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||||
{
|
{
|
||||||
if(i == m_Snap.m_LocalClientID || !m_Snap.m_paPlayerInfos[i] || !Friends()->IsFriend(m_aClients[i].m_aName, m_aClients[i].m_aClan, true))
|
// update friend state
|
||||||
m_aClients[i].m_Friend = false;
|
m_aClients[i].m_Friend = !(i == m_Snap.m_LocalClientID
|
||||||
else
|
|| !m_Snap.m_paPlayerInfos[i]
|
||||||
m_aClients[i].m_Friend = true;
|
|| !Friends()->IsFriend(m_aClients[i].m_aName, m_aClients[i].m_aClan, true));
|
||||||
}
|
|
||||||
|
|
||||||
// update foe state
|
// update foe state
|
||||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
m_aClients[i].m_Foe = !(i == m_Snap.m_LocalClientID
|
||||||
{
|
|| !m_Snap.m_paPlayerInfos[i]
|
||||||
if(i == m_Snap.m_LocalClientID || !m_Snap.m_paPlayerInfos[i] || !Foes()->IsFriend(m_aClients[i].m_aName, m_aClients[i].m_aClan, true))
|
|| !Foes()->IsFriend(m_aClients[i].m_aName, m_aClients[i].m_aClan, true));
|
||||||
m_aClients[i].m_Foe = false;
|
|
||||||
else
|
|
||||||
m_aClients[i].m_Foe = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort player infos by name
|
// sort player infos by name
|
||||||
|
@ -1414,7 +1409,6 @@ void CGameClient::OnPredict()
|
||||||
class CLocalProjectile PredictedProjectiles[MaxProjectiles];
|
class CLocalProjectile PredictedProjectiles[MaxProjectiles];
|
||||||
int NumProjectiles = 0;
|
int NumProjectiles = 0;
|
||||||
int ReloadTimer = 0;
|
int ReloadTimer = 0;
|
||||||
vec2 PrevPos;
|
|
||||||
|
|
||||||
if(AntiPingWeapons())
|
if(AntiPingWeapons())
|
||||||
{
|
{
|
||||||
|
@ -1518,44 +1512,34 @@ void CGameClient::OnPredict()
|
||||||
|
|
||||||
bool WeaponFired = false;
|
bool WeaponFired = false;
|
||||||
bool NewPresses = false;
|
bool NewPresses = false;
|
||||||
// handle weapons
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if(ReloadTimer)
|
|
||||||
break;
|
|
||||||
if(!World.m_apCharacters[m_Snap.m_LocalClientID])
|
|
||||||
break;
|
|
||||||
if(!pInput || !pPrevInput)
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
// handle weapons
|
||||||
|
|
||||||
|
if(!ReloadTimer && World.m_apCharacters[m_Snap.m_LocalClientID] && (pInput && pPrevInput))
|
||||||
|
{
|
||||||
bool FullAuto = false;
|
bool FullAuto = false;
|
||||||
if(Local->m_ActiveWeapon == WEAPON_GRENADE || Local->m_ActiveWeapon == WEAPON_SHOTGUN || Local->m_ActiveWeapon == WEAPON_RIFLE)
|
if(Local->m_ActiveWeapon == WEAPON_GRENADE || Local->m_ActiveWeapon == WEAPON_SHOTGUN || Local->m_ActiveWeapon == WEAPON_RIFLE)
|
||||||
FullAuto = true;
|
FullAuto = true;
|
||||||
|
|
||||||
bool WillFire = false;
|
bool WillFire = false;
|
||||||
|
|
||||||
if(CountInput(PrevInput.m_Fire, Input.m_Fire).m_Presses)
|
if(CountInput(PrevInput.m_Fire, Input.m_Fire).m_Presses)
|
||||||
{
|
{
|
||||||
WillFire = true;
|
WillFire = true;
|
||||||
NewPresses = true;
|
NewPresses = true;
|
||||||
}
|
}
|
||||||
if(FullAuto && (Input.m_Fire&1))
|
|
||||||
|
if(FullAuto && (Input.m_Fire & 1))
|
||||||
WillFire = true;
|
WillFire = true;
|
||||||
if(!WillFire)
|
|
||||||
break;
|
|
||||||
if(!IsRace(&Info) && !m_Snap.m_pLocalCharacter->m_AmmoCount && Local->m_ActiveWeapon != WEAPON_HAMMER)
|
|
||||||
break;
|
|
||||||
|
|
||||||
int ExpectedStartTick = Tick-1;
|
if(WillFire && ((IsRace(&Info) || m_Snap.m_pLocalCharacter->m_AmmoCount) || Local->m_ActiveWeapon == WEAPON_HAMMER)) {
|
||||||
|
int ExpectedStartTick = Tick - 1;
|
||||||
ReloadTimer = g_pData->m_Weapons.m_aId[Local->m_ActiveWeapon].m_Firedelay * SERVER_TICK_SPEED / 1000;
|
ReloadTimer = g_pData->m_Weapons.m_aId[Local->m_ActiveWeapon].m_Firedelay * SERVER_TICK_SPEED / 1000;
|
||||||
|
|
||||||
bool DirectInput = Client()->InputExists(Tick);
|
bool DirectInput = Client()->InputExists(Tick);
|
||||||
if(!DirectInput)
|
if(!DirectInput)
|
||||||
{
|
{
|
||||||
ReloadTimer++;
|
ReloadTimer++;
|
||||||
ExpectedStartTick++;
|
ExpectedStartTick++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(Local->m_ActiveWeapon)
|
switch(Local->m_ActiveWeapon)
|
||||||
{
|
{
|
||||||
case WEAPON_RIFLE:
|
case WEAPON_RIFLE:
|
||||||
|
@ -1595,7 +1579,7 @@ void CGameClient::OnPredict()
|
||||||
continue;
|
continue;
|
||||||
if(i == m_Snap.m_LocalClientID)
|
if(i == m_Snap.m_LocalClientID)
|
||||||
continue;
|
continue;
|
||||||
if(!(distance(World.m_apCharacters[i]->m_Pos, ProjPos) < Radius+ProximityRadius))
|
if(distance(World.m_apCharacters[i]->m_Pos, ProjPos) >= Radius + ProximityRadius)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CCharacterCore *pTarget = World.m_apCharacters[i];
|
CCharacterCore *pTarget = World.m_apCharacters[i];
|
||||||
|
@ -1634,7 +1618,8 @@ void CGameClient::OnPredict()
|
||||||
if(!DirectInput)
|
if(!DirectInput)
|
||||||
ReloadTimer++;
|
ReloadTimer++;
|
||||||
}
|
}
|
||||||
} while(false);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(ReloadTimer)
|
if(ReloadTimer)
|
||||||
ReloadTimer--;
|
ReloadTimer--;
|
||||||
|
@ -1693,10 +1678,7 @@ void CGameClient::OnPredict()
|
||||||
{
|
{
|
||||||
if(!World.m_apCharacters[c])
|
if(!World.m_apCharacters[c])
|
||||||
continue;
|
continue;
|
||||||
if(m_Snap.m_LocalClientID == c)
|
World.m_apCharacters[c]->Tick(m_Snap.m_LocalClientID == c, true);
|
||||||
World.m_apCharacters[c]->Tick(true, true);
|
|
||||||
else
|
|
||||||
World.m_apCharacters[c]->Tick(false, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2103,7 +2085,7 @@ void CLocalProjectile::Init(CGameClient *pGameClient, CWorldCore *pWorld, CColli
|
||||||
{
|
{
|
||||||
bool StandardVel = (fabs(1.0f - length(m_Direction)) < 0.015);
|
bool StandardVel = (fabs(1.0f - length(m_Direction)) < 0.015);
|
||||||
m_Owner = -1;
|
m_Owner = -1;
|
||||||
m_Explosive = ((m_Type == WEAPON_GRENADE && StandardVel) ? true : false);
|
m_Explosive = m_Type == WEAPON_GRENADE && StandardVel;
|
||||||
m_Bouncing = 0;
|
m_Bouncing = 0;
|
||||||
m_Freeze = 0;
|
m_Freeze = 0;
|
||||||
m_ExtraInfo = false;
|
m_ExtraInfo = false;
|
||||||
|
@ -2155,8 +2137,8 @@ vec2 CLocalProjectile::GetPos(float Time)
|
||||||
|
|
||||||
bool CLocalProjectile::GameLayerClipped(vec2 CheckPos)
|
bool CLocalProjectile::GameLayerClipped(vec2 CheckPos)
|
||||||
{
|
{
|
||||||
return round_to_int(CheckPos.x)/32 < -200 || round_to_int(CheckPos.x)/32 > m_pCollision->GetWidth()+200 ||
|
return round_to_int(CheckPos.x) / 32 < -200 || round_to_int(CheckPos.x) / 32 > m_pCollision->GetWidth() + 200 ||
|
||||||
round_to_int(CheckPos.y)/32 < -200 || round_to_int(CheckPos.y)/32 > m_pCollision->GetHeight()+200 ? true : false;
|
round_to_int(CheckPos.y)/32 < -200 || round_to_int(CheckPos.y)/32 > m_pCollision->GetHeight()+200;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLocalProjectile::Tick(int CurrentTick, int GameTickSpeed, int LocalClientID)
|
void CLocalProjectile::Tick(int CurrentTick, int GameTickSpeed, int LocalClientID)
|
||||||
|
@ -2183,7 +2165,7 @@ void CLocalProjectile::Tick(int CurrentTick, int GameTickSpeed, int LocalClientI
|
||||||
|
|
||||||
bool OwnerCanProbablyHitOthers = (m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerHooking);
|
bool OwnerCanProbablyHitOthers = (m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerHooking);
|
||||||
|
|
||||||
if(((Target >= 0 && (m_Owner >= 0 ? OwnerCanProbablyHitOthers : 1 || Target == m_Owner)) || Collide || GameLayerClipped(CurPos)) && !IsWeaponCollide)
|
if(((Target >= 0 && (m_Owner >= 0 ? OwnerCanProbablyHitOthers : true)) || Collide || GameLayerClipped(CurPos)) && !IsWeaponCollide)
|
||||||
{
|
{
|
||||||
if(m_Explosive && (Target < 0 || (Target >= 0 && (!m_Freeze || (m_Weapon == WEAPON_SHOTGUN && Collide)))))
|
if(m_Explosive && (Target < 0 || (Target >= 0 && (!m_Freeze || (m_Weapon == WEAPON_SHOTGUN && Collide)))))
|
||||||
CreateExplosion(ColPos, m_Owner);
|
CreateExplosion(ColPos, m_Owner);
|
||||||
|
@ -2209,11 +2191,11 @@ void CLocalProjectile::Tick(int CurrentTick, int GameTickSpeed, int LocalClientI
|
||||||
{
|
{
|
||||||
int Lifetime = 0;
|
int Lifetime = 0;
|
||||||
if(m_Weapon == WEAPON_GRENADE)
|
if(m_Weapon == WEAPON_GRENADE)
|
||||||
Lifetime = m_pGameClient->m_Tuning[g_Config.m_ClDummy].m_GrenadeLifetime * SERVER_TICK_SPEED;
|
Lifetime = (int)(m_pGameClient->m_Tuning[g_Config.m_ClDummy].m_GrenadeLifetime * SERVER_TICK_SPEED);
|
||||||
else if(m_Weapon == WEAPON_GUN)
|
else if(m_Weapon == WEAPON_GUN)
|
||||||
Lifetime = m_pGameClient->m_Tuning[g_Config.m_ClDummy].m_GrenadeLifetime * SERVER_TICK_SPEED;
|
Lifetime = (int)(m_pGameClient->m_Tuning[g_Config.m_ClDummy].m_GrenadeLifetime * SERVER_TICK_SPEED);
|
||||||
else if(m_Weapon == WEAPON_SHOTGUN)
|
else if(m_Weapon == WEAPON_SHOTGUN)
|
||||||
Lifetime = m_pGameClient->m_Tuning[g_Config.m_ClDummy].m_ShotgunLifetime * SERVER_TICK_SPEED;
|
Lifetime = (int)(m_pGameClient->m_Tuning[g_Config.m_ClDummy].m_ShotgunLifetime * SERVER_TICK_SPEED);
|
||||||
int LifeSpan = Lifetime - (CurrentTick - m_StartTick);
|
int LifeSpan = Lifetime - (CurrentTick - m_StartTick);
|
||||||
if(LifeSpan == -1)
|
if(LifeSpan == -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4591,6 +4591,47 @@ void CEditor::RenderUndoList(CUIRect View)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CEditor::IsEnvelopeUsed(int EnvelopeIndex)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < m_Map.m_lGroups.size(); i++)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < m_Map.m_lGroups[i]->m_lLayers.size(); j++)
|
||||||
|
{
|
||||||
|
if(m_Map.m_lGroups[i]->m_lLayers[j]->m_Type == LAYERTYPE_QUADS)
|
||||||
|
{
|
||||||
|
CLayerQuads *pQuadLayer = (CLayerQuads *)m_Map.m_lGroups[i]->m_lLayers[j];
|
||||||
|
for(int k = 0; k < pQuadLayer->m_lQuads.size(); k++)
|
||||||
|
{
|
||||||
|
if(pQuadLayer->m_lQuads[k].m_PosEnv == EnvelopeIndex
|
||||||
|
|| pQuadLayer->m_lQuads[k].m_ColorEnv == EnvelopeIndex)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_Map.m_lGroups[i]->m_lLayers[j]->m_Type == LAYERTYPE_SOUNDS)
|
||||||
|
{
|
||||||
|
CLayerSounds *pSoundLayer = (CLayerSounds *)m_Map.m_lGroups[i]->m_lLayers[j];
|
||||||
|
for(int k = 0; k < pSoundLayer->m_lSources.size(); k++)
|
||||||
|
{
|
||||||
|
if(pSoundLayer->m_lSources[k].m_PosEnv == EnvelopeIndex
|
||||||
|
|| pSoundLayer->m_lSources[k].m_SoundEnv == EnvelopeIndex)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_Map.m_lGroups[i]->m_lLayers[j]->m_Type == LAYERTYPE_TILES)
|
||||||
|
{
|
||||||
|
CLayerTiles *pTileLayer = (CLayerTiles *)m_Map.m_lGroups[i]->m_lLayers[j];
|
||||||
|
if(pTileLayer->m_ColorEnv == EnvelopeIndex)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CEditor::RenderEnvelopeEditor(CUIRect View)
|
void CEditor::RenderEnvelopeEditor(CUIRect View)
|
||||||
{
|
{
|
||||||
if(m_SelectedEnvelope < 0) m_SelectedEnvelope = 0;
|
if(m_SelectedEnvelope < 0) m_SelectedEnvelope = 0;
|
||||||
|
@ -4680,7 +4721,16 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
|
||||||
Shifter.VSplitLeft(15.0f, &Dec, &Shifter);
|
Shifter.VSplitLeft(15.0f, &Dec, &Shifter);
|
||||||
char aBuf[512];
|
char aBuf[512];
|
||||||
str_format(aBuf, sizeof(aBuf),"%d/%d", m_SelectedEnvelope+1, m_Map.m_lEnvelopes.size());
|
str_format(aBuf, sizeof(aBuf),"%d/%d", m_SelectedEnvelope+1, m_Map.m_lEnvelopes.size());
|
||||||
RenderTools()->DrawUIRect(&Shifter, vec4(1,1,1,0.5f), 0, 0.0f);
|
|
||||||
|
vec4 EnvColor = vec4(1, 1, 1, 0.5f);
|
||||||
|
if(m_Map.m_lEnvelopes.size())
|
||||||
|
{
|
||||||
|
EnvColor = IsEnvelopeUsed(m_SelectedEnvelope) ?
|
||||||
|
vec4(0.7f, 1, 0.7f, 0.5f) :
|
||||||
|
vec4(1, 0.7f, 0.7f, 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderTools()->DrawUIRect(&Shifter, EnvColor, 0, 0.0f);
|
||||||
UI()->DoLabel(&Shifter, aBuf, 10.0f, 0, -1);
|
UI()->DoLabel(&Shifter, aBuf, 10.0f, 0, -1);
|
||||||
|
|
||||||
static int s_PrevButton = 0;
|
static int s_PrevButton = 0;
|
||||||
|
|
|
@ -1018,6 +1018,8 @@ public:
|
||||||
static void AddImage(const char *pFilename, int StorageType, void *pUser);
|
static void AddImage(const char *pFilename, int StorageType, void *pUser);
|
||||||
static void AddSound(const char *pFileName, int StorageType, void *pUser);
|
static void AddSound(const char *pFileName, int StorageType, void *pUser);
|
||||||
|
|
||||||
|
bool IsEnvelopeUsed(int EnvelopeIndex);
|
||||||
|
|
||||||
void RenderImages(CUIRect Toolbox, CUIRect View);
|
void RenderImages(CUIRect Toolbox, CUIRect View);
|
||||||
void RenderLayers(CUIRect Toolbox, CUIRect View);
|
void RenderLayers(CUIRect Toolbox, CUIRect View);
|
||||||
void RenderSounds(CUIRect Toolbox, CUIRect View);
|
void RenderSounds(CUIRect Toolbox, CUIRect View);
|
||||||
|
|
Loading…
Reference in a new issue