Added Fluxid's HookThrough

Signed-off-by: GreYFoXGTi <GreYFoXGTi@GMaiL.CoM>
This commit is contained in:
GreYFoXGTi 2010-08-21 04:20:01 +02:00
parent 57712d885f
commit e7721811dd
9 changed files with 73 additions and 12 deletions

View file

@ -162,7 +162,8 @@ int CCollision::GetCollisionDDRace(int Index)
int CCollision::GetCollisionDDRace2(int Index)
{
/*dbg_msg("GetCollisionDDRace2","m_pFront[%d].m_Index = %d",Index,m_pFront[Index].m_Index);//Remove*/
if(Index < 0)
if(Index < 0 || !m_pFront)
return 0;
return m_pFront[Index].m_Index;
}
@ -194,22 +195,61 @@ void CCollision::SetCollisionAt(float x, float y, int flag)
}
// TODO: rewrite this smarter!
int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision)
void ThroughOffset(vec2 Pos0, vec2 Pos1, int *Ox, int *Oy)
{
float x = Pos0.x - Pos1.x;
float y = Pos0.y - Pos1.y;
if (fabs(x) > fabs(y))
{
if (x < 0)
{
*Ox = -32;
*Oy = 0;
}
else
{
*Ox = 32;
*Oy = 0;
}
}
else
{
if (y < 0)
{
*Ox = 0;
*Oy = -32;
}
else
{
*Ox = 0;
*Oy = 32;
}
}
}
int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, bool AllowThrough)
{
float d = distance(Pos0, Pos1);
vec2 Last = Pos0;
int ix, iy; // Temporary position for checking collision
int dx, dy; // Offset for checking the "through" tile
if (AllowThrough)
{
ThroughOffset(Pos0, Pos1, &dx, &dy);
}
for(float f = 0; f < d; f++)
{
float a = f/d;
vec2 Pos = mix(Pos0, Pos1, a);
if(CheckPoint(Pos.x, Pos.y))
ix = round(Pos.x);
iy = round(Pos.y);
if(CheckPoint(ix, iy) && !(AllowThrough && IsThrough(ix + dx, iy + dy)))
{
if(pOutCollision)
*pOutCollision = Pos;
if(pOutBeforeCollision)
*pOutBeforeCollision = Last;
return GetCollisionAt(Pos.x, Pos.y);
return GetCollisionAt(ix, iy);
}
Last = Pos;
}
@ -391,6 +431,22 @@ int CCollision::IsSolid(int x, int y)
return (GetTile(x,y)&COLFLAG_SOLID);
}
int CCollision::IsThrough(int x, int y)
{
int nx = clamp(x/32, 0, m_Width-1);
int ny = clamp(y/32, 0, m_Height-1);
int Index = m_pTiles[ny*m_Width+nx].m_Index;
int Findex;
if (m_pFront)
Findex = m_pFront[ny*m_Width+nx].m_Index;
if (Index == TILE_THROUGH)
return Index;
else if (Findex == TILE_THROUGH)
return Findex;
else
return 0;
}
int CCollision::IsNoLaser(int x, int y)
{
return (CCollision::GetTile(x,y) & COLFLAG_NOLASER);

View file

@ -27,7 +27,7 @@ public:
int GetCollisionAt(float x, float y) { return GetTile(round(x), round(y)); }
int GetWidth() { return m_Width; };
int GetHeight() { return m_Height; };
int IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision);
int IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, bool AllowThrough);
int IntersectNoLaser(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision);
int IntersectAir(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision);
void MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *Bpounces);
@ -47,6 +47,7 @@ public:
bool IsFront(int x, int y);
int IsSolid(int x, int y);
int IsThrough(int x, int y);
int IsNoLaser(int x, int y);
int IsCp(int x, int y);

View file

@ -192,18 +192,20 @@ void CCharacterCore::Tick(bool UseInput)
{
m_HookState = HOOK_RETRACT_START;
NewPos = m_Pos + normalize(NewPos-m_Pos) * m_pWorld->m_Tuning.m_HookLength;
m_pReset = true;
}
// 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);
int Hit = m_pCollision->IntersectLine(m_HookPos, NewPos, &NewPos, 0,true);
if(Hit)
{
if(Hit&CCollision::COLFLAG_NOHOOK)
GoingToRetract = true;
else
GoingToHitGround = true;
m_pReset = true;
}
// Check against other players first

View file

@ -190,6 +190,7 @@ public:
int m_Angle;
CNetObj_PlayerInput m_Input;
bool m_pReset;
int m_TriggeredEvents;
void Init(CWorldCore *pWorld, CCollision *pCollision);

View file

@ -898,11 +898,12 @@ void CCharacter::TickDefered()
m_Core.Write(&Current);
// only allow dead reackoning for a top of 3 seconds
if(m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0)
if(m_Core.m_pReset || m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0)
{
m_ReckoningTick = Server()->Tick();
m_SendCore = m_Core;
m_ReckoningCore = m_Core;
m_Core.m_pReset = false;
}
}
}

View file

@ -35,7 +35,7 @@ void CGun::fire()
CCharacter *target = ents[i];
int res=0;
vec2 coltile;
res = GameServer()->Collision()->IntersectLine(m_Pos, target->m_Pos,0,0);
res = GameServer()->Collision()->IntersectLine(m_Pos, target->m_Pos,0,0,false);
if (!res)
{
int len=length(ents[i]->m_Pos - m_Pos);

View file

@ -26,4 +26,4 @@ public:
};
#endif
#endif

View file

@ -56,7 +56,7 @@ void CLaser::DoBounce()
vec2 Coltile;
int res;
res = GameServer()->Collision()->IntersectLine(m_Pos, To, &Coltile, &To);
res = GameServer()->Collision()->IntersectLine(m_Pos, To, &Coltile, &To,false);
if(res)
{

View file

@ -68,7 +68,7 @@ void CProjectile::Tick()
vec2 ColPos;
vec2 NewPos;
vec2 Speed = CurPos - PrevPos;
int Collide = GameServer()->Collision()->IntersectLine(PrevPos, CurPos, &ColPos, &NewPos);
int Collide = GameServer()->Collision()->IntersectLine(PrevPos, CurPos, &ColPos, &NewPos,false);
CCharacter *OwnerChar;