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//////////////////////////////////////////////////
11CEntity::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
27CEntity::~CEntity()
28{
29 GameWorld()->RemoveEntity(pEntity: this);
30 Server()->SnapFreeId(Id: m_Id);
31}
32
33bool CEntity::NetworkClipped(int SnappingClient) const
34{
35 return ::NetworkClipped(pGameServer: m_pGameWorld->GameServer(), SnappingClient, CheckPos: m_Pos);
36}
37
38bool CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos) const
39{
40 return ::NetworkClipped(pGameServer: m_pGameWorld->GameServer(), SnappingClient, CheckPos);
41}
42
43bool CEntity::NetworkClippedLine(int SnappingClient, vec2 StartPos, vec2 EndPos) const
44{
45 return ::NetworkClippedLine(pGameServer: m_pGameWorld->GameServer(), SnappingClient, StartPos, EndPos);
46}
47
48bool 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
54bool 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
77bool 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
90bool 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
103bool 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