Fix switch state for super, cleanup door snapping, add dragger/gun/light

This commit is contained in:
trml 2021-10-14 22:59:39 +02:00
parent f0bd4cf5fa
commit 71e5b7ed3a
8 changed files with 129 additions and 58 deletions

View file

@ -36,7 +36,7 @@ Emoticons = ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY",
Powerups = ["HEALTH", "ARMOR", "WEAPON", "NINJA"] Powerups = ["HEALTH", "ARMOR", "WEAPON", "NINJA"]
Authed = ["NO", "HELPER", "MOD", "ADMIN"] Authed = ["NO", "HELPER", "MOD", "ADMIN"]
EntityClasses = ["PICKUP", "PROJECTILE", "DOOR"] EntityClasses = ["PROJECTILE", "DOOR", "DRAGGER_WEAK", "DRAGGER_NORMAL", "DRAGGER_STRONG", "GUN_NORMAL", "GUN_EXPLOSIVE", "GUN_FREEZE", "GUN_UNFREEZE", "LIGHT", "PICKUP"]
RawHeader = ''' RawHeader = '''

View file

@ -302,19 +302,23 @@ void CItems::OnRender()
if(Client()->State() < IClient::STATE_ONLINE) if(Client()->State() < IClient::STATE_ONLINE)
return; return;
bool IsSuper = m_pClient->IsLocalCharSuper();
int Ticks = Client()->GameTick(g_Config.m_ClDummy) % Client()->GameTickSpeed(); int Ticks = Client()->GameTick(g_Config.m_ClDummy) % Client()->GameTickSpeed();
bool BlinkingSwitchPickup = (Ticks % 22) < 4; bool BlinkingPickup = (Ticks % 22) < 4;
bool BlinkingSwitchDoor = (Ticks % 22) < 4; bool BlinkingGun = (Ticks % 22) < 4;
bool BlinkingSwitchProj = (Ticks % 20) < 2; bool BlinkingDragger = (Ticks % 22) < 4;
bool BlinkingSwitchProjEx = (Ticks % 6) < 2; bool BlinkingProj = (Ticks % 20) < 2;
bool BlinkingProjEx = (Ticks % 6) < 2;
bool BlinkingLight = (Ticks % 6) < 2;
int OwnTeam = m_pClient->OwnTeam(); int OwnTeam = m_pClient->OwnTeam();
int DraggerStartTick = maximum((Client()->GameTick(g_Config.m_ClDummy) / 7) * 7, Client()->GameTick(g_Config.m_ClDummy) - 4);
bool UsePredicted = GameClient()->Predict() && GameClient()->AntiPingGunfire(); bool UsePredicted = GameClient()->Predict() && GameClient()->AntiPingGunfire();
if(UsePredicted) if(UsePredicted)
{ {
for(auto *pProj = (CProjectile *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity()) for(auto *pProj = (CProjectile *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity())
{ {
if(pProj->m_Number > 0 && !Collision()->m_pSwitchers[pProj->m_Number].m_Status[OwnTeam] && (pProj->m_Explosive ? BlinkingSwitchProjEx : BlinkingSwitchProj)) if(!IsSuper && pProj->m_Number > 0 && !Collision()->m_pSwitchers[pProj->m_Number].m_Status[OwnTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj))
continue; continue;
CProjectileData Data = pProj->GetData(); CProjectileData Data = pProj->GetData();
@ -330,7 +334,7 @@ void CItems::OnRender()
} }
for(auto *pPickup = (CPickup *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity()) for(auto *pPickup = (CPickup *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity())
{ {
if(pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && !Collision()->m_pSwitchers[pPickup->m_Number].m_Status[OwnTeam] && BlinkingSwitchPickup) if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && !Collision()->m_pSwitchers[pPickup->m_Number].m_Status[OwnTeam] && BlinkingPickup)
continue; continue;
if(pPickup->InDDNetTile()) if(pPickup->InDDNetTile())
@ -353,6 +357,10 @@ void CItems::OnRender()
const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
CNetObj_EntityEx *pEntEx = (CNetObj_EntityEx *)Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_ENTITYEX, Item.m_ID); CNetObj_EntityEx *pEntEx = (CNetObj_EntityEx *)Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_ENTITYEX, Item.m_ID);
bool Inactive = false;
if(pEntEx)
Inactive = !IsSuper && pEntEx->m_SwitchNumber > 0 && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[OwnTeam];
if(Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE) if(Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE)
{ {
CProjectileData Data; CProjectileData Data;
@ -381,20 +389,20 @@ void CItems::OnRender()
continue; continue;
} }
} }
if(pEntEx && pEntEx->m_SwitchNumber > 0 && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[OwnTeam] && (Data.m_Explosive ? BlinkingSwitchProjEx : BlinkingSwitchProj)) if(Inactive && (Data.m_Explosive ? BlinkingProjEx : BlinkingProj))
continue; continue;
RenderProjectile(&Data, Item.m_ID); RenderProjectile(&Data, Item.m_ID);
} }
else if(Item.m_Type == NETOBJTYPE_PICKUP) else if(Item.m_Type == NETOBJTYPE_PICKUP)
{ {
if(Inactive && BlinkingPickup)
continue;
if(UsePredicted) if(UsePredicted)
{ {
auto *pPickup = (CPickup *)GameClient()->m_GameWorld.FindMatch(Item.m_ID, Item.m_Type, pData); auto *pPickup = (CPickup *)GameClient()->m_GameWorld.FindMatch(Item.m_ID, Item.m_Type, pData);
if(pPickup && pPickup->InDDNetTile()) if(pPickup && pPickup->InDDNetTile())
continue; continue;
} }
if(pEntEx && pEntEx->m_SwitchNumber > 0 && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[OwnTeam] && BlinkingSwitchPickup)
continue;
const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_ID); const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_ID);
if(pPrev) if(pPrev)
RenderPickup((const CNetObj_Pickup *)pPrev, (const CNetObj_Pickup *)pData); RenderPickup((const CNetObj_Pickup *)pPrev, (const CNetObj_Pickup *)pData);
@ -408,16 +416,28 @@ void CItems::OnRender()
continue; continue;
} }
CNetObj_Laser Laser = *((const CNetObj_Laser *)pData); CNetObj_Laser Laser = *((const CNetObj_Laser *)pData);
if(pEntEx && pEntEx->m_EntityClass == ENTITYCLASS_DOOR)
if(pEntEx)
{ {
if(pEntEx->m_SwitchNumber > 0 && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[OwnTeam]) if(pEntEx->m_EntityClass == ENTITYCLASS_LIGHT && Inactive && BlinkingLight)
continue;
if(pEntEx->m_EntityClass >= ENTITYCLASS_GUN_NORMAL && pEntEx->m_EntityClass <= ENTITYCLASS_GUN_UNFREEZE && Inactive && BlinkingGun)
continue;
if(pEntEx->m_EntityClass >= ENTITYCLASS_DRAGGER_WEAK && pEntEx->m_EntityClass <= ENTITYCLASS_DRAGGER_STRONG)
{ {
if(BlinkingSwitchDoor) if(Inactive && BlinkingDragger)
continue; continue;
Laser.m_FromX = Laser.m_X; Laser.m_StartTick = DraggerStartTick;
Laser.m_FromY = Laser.m_Y; }
if(pEntEx->m_EntityClass == ENTITYCLASS_DOOR)
{
if(Inactive || IsSuper)
{
Laser.m_FromX = Laser.m_X;
Laser.m_FromY = Laser.m_Y;
}
Laser.m_StartTick = Client()->GameTick(g_Config.m_ClDummy);
} }
Laser.m_StartTick = Client()->GameTick(g_Config.m_ClDummy);
} }
RenderLaser(&Laser); RenderLaser(&Laser);
} }

