mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Make hooks go through teleporters
This commit is contained in:
parent
717219e1c2
commit
54b942fa7e
|
@ -1,5 +1,6 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#include <iostream>
|
||||
#include <base/system.h>
|
||||
#include <base/math.h>
|
||||
#include <base/vmath.h>
|
||||
|
@ -192,7 +193,8 @@ int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *p
|
|||
vec2 Pos = mix(Pos0, Pos1, a);
|
||||
ix = round(Pos.x);
|
||||
iy = round(Pos.y);
|
||||
if(CheckPoint(ix, iy) && !(AllowThrough && IsThrough(ix + dx, iy + dy)))
|
||||
|
||||
if((CheckPoint(ix, iy) && !(AllowThrough && IsThrough(ix + dx, iy + dy))))
|
||||
{
|
||||
if(pOutCollision)
|
||||
*pOutCollision = Pos;
|
||||
|
@ -200,6 +202,55 @@ int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *p
|
|||
*pOutBeforeCollision = Last;
|
||||
return GetCollisionAt(ix, iy);
|
||||
}
|
||||
|
||||
Last = Pos;
|
||||
}
|
||||
if(pOutCollision)
|
||||
*pOutCollision = Pos1;
|
||||
if(pOutBeforeCollision)
|
||||
*pOutBeforeCollision = Pos1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCollision::IntersectLineTele(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, int *pTeleNr, bool AllowThrough)
|
||||
{
|
||||
float Distance = distance(Pos0, Pos1);
|
||||
int End(Distance+1);
|
||||
vec2 Last = Pos0;
|
||||
int ix = 0, iy = 0; // Temporary position for checking collision
|
||||
int dx = 0, dy = 0; // Offset for checking the "through" tile
|
||||
if (AllowThrough)
|
||||
{
|
||||
ThroughOffset(Pos0, Pos1, &dx, &dy);
|
||||
}
|
||||
for(int i = 0; i < End; i++)
|
||||
{
|
||||
float a = i/Distance;
|
||||
vec2 Pos = mix(Pos0, Pos1, a);
|
||||
ix = round(Pos.x);
|
||||
iy = round(Pos.y);
|
||||
|
||||
int Nx = clamp(ix/32, 0, m_Width-1);
|
||||
int Ny = clamp(iy/32, 0, m_Height-1);
|
||||
*pTeleNr = IsTeleport(Ny*m_Width+Nx);
|
||||
if(*pTeleNr)
|
||||
{
|
||||
if(pOutCollision)
|
||||
*pOutCollision = Pos;
|
||||
if(pOutBeforeCollision)
|
||||
*pOutBeforeCollision = Last;
|
||||
return COLFLAG_TELE;
|
||||
}
|
||||
|
||||
if((CheckPoint(ix, iy) && !(AllowThrough && IsThrough(ix + dx, iy + dy))))
|
||||
{
|
||||
if(pOutCollision)
|
||||
*pOutCollision = Pos;
|
||||
if(pOutBeforeCollision)
|
||||
*pOutBeforeCollision = Last;
|
||||
return GetCollisionAt(ix, iy);
|
||||
}
|
||||
|
||||
Last = Pos;
|
||||
}
|
||||
if(pOutCollision)
|
||||
|
@ -711,6 +762,51 @@ int CCollision::GetIndex(int Nx, int Ny)
|
|||
return m_pTiles[Ny*m_Width+Nx].m_Index;
|
||||
}
|
||||
|
||||
int CCollision::GetIndex(vec2 Pos)
|
||||
{
|
||||
int nx = clamp((int)Pos.x/32, 0, m_Width-1);
|
||||
int ny = clamp((int)Pos.y/32, 0, m_Height-1);
|
||||
|
||||
return ny*m_Width+nx;
|
||||
}
|
||||
|
||||
int CCollision::GetIndex(vec2 PrevPos, vec2 Pos)
|
||||
{
|
||||
float Distance = distance(PrevPos, Pos);
|
||||
|
||||
if(!Distance)
|
||||
{
|
||||
int Nx = clamp((int)Pos.x/32, 0, m_Width-1);
|
||||
int Ny = clamp((int)Pos.y/32, 0, m_Height-1);
|
||||
|
||||
if ((m_pTele) ||
|
||||
(m_pSpeedup && m_pSpeedup[Ny*m_Width+Nx].m_Force > 0))
|
||||
{
|
||||
return Ny*m_Width+Nx;
|
||||
}
|
||||
}
|
||||
|
||||
float a = 0.0f;
|
||||
vec2 Tmp = vec2(0, 0);
|
||||
int Nx = 0;
|
||||
int Ny = 0;
|
||||
|
||||
for(float f = 0; f < Distance; f++)
|
||||
{
|
||||
a = f/Distance;
|
||||
Tmp = mix(PrevPos, Pos, a);
|
||||
Nx = clamp((int)Tmp.x/32, 0, m_Width-1);
|
||||
Ny = clamp((int)Tmp.y/32, 0, m_Height-1);
|
||||
if ((m_pTele) ||
|
||||
(m_pSpeedup && m_pSpeedup[Ny*m_Width+Nx].m_Force > 0))
|
||||
{
|
||||
return Ny*m_Width+Nx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CCollision::GetFIndex(int Nx, int Ny)
|
||||
{
|
||||
if(!m_pFront) return 0;
|
||||
|
|
|
@ -25,7 +25,8 @@ public:
|
|||
COLFLAG_NOHOOK=4,
|
||||
// DDRace
|
||||
COLFLAG_NOLASER=8,
|
||||
COLFLAG_THROUGH=16
|
||||
COLFLAG_THROUGH=16,
|
||||
COLFLAG_TELE=32
|
||||
};
|
||||
|
||||
CCollision();
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
int GetWidth() { return m_Width; };
|
||||
int GetHeight() { return m_Height; };
|
||||
int IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, bool AllowThrough);
|
||||
int IntersectLineTele(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, int *pTeleNr, bool AllowThrough);
|
||||
void MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces);
|
||||
void MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity);
|
||||
bool TestBox(vec2 Pos, vec2 Size);
|
||||
|
@ -54,6 +56,8 @@ public:
|
|||
int IntersectNoLaserNW(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision);
|
||||
int IntersectAir(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision);
|
||||
int GetIndex(int x, int y);
|
||||
int GetIndex(vec2 Pos);
|
||||
int GetIndex(vec2 PrevPos, vec2 Pos);
|
||||
int GetFIndex(int x, int y);
|
||||
|
||||
int GetTile(int x, int y);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "gamecore.h"
|
||||
|
||||
#include <engine/shared/config.h>
|
||||
|
||||
#include <engine/server/server.h>
|
||||
const char *CTuningParams::m_apNames[] =
|
||||
{
|
||||
#define MACRO_TUNING_PARAM(Name,ScriptName,Value) #ScriptName,
|
||||
|
@ -57,10 +57,11 @@ float VelocityRamp(float Value, float Start, float Range, float Curvature)
|
|||
return 1.0f/powf(Curvature, (Value-Start)/Range);
|
||||
}
|
||||
|
||||
void CCharacterCore::Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore* pTeams)
|
||||
void CCharacterCore::Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore* pTeams, std::map<int, std::vector<vec2> > pTeleOuts)
|
||||
{
|
||||
m_pWorld = pWorld;
|
||||
m_pCollision = pCollision;
|
||||
m_pTeleOuts = pTeleOuts;
|
||||
|
||||
m_pTeams = pTeams;
|
||||
m_Id = -1;
|
||||
|
@ -70,6 +71,7 @@ void CCharacterCore::Reset()
|
|||
{
|
||||
m_Pos = vec2(0,0);
|
||||
m_Vel = vec2(0,0);
|
||||
m_NewHook = false;
|
||||
m_HookPos = vec2(0,0);
|
||||
m_HookDir = vec2(0,0);
|
||||
m_HookTick = 0;
|
||||
|
@ -229,7 +231,8 @@ void CCharacterCore::Tick(bool UseInput)
|
|||
else if(m_HookState == HOOK_FLYING)
|
||||
{
|
||||
vec2 NewPos = m_HookPos+m_HookDir*m_pWorld->m_Tuning.m_HookFireSpeed;
|
||||
if(distance(m_Pos, NewPos) > m_pWorld->m_Tuning.m_HookLength)
|
||||
if((!m_NewHook && distance(m_Pos, NewPos) > m_pWorld->m_Tuning.m_HookLength)
|
||||
|| (m_NewHook && distance(m_HookTeleBase, NewPos) > m_pWorld->m_Tuning.m_HookLength))
|
||||
{
|
||||
m_HookState = HOOK_RETRACT_START;
|
||||
NewPos = m_Pos + normalize(NewPos-m_Pos) * m_pWorld->m_Tuning.m_HookLength;
|
||||
|
@ -239,11 +242,24 @@ void CCharacterCore::Tick(bool UseInput)
|
|||
// make sure that the hook doesn't go though the ground
|
||||
bool GoingToHitGround = false;
|
||||
bool GoingToRetract = false;
|
||||
int Hit = m_pCollision->IntersectLine(m_HookPos, NewPos, &NewPos, 0, true);
|
||||
bool GoingThroughTele = false;
|
||||
int teleNr = 0;
|
||||
int Hit;
|
||||
if (m_NewHook)
|
||||
Hit = m_pCollision->IntersectLine(m_HookPos, NewPos, &NewPos, 0, true);
|
||||
else
|
||||
Hit = m_pCollision->IntersectLineTele(m_HookPos, NewPos, &NewPos, 0, &teleNr, true);
|
||||
|
||||
//m_NewHook = false;
|
||||
|
||||
if(Hit)
|
||||
{
|
||||
if(Hit&CCollision::COLFLAG_NOHOOK)
|
||||
GoingToRetract = true;
|
||||
else if (Hit&CCollision::COLFLAG_TELE)
|
||||
{
|
||||
GoingThroughTele = true;
|
||||
}
|
||||
else
|
||||
GoingToHitGround = true;
|
||||
m_pReset = true;
|
||||
|
@ -260,7 +276,7 @@ void CCharacterCore::Tick(bool UseInput)
|
|||
continue;
|
||||
|
||||
vec2 ClosestPoint = closest_point_on_line(m_HookPos, NewPos, pCharCore->m_Pos);
|
||||
if(distance(pCharCore->m_Pos, ClosestPoint) < PhysSize+2.0f)
|
||||
if(m_HookState != HOOK_RETRACT_START && distance(pCharCore->m_Pos, ClosestPoint) < PhysSize+2.0f)
|
||||
{
|
||||
if (m_HookedPlayer == -1 || distance(m_HookPos, pCharCore->m_Pos) < Distance)
|
||||
{
|
||||
|
@ -287,7 +303,21 @@ void CCharacterCore::Tick(bool UseInput)
|
|||
m_HookState = HOOK_RETRACT_START;
|
||||
}
|
||||
|
||||
m_HookPos = NewPos;
|
||||
if(GoingThroughTele)
|
||||
{
|
||||
m_TriggeredEvents = 0;
|
||||
m_HookedPlayer = -1;
|
||||
|
||||
m_NewHook = true;
|
||||
int Num = m_pTeleOuts[teleNr-1].size();
|
||||
m_HookPos = m_pTeleOuts[teleNr-1][(!Num)?Num:rand() % Num]+TargetDirection*PhysSize*1.5f;
|
||||
m_HookDir = TargetDirection;
|
||||
m_HookTeleBase = m_HookPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HookPos = NewPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,6 +443,11 @@ void CCharacterCore::Tick(bool UseInput)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_HookState != HOOK_FLYING)
|
||||
{
|
||||
m_NewHook = false;
|
||||
}
|
||||
}
|
||||
|
||||
// clamp the velocity to something sane
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include <base/system.h>
|
||||
#include <base/math.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <math.h>
|
||||
#include "collision.h"
|
||||
#include <engine/shared/protocol.h>
|
||||
|
@ -161,6 +164,7 @@ enum
|
|||
COREEVENT_HOOK_ATTACH_GROUND=0x10,
|
||||
COREEVENT_HOOK_HIT_NOHOOK=0x20,
|
||||
COREEVENT_HOOK_RETRACT=0x40,
|
||||
//COREEVENT_HOOK_TELE=0x80,
|
||||
};
|
||||
|
||||
class CWorldCore
|
||||
|
@ -179,16 +183,22 @@ class CCharacterCore
|
|||
{
|
||||
CWorldCore *m_pWorld;
|
||||
CCollision *m_pCollision;
|
||||
std::map<int, std::vector<vec2> > m_pTeleOuts;
|
||||
public:
|
||||
vec2 m_Pos;
|
||||
vec2 m_Vel;
|
||||
|
||||
vec2 m_HookPos;
|
||||
vec2 m_HookDir;
|
||||
vec2 m_HookTeleBase;
|
||||
int m_HookTick;
|
||||
int m_HookState;
|
||||
int m_HookedPlayer;
|
||||
|
||||
bool m_NewHook;
|
||||
vec2 m_NewHookPos;
|
||||
vec2 m_NewHookDir;
|
||||
|
||||
int m_Jumped;
|
||||
|
||||
int m_Direction;
|
||||
|
@ -197,7 +207,7 @@ public:
|
|||
|
||||
int m_TriggeredEvents;
|
||||
|
||||
void Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore* pTeams);
|
||||
void Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore* pTeams, std::map<int, std::vector<vec2> > pTeleOuts);
|
||||
void Reset();
|
||||
void Tick(bool UseInput);
|
||||
void Move();
|
||||
|
|
|
@ -71,7 +71,7 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
|
|||
m_Pos = Pos;
|
||||
|
||||
m_Core.Reset();
|
||||
m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision(), &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core);
|
||||
m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision(), &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core, ((CGameControllerDDRace*)GameServer()->m_pController)->m_TeleOuts);
|
||||
m_Core.m_Pos = m_Pos;
|
||||
GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = &m_Core;
|
||||
|
||||
|
@ -651,7 +651,7 @@ void CCharacter::TickDefered()
|
|||
// advance the dummy
|
||||
{
|
||||
CWorldCore TempWorld;
|
||||
m_ReckoningCore.Init(&TempWorld, GameServer()->Collision(), &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core);
|
||||
m_ReckoningCore.Init(&TempWorld, GameServer()->Collision(), &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core, ((CGameControllerDDRace*)GameServer()->m_pController)->m_TeleOuts);
|
||||
m_ReckoningCore.m_Id = m_pPlayer->GetCID();
|
||||
m_ReckoningCore.Tick(false);
|
||||
m_ReckoningCore.Move();
|
||||
|
|
Loading…
Reference in a new issue