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