View file

@ -2598,10 +2598,16 @@ int CGameClient::OwnTeam()
return 0; return 0;
else if(m_Snap.m_SpecInfo.m_Active && m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW) else if(m_Snap.m_SpecInfo.m_Active && m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW)
return m_Teams.Team(m_Snap.m_SpecInfo.m_SpectatorID); return m_Teams.Team(m_Snap.m_SpecInfo.m_SpectatorID);
return m_Teams.Team(m_Snap.m_LocalClientID); return m_Teams.Team(m_Snap.m_LocalClientID);
} }
bool CGameClient::IsLocalCharSuper()
{
if(m_Snap.m_LocalClientID < 0)
return 0;
return m_aClients[m_Snap.m_LocalClientID].m_Super;
}
void CGameClient::LoadGameSkin(const char *pPath, bool AsDir) void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
{ {
if(m_GameSkinLoaded) if(m_GameSkinLoaded)

View file

@ -512,6 +512,7 @@ public:
void Echo(const char *pString); void Echo(const char *pString);
bool IsOtherTeam(int ClientID); bool IsOtherTeam(int ClientID);
int OwnTeam(); int OwnTeam();
bool IsLocalCharSuper();
bool CanDisplayWarning(); bool CanDisplayWarning();
bool IsDisplayingWarning(); bool IsDisplayingWarning();

View file

@ -62,12 +62,6 @@ void CDoor::Snap(int SnappingClient)
pObj->m_X = (int)m_Pos.x; pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y; pObj->m_Y = (int)m_Pos.y;
CCharacter *Char = GameServer()->GetPlayerChar(SnappingClient);
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11;
if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
int SnappingClientVersion = SnappingClient >= 0 ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR; int SnappingClientVersion = SnappingClient >= 0 ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR;
if(SnappingClientVersion >= VERSION_DDNET_SWITCH) if(SnappingClientVersion >= VERSION_DDNET_SWITCH)
@ -76,29 +70,23 @@ void CDoor::Snap(int SnappingClient)
pObj->m_FromY = (int)m_To.y; pObj->m_FromY = (int)m_To.y;
pObj->m_StartTick = 0; pObj->m_StartTick = 0;
} }
else if(Char) else
{ {
if(Char->Team() == TEAM_SUPER) CCharacter *Char = GameServer()->GetPlayerChar(SnappingClient);
if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
if(Char && Char->Team() != TEAM_SUPER && Char->IsAlive() && GameServer()->Collision()->m_NumSwitchers > 0 && GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()])
{
pObj->m_FromX = (int)m_To.x;
pObj->m_FromY = (int)m_To.y;
}
else
{ {
pObj->m_FromX = (int)m_Pos.x; pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y; pObj->m_FromY = (int)m_Pos.y;
} }
else pObj->m_StartTick = Server()->Tick();
{
if(Char->IsAlive() && GameServer()->Collision()->m_NumSwitchers > 0 && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()] && (!Tick))
return;
if(Char->IsAlive() && GameServer()->Collision()->m_NumSwitchers > 0 && GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()])
{
pObj->m_FromX = (int)m_To.x;
pObj->m_FromY = (int)m_To.y;
}
else
{
pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y;
}
pObj->m_StartTick = Server()->Tick();
}
} }
} }

