2010-11-20 10:37:14 +00:00
|
|
|
/* (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. */
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/generated/protocol.h>
|
|
|
|
#include <game/server/gamecontext.h>
|
2010-07-29 05:21:18 +00:00
|
|
|
#include <engine/shared/config.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "laser.h"
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2010-08-30 23:45:42 +00:00
|
|
|
CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner, int Type)
|
2011-01-19 17:27:50 +00:00
|
|
|
: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER)
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Pos = Pos;
|
|
|
|
m_Owner = Owner;
|
|
|
|
m_Energy = StartEnergy;
|
|
|
|
m_Dir = Direction;
|
|
|
|
m_Bounces = 0;
|
|
|
|
m_EvalTick = 0;
|
2011-01-07 18:37:21 +00:00
|
|
|
m_Type = Type;
|
2010-05-29 07:25:38 +00:00
|
|
|
GameWorld()->InsertEntity(this);
|
|
|
|
DoBounce();
|
2008-08-14 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool CLaser::HitCharacter(vec2 From, vec2 To)
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 At;
|
2010-09-21 19:09:11 +00:00
|
|
|
CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner);
|
|
|
|
CCharacter *Hit = GameServer()->m_World.IntersectCharacter(m_Pos, To, 0.f, At, m_Bounces != 0 ? 0: OwnerChar, m_Owner);
|
2010-12-01 22:06:28 +00:00
|
|
|
if(!Hit || (Hit == OwnerChar && g_Config.m_SvOldLaser))
|
2008-08-14 18:25:44 +00:00
|
|
|
return false;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_From = From;
|
|
|
|
m_Pos = At;
|
2010-07-29 05:21:18 +00:00
|
|
|
m_Energy = -1;
|
2010-09-08 16:22:11 +00:00
|
|
|
if (m_Type == 1 && g_Config.m_SvHit)
|
2010-07-29 05:21:18 +00:00
|
|
|
{
|
2010-12-01 22:06:28 +00:00
|
|
|
vec2 Temp;
|
|
|
|
if(!g_Config.m_SvOldLaser)
|
|
|
|
Temp = Hit->m_Core.m_Vel + normalize(m_PrevPos - Hit->m_Core.m_Pos) * 10;
|
|
|
|
else
|
|
|
|
Temp = Hit->m_Core.m_Vel + normalize(OwnerChar->m_Core.m_Pos-Hit->m_Core.m_Pos)*10;
|
2010-11-01 12:08:48 +00:00
|
|
|
if(Temp.x > 0 && ((Hit->m_TileIndex == TILE_STOP && Hit->m_TileFlags == ROTATION_270) || (Hit->m_TileIndexL == TILE_STOP && Hit->m_TileFlagsL == ROTATION_270) || (Hit->m_TileIndexL == TILE_STOPS && (Hit->m_TileFlagsL == ROTATION_90 || Hit->m_TileFlagsL ==ROTATION_270)) || (Hit->m_TileIndexL == TILE_STOPA) || (Hit->m_TileFIndex == TILE_STOP && Hit->m_TileFFlags == ROTATION_270) || (Hit->m_TileFIndexL == TILE_STOP && Hit->m_TileFFlagsL == ROTATION_270) || (Hit->m_TileFIndexL == TILE_STOPS && (Hit->m_TileFFlagsL == ROTATION_90 || Hit->m_TileFFlagsL == ROTATION_270)) || (Hit->m_TileFIndexL == TILE_STOPA) || (Hit->m_TileSIndex == TILE_STOP && Hit->m_TileSFlags == ROTATION_270) || (Hit->m_TileSIndexL == TILE_STOP && Hit->m_TileSFlagsL == ROTATION_270) || (Hit->m_TileSIndexL == TILE_STOPS && (Hit->m_TileSFlagsL == ROTATION_90 || Hit->m_TileSFlagsL == ROTATION_270)) || (Hit->m_TileSIndexL == TILE_STOPA)))
|
|
|
|
Temp.x = 0;
|
|
|
|
if(Temp.x < 0 && ((Hit->m_TileIndex == TILE_STOP && Hit->m_TileFlags == ROTATION_90) || (Hit->m_TileIndexR == TILE_STOP && Hit->m_TileFlagsR == ROTATION_90) || (Hit->m_TileIndexR == TILE_STOPS && (Hit->m_TileFlagsR == ROTATION_90 || Hit->m_TileFlagsR == ROTATION_270)) || (Hit->m_TileIndexR == TILE_STOPA) || (Hit->m_TileFIndex == TILE_STOP && Hit->m_TileFFlags == ROTATION_90) || (Hit->m_TileFIndexR == TILE_STOP && Hit->m_TileFFlagsR == ROTATION_90) || (Hit->m_TileFIndexR == TILE_STOPS && (Hit->m_TileFFlagsR == ROTATION_90 || Hit->m_TileFFlagsR == ROTATION_270)) || (Hit->m_TileFIndexR == TILE_STOPA) || (Hit->m_TileSIndex == TILE_STOP && Hit->m_TileSFlags == ROTATION_90) || (Hit->m_TileSIndexR == TILE_STOP && Hit->m_TileSFlagsR == ROTATION_90) || (Hit->m_TileSIndexR == TILE_STOPS && (Hit->m_TileSFlagsR == ROTATION_90 || Hit->m_TileSFlagsR == ROTATION_270)) || (Hit->m_TileSIndexR == TILE_STOPA)))
|
|
|
|
Temp.x = 0;
|
|
|
|
if(Temp.y < 0 && ((Hit->m_TileIndex == TILE_STOP && Hit->m_TileFlags == ROTATION_180) || (Hit->m_TileIndexB == TILE_STOP && Hit->m_TileFlagsB == ROTATION_180) || (Hit->m_TileIndexB == TILE_STOPS && (Hit->m_TileFlagsB == ROTATION_0 || Hit->m_TileFlagsB == ROTATION_180)) || (Hit->m_TileIndexB == TILE_STOPA) || (Hit->m_TileFIndex == TILE_STOP && Hit->m_TileFFlags == ROTATION_180) || (Hit->m_TileFIndexB == TILE_STOP && Hit->m_TileFFlagsB == ROTATION_180) || (Hit->m_TileFIndexB == TILE_STOPS && (Hit->m_TileFFlagsB == ROTATION_0 || Hit->m_TileFFlagsB == ROTATION_180)) || (Hit->m_TileFIndexB == TILE_STOPA) || (Hit->m_TileSIndex == TILE_STOP && Hit->m_TileSFlags == ROTATION_180) || (Hit->m_TileSIndexB == TILE_STOP && Hit->m_TileSFlagsB == ROTATION_180) || (Hit->m_TileSIndexB == TILE_STOPS && (Hit->m_TileSFlagsB == ROTATION_0 || Hit->m_TileSFlagsB == ROTATION_180)) || (Hit->m_TileSIndexB == TILE_STOPA)))
|
|
|
|
Temp.y = 0;
|
|
|
|
if(Temp.y > 0 && ((Hit->m_TileIndex == TILE_STOP && Hit->m_TileFlags == ROTATION_0) || (Hit->m_TileIndexT == TILE_STOP && Hit->m_TileFlagsT == ROTATION_0) || (Hit->m_TileIndexT == TILE_STOPS && (Hit->m_TileFlagsT == ROTATION_0 || Hit->m_TileFlagsT == ROTATION_180)) || (Hit->m_TileIndexT == TILE_STOPA) || (Hit->m_TileFIndex == TILE_STOP && Hit->m_TileFFlags == ROTATION_0) || (Hit->m_TileFIndexT == TILE_STOP && Hit->m_TileFFlagsT == ROTATION_0) || (Hit->m_TileFIndexT == TILE_STOPS && (Hit->m_TileFFlagsT == ROTATION_0 || Hit->m_TileFFlagsT == ROTATION_180)) || (Hit->m_TileFIndexT == TILE_STOPA) || (Hit->m_TileSIndex == TILE_STOP && Hit->m_TileSFlags == ROTATION_0) || (Hit->m_TileSIndexT == TILE_STOP && Hit->m_TileSFlagsT == ROTATION_0) || (Hit->m_TileSIndexT == TILE_STOPS && (Hit->m_TileSFlagsT == ROTATION_0 || Hit->m_TileSFlagsT == ROTATION_180)) || (Hit->m_TileSIndexT == TILE_STOPA)))
|
|
|
|
Temp.y = 0;
|
|
|
|
Hit->m_Core.m_Vel = Temp;
|
2010-08-27 23:30:50 +00:00
|
|
|
}
|
|
|
|
else if (m_Type == 0)
|
2010-07-29 05:21:18 +00:00
|
|
|
{
|
|
|
|
Hit->UnFreeze();
|
|
|
|
}
|
2008-08-14 18:25:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLaser::DoBounce()
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_EvalTick = Server()->Tick();
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Energy < 0)
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->m_World.DestroyEntity(this);
|
2008-08-14 18:25:44 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-07-29 05:21:18 +00:00
|
|
|
m_PrevPos = m_Pos;
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 To = m_Pos + m_Dir * m_Energy;
|
|
|
|
vec2 OrgTo = To;
|
2010-07-29 05:21:18 +00:00
|
|
|
vec2 Coltile;
|
|
|
|
|
|
|
|
int res;
|
2010-08-21 02:20:01 +00:00
|
|
|
res = GameServer()->Collision()->IntersectLine(m_Pos, To, &Coltile, &To,false);
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2010-07-29 05:21:18 +00:00
|
|
|
if(res)
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!HitCharacter(m_Pos, To))
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
|
|
|
// intersected
|
2010-05-29 07:25:38 +00:00
|
|
|
m_From = m_Pos;
|
|
|
|
m_Pos = To;
|
2009-01-11 10:26:17 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 TempPos = m_Pos;
|
|
|
|
vec2 TempDir = m_Dir * 4.0f;
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2010-07-29 05:21:18 +00:00
|
|
|
int f;
|
|
|
|
if(res == -1) {
|
|
|
|
f = GameServer()->Collision()->GetTile(round(Coltile.x), round(Coltile.y));
|
2010-08-10 04:28:17 +00:00
|
|
|
GameServer()->Collision()->SetCollisionAt(round(Coltile.x), round(Coltile.y), CCollision::COLFLAG_SOLID);
|
2010-07-29 05:21:18 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->Collision()->MovePoint(&TempPos, &TempDir, 1.0f, 0);
|
2010-07-29 05:21:18 +00:00
|
|
|
if(res == -1) {
|
2010-08-10 04:28:17 +00:00
|
|
|
GameServer()->Collision()->SetCollisionAt(round(Coltile.x), round(Coltile.y), f);
|
2010-07-29 05:21:18 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Pos = TempPos;
|
|
|
|
m_Dir = normalize(TempDir);
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Energy -= distance(m_From, m_Pos) + GameServer()->Tuning()->m_LaserBounceCost;
|
|
|
|
m_Bounces++;
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Bounces > GameServer()->Tuning()->m_LaserBounceNum)
|
|
|
|
m_Energy = -1;
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->CreateSound(m_Pos, SOUND_RIFLE_BOUNCE);
|
2008-08-14 18:25:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!HitCharacter(m_Pos, To))
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_From = m_Pos;
|
|
|
|
m_Pos = To;
|
|
|
|
m_Energy = -1;
|
2008-08-14 18:25:44 +00:00
|
|
|
}
|
|
|
|
}
|
2010-09-08 16:22:11 +00:00
|
|
|
//m_Owner = -1;
|
2008-08-14 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLaser::Reset()
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->m_World.DestroyEntity(this);
|
2008-08-14 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLaser::Tick()
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Server()->Tick() > m_EvalTick+(Server()->TickSpeed()*GameServer()->Tuning()->m_LaserBounceDelay)/1000.0f)
|
|
|
|
DoBounce();
|
2008-08-14 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLaser::Snap(int SnappingClient)
|
2008-08-14 18:25:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(NetworkClipped(SnappingClient))
|
2008-08-14 18:25:44 +00:00
|
|
|
return;
|
2010-12-04 16:35:41 +00:00
|
|
|
CCharacter * SnappingChar = GameServer()->GetPlayerChar(SnappingClient);
|
|
|
|
CCharacter * OwnerChar = 0;
|
2010-12-04 21:51:03 +00:00
|
|
|
if(m_Owner >= 0)
|
2010-12-04 16:35:41 +00:00
|
|
|
OwnerChar = GameServer()->GetPlayerChar(m_Owner);
|
2010-12-04 16:51:14 +00:00
|
|
|
if(!SnappingChar || !OwnerChar)
|
|
|
|
return;
|
|
|
|
if(SnappingChar->m_Alive && OwnerChar->m_Alive && SnappingChar->Team() != OwnerChar->Team())
|
2010-12-04 16:35:41 +00:00
|
|
|
return;
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, m_Id, sizeof(CNetObj_Laser)));
|
2010-12-16 02:29:08 +00:00
|
|
|
if(!pObj)
|
|
|
|
return;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
pObj->m_X = (int)m_Pos.x;
|
|
|
|
pObj->m_Y = (int)m_Pos.y;
|
|
|
|
pObj->m_FromX = (int)m_From.x;
|
|
|
|
pObj->m_FromY = (int)m_From.y;
|
|
|
|
pObj->m_StartTick = m_EvalTick;
|
2008-08-14 18:25:44 +00:00
|
|
|
}
|