| 1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
| 2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
| 3 | |
| 4 | #include "entity.h" |
| 5 | |
| 6 | #include "gamecontext.h" |
| 7 | #include "player.h" |
| 8 | |
| 9 | ////////////////////////////////////////////////// |
| 10 | // Entity |
| 11 | ////////////////////////////////////////////////// |
| 12 | CEntity::CEntity(CGameWorld *pGameWorld, int ObjType, vec2 Pos, int ProximityRadius) |
| 13 | { |
| 14 | m_pGameWorld = pGameWorld; |
| 15 | m_pCCollision = GameServer()->Collision(); |
| 16 | |
| 17 | m_ObjType = ObjType; |
| 18 | m_Pos = Pos; |
| 19 | m_ProximityRadius = ProximityRadius; |
| 20 | |
| 21 | m_MarkedForDestroy = false; |
| 22 | m_Id = Server()->SnapNewId(); |
| 23 | |
| 24 | m_pPrevTypeEntity = nullptr; |
| 25 | m_pNextTypeEntity = nullptr; |
| 26 | } |
| 27 | |
| 28 | CEntity::~CEntity() |
| 29 | { |
| 30 | GameWorld()->RemoveEntity(pEntity: this); |
| 31 | Server()->SnapFreeId(Id: m_Id); |
| 32 | } |
| 33 | |
| 34 | bool CEntity::NetworkClipped(int SnappingClient) const |
| 35 | { |
| 36 | return ::NetworkClipped(pGameServer: m_pGameWorld->GameServer(), SnappingClient, CheckPos: m_Pos); |
| 37 | } |
| 38 | |
| 39 | bool CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos) const |
| 40 | { |
| 41 | return ::NetworkClipped(pGameServer: m_pGameWorld->GameServer(), SnappingClient, CheckPos); |
| 42 | } |
| 43 | |
| 44 | bool CEntity::NetworkClippedLine(int SnappingClient, vec2 StartPos, vec2 EndPos) const |
| 45 | { |
| 46 | return ::NetworkClippedLine(pGameServer: m_pGameWorld->GameServer(), SnappingClient, StartPos, EndPos); |
| 47 | } |
| 48 | |
| 49 | bool CEntity::GameLayerClipped(vec2 CheckPos) |
| 50 | { |
| 51 | return round_to_int(f: CheckPos.x) / 32 < -200 || round_to_int(f: CheckPos.x) / 32 > GameServer()->Collision()->GetWidth() + 200 || |
| 52 | round_to_int(f: CheckPos.y) / 32 < -200 || round_to_int(f: CheckPos.y) / 32 > GameServer()->Collision()->GetHeight() + 200; |
| 53 | } |
| 54 | |
| 55 | bool CEntity::GetNearestAirPos(vec2 Pos, vec2 PrevPos, vec2 *pOutPos) |
| 56 | { |
| 57 | for(int k = 0; k < 16 && GameServer()->Collision()->CheckPoint(Pos); k++) |
| 58 | { |
| 59 | Pos -= normalize(v: PrevPos - Pos); |
| 60 | } |
| 61 | |
| 62 | vec2 PosInBlock = vec2(round_to_int(f: Pos.x) % 32, round_to_int(f: Pos.y) % 32); |
| 63 | vec2 BlockCenter = vec2(round_to_int(f: Pos.x), round_to_int(f: Pos.y)) - PosInBlock + vec2(16.0f, 16.0f); |
| 64 | |
| 65 | *pOutPos = vec2(BlockCenter.x + (PosInBlock.x < 16 ? -2.0f : 1.0f), Pos.y); |
| 66 | if(!GameServer()->Collision()->TestBox(Pos: *pOutPos, Size: CCharacterCore::PhysicalSizeVec2())) |
| 67 | return true; |
| 68 | |
| 69 | *pOutPos = vec2(Pos.x, BlockCenter.y + (PosInBlock.y < 16 ? -2.0f : 1.0f)); |
| 70 | if(!GameServer()->Collision()->TestBox(Pos: *pOutPos, Size: CCharacterCore::PhysicalSizeVec2())) |
| 71 | return true; |
| 72 | |
| 73 | *pOutPos = vec2(BlockCenter.x + (PosInBlock.x < 16 ? -2.0f : 1.0f), |
| 74 | BlockCenter.y + (PosInBlock.y < 16 ? -2.0f : 1.0f)); |
| 75 | return !GameServer()->Collision()->TestBox(Pos: *pOutPos, Size: CCharacterCore::PhysicalSizeVec2()); |
| 76 | } |
| 77 | |
| 78 | bool CEntity::GetNearestAirPosPlayer(vec2 PlayerPos, vec2 *pOutPos) |
| 79 | { |
| 80 | for(int Distance = 5; Distance >= -1; Distance--) |
| 81 | { |
| 82 | *pOutPos = vec2(PlayerPos.x, PlayerPos.y - Distance); |
| 83 | if(!GameServer()->Collision()->TestBox(Pos: *pOutPos, Size: CCharacterCore::PhysicalSizeVec2())) |
| 84 | { |
| 85 | return true; |
| 86 | } |
| 87 | } |
| 88 | return false; |
| 89 | } |
| 90 | |
| 91 | bool NetworkClipped(const CGameContext *pGameServer, int SnappingClient, vec2 CheckPos) |
| 92 | { |
| 93 | if(SnappingClient == SERVER_DEMO_CLIENT || pGameServer->m_apPlayers[SnappingClient]->m_ShowAll) |
| 94 | return false; |
| 95 | |
| 96 | float dx = pGameServer->m_apPlayers[SnappingClient]->m_ViewPos.x - CheckPos.x; |
| 97 | if(absolute(a: dx) > pGameServer->m_apPlayers[SnappingClient]->m_ShowDistance.x) |
| 98 | return true; |
| 99 | |
| 100 | float dy = pGameServer->m_apPlayers[SnappingClient]->m_ViewPos.y - CheckPos.y; |
| 101 | return absolute(a: dy) > pGameServer->m_apPlayers[SnappingClient]->m_ShowDistance.y; |
| 102 | } |
| 103 | |
| 104 | bool NetworkClippedLine(const CGameContext *pGameServer, int SnappingClient, vec2 StartPos, vec2 EndPos) |
| 105 | { |
| 106 | if(SnappingClient == SERVER_DEMO_CLIENT || pGameServer->m_apPlayers[SnappingClient]->m_ShowAll) |
| 107 | return false; |
| 108 | |
| 109 | vec2 &ViewPos = pGameServer->m_apPlayers[SnappingClient]->m_ViewPos; |
| 110 | vec2 &ShowDistance = pGameServer->m_apPlayers[SnappingClient]->m_ShowDistance; |
| 111 | |
| 112 | vec2 DistanceToLine, ClosestPoint; |
| 113 | if(closest_point_on_line(line_pointA: StartPos, line_pointB: EndPos, target_point: ViewPos, out_pos&: ClosestPoint)) |
| 114 | { |
| 115 | DistanceToLine = ViewPos - ClosestPoint; |
| 116 | } |
| 117 | else |
| 118 | { |
| 119 | // No line section was passed but two equal points |
| 120 | DistanceToLine = ViewPos - StartPos; |
| 121 | } |
| 122 | float ClippDistance = maximum(a: ShowDistance.x, b: ShowDistance.y); |
| 123 | return (absolute(a: DistanceToLine.x) > ClippDistance || absolute(a: DistanceToLine.y) > ClippDistance); |
| 124 | } |
| 125 | |