View file

@ -8,6 +8,7 @@
#include <game/server/gamemodes/DDRace.h> #include <game/server/gamemodes/DDRace.h>
#include <game/server/player.h> #include <game/server/player.h>
#include <game/server/teams.h> #include <game/server/teams.h>
#include <game/version.h>
#include "character.h" #include "character.h"
@ -164,6 +165,16 @@ void CDragger::Snap(int SnappingClient)
if(((CGameControllerDDRace *)GameServer()->m_pController)->m_Teams.GetTeamState(m_CaughtTeam) == CGameTeams::TEAMSTATE_EMPTY) if(((CGameControllerDDRace *)GameServer()->m_pController)->m_Teams.GetTeamState(m_CaughtTeam) == CGameTeams::TEAMSTATE_EMPTY)
return; return;
CNetObj_EntityEx *pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
if(!pEntData)
return;
pEntData->m_SwitchNumber = m_Number;
pEntData->m_Layer = m_Layer;
pEntData->m_EntityClass = clamp(ENTITYCLASS_DRAGGER_WEAK + round_to_int(m_Strength) - 1, (int)ENTITYCLASS_DRAGGER_WEAK, (int)ENTITYCLASS_DRAGGER_STRONG);
int SnappingClientVersion = SnappingClient >= 0 ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR;
CCharacter *Target = m_Target; CCharacter *Target = m_Target;
for(int &SoloID : m_SoloIDs) for(int &SoloID : m_SoloIDs)
@ -200,9 +211,13 @@ void CDragger::Snap(int SnappingClient)
if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW) if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID); Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11; if(i != -1 || SnappingClientVersion < VERSION_DDNET_SWITCH)
if(Char && Char->IsAlive() && (m_Layer == LAYER_SWITCH && m_Number && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()] && (!Tick))) {
continue; int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11;
if(Char && Char->IsAlive() && (m_Layer == LAYER_SWITCH && m_Number && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()] && (!Tick)))
continue;
}
if(Char && Char->IsAlive()) if(Char && Char->IsAlive())
{ {
if(Char->Team() != m_CaughtTeam) if(Char->Team() != m_CaughtTeam)
@ -250,12 +265,19 @@ void CDragger::Snap(int SnappingClient)
obj->m_FromY = (int)m_Pos.y; obj->m_FromY = (int)m_Pos.y;
} }
int StartTick = m_EvalTick; if(i != -1 || SnappingClientVersion < VERSION_DDNET_SWITCH)
if(StartTick < Server()->Tick() - 4) {
StartTick = Server()->Tick() - 4; int StartTick = m_EvalTick;
else if(StartTick > Server()->Tick()) if(StartTick < Server()->Tick() - 4)
StartTick = Server()->Tick(); StartTick = Server()->Tick() - 4;
obj->m_StartTick = StartTick; else if(StartTick > Server()->Tick())
StartTick = Server()->Tick();
obj->m_StartTick = StartTick;
}
else
{
obj->m_StartTick = 0;
}
} }
} }

View file

@ -5,6 +5,7 @@
#include <game/server/gamecontext.h> #include <game/server/gamecontext.h>
#include <game/server/player.h> #include <game/server/player.h>
#include <game/server/teams.h> #include <game/server/teams.h>
#include <game/version.h>
#include "character.h" #include "character.h"
#include "gun.h" #include "gun.h"
@ -111,6 +112,22 @@ void CGun::Tick()
void CGun::Snap(int SnappingClient) void CGun::Snap(int SnappingClient)
{ {
CNetObj_EntityEx *pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
if(!pEntData)
return;
pEntData->m_SwitchNumber = m_Number;
pEntData->m_Layer = m_Layer;
if(m_Explosive && !m_Freeze)
pEntData->m_EntityClass = ENTITYCLASS_GUN_NORMAL;
else if(m_Explosive && m_Freeze)
pEntData->m_EntityClass = ENTITYCLASS_GUN_EXPLOSIVE;
else if(!m_Explosive && m_Freeze)
pEntData->m_EntityClass = ENTITYCLASS_GUN_FREEZE;
else
pEntData->m_EntityClass = ENTITYCLASS_GUN_UNFREEZE;
if(NetworkClipped(SnappingClient)) if(NetworkClipped(SnappingClient))
return; return;
@ -120,9 +137,14 @@ void CGun::Snap(int SnappingClient)
GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW) GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID); Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11; int SnappingClientVersion = SnappingClient >= 0 ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR;
if(Char && Char->IsAlive() && (m_Layer == LAYER_SWITCH && m_Number > 0 && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()]) && (!Tick)) if(SnappingClientVersion < VERSION_DDNET_SWITCH)
return; {
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11;
if(Char && Char->IsAlive() && (m_Layer == LAYER_SWITCH && m_Number > 0 && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()]) && (!Tick))
return;
}
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser))); CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj) if(!pObj)

View file

@ -6,6 +6,7 @@
#include <game/mapitems.h> #include <game/mapitems.h>
#include <game/server/gamecontext.h> #include <game/server/gamecontext.h>
#include <game/server/player.h> #include <game/server/player.h>
#include <game/version.h>
#include "character.h" #include "character.h"
@ -101,6 +102,14 @@ void CLight::Tick()
void CLight::Snap(int SnappingClient) void CLight::Snap(int SnappingClient)
{ {
CNetObj_EntityEx *pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
if(!pEntData)
return;
pEntData->m_SwitchNumber = m_Number;
pEntData->m_Layer = m_Layer;
pEntData->m_EntityClass = ENTITYCLASS_LIGHT;
if(NetworkClipped(SnappingClient, m_Pos) && NetworkClipped(SnappingClient, m_To)) if(NetworkClipped(SnappingClient, m_Pos) && NetworkClipped(SnappingClient, m_To))
return; return;
@ -109,10 +118,13 @@ void CLight::Snap(int SnappingClient)
if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW) if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID); Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 6; int SnappingClientVersion = SnappingClient >= 0 ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR;
if(SnappingClientVersion < VERSION_DDNET_SWITCH)
if(Char && Char->IsAlive() && m_Layer == LAYER_SWITCH && m_Number > 0 && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()] && (Tick)) {
return; int Tick = (Server()->Tick() % Server()->TickSpeed()) % 6;
if(Char && Char->IsAlive() && m_Layer == LAYER_SWITCH && m_Number > 0 && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()] && Tick)
return;
}
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem( CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(
NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser))); NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));