ddnet/src/game/server/entities/laser.cpp

130 lines
3.1 KiB
C++
Raw Normal View History

2010-05-29 07:25:38 +00:00
// copyright (c) 2007 magnus auvinen, see licence.txt for more info
#include <game/generated/protocol.h>
#include <game/server/gamecontext.h>
#include <engine/shared/config.h>
2010-05-29 07:25:38 +00:00
#include "laser.h"
CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner, int Type)
2010-05-29 07:25:38 +00:00
: CEntity(pGameWorld, NETOBJTYPE_LASER)
{
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;
m_Type = Type;
2010-05-29 07:25:38 +00:00
GameWorld()->InsertEntity(this);
DoBounce();
}
2010-05-29 07:25:38 +00:00
bool CLaser::HitCharacter(vec2 From, vec2 To)
{
2010-05-29 07:25:38 +00:00
vec2 At;
CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner);
CCharacter *Hit = GameServer()->m_World.IntersectCharacter(m_Pos, To, 0.f, At, m_Bounces > 0 ? 0 : OwnerChar);
2010-05-29 07:25:38 +00:00
if(!Hit)
return false;
if(OwnerChar != 0 && OwnerChar->Team() != Hit->Team()) return false;
2010-05-29 07:25:38 +00:00
m_From = From;
m_Pos = At;
m_Energy = -1;
if (m_Type == 1 && g_Config.m_SvHit)
{
Hit->m_Core.m_Vel+=normalize(m_PrevPos - Hit->m_Core.m_Pos) * 10;
}
else if (m_Type == 0)
{
Hit->UnFreeze();
}
return true;
}
2010-05-29 07:25:38 +00:00
void CLaser::DoBounce()
{
2010-05-29 07:25:38 +00:00
m_EvalTick = Server()->Tick();
2010-05-29 07:25:38 +00:00
if(m_Energy < 0)
{
2010-05-29 07:25:38 +00:00
GameServer()->m_World.DestroyEntity(this);
return;
}
m_PrevPos = m_Pos;
2010-05-29 07:25:38 +00:00
vec2 To = m_Pos + m_Dir * m_Energy;
vec2 OrgTo = To;
vec2 Coltile;
int res;
res = GameServer()->Collision()->IntersectLine(m_Pos, To, &Coltile, &To,false);
if(res)
{
2010-05-29 07:25:38 +00:00
if(!HitCharacter(m_Pos, To))
{
// intersected
2010-05-29 07:25:38 +00:00
m_From = m_Pos;
m_Pos = To;
2010-05-29 07:25:38 +00:00
vec2 TempPos = m_Pos;
vec2 TempDir = m_Dir * 4.0f;
int f;
if(res == -1) {
f = GameServer()->Collision()->GetTile(round(Coltile.x), round(Coltile.y));
GameServer()->Collision()->SetCollisionAt(round(Coltile.x), round(Coltile.y), CCollision::COLFLAG_SOLID);
}
2010-05-29 07:25:38 +00:00
GameServer()->Collision()->MovePoint(&TempPos, &TempDir, 1.0f, 0);
if(res == -1) {
GameServer()->Collision()->SetCollisionAt(round(Coltile.x), round(Coltile.y), f);
}
2010-05-29 07:25:38 +00:00
m_Pos = TempPos;
m_Dir = normalize(TempDir);
2010-05-29 07:25:38 +00:00
m_Energy -= distance(m_From, m_Pos) + GameServer()->Tuning()->m_LaserBounceCost;
m_Bounces++;
2010-05-29 07:25:38 +00:00
if(m_Bounces > GameServer()->Tuning()->m_LaserBounceNum)
m_Energy = -1;
2010-05-29 07:25:38 +00:00
GameServer()->CreateSound(m_Pos, SOUND_RIFLE_BOUNCE);
}
}
else
{
2010-05-29 07:25:38 +00:00
if(!HitCharacter(m_Pos, To))
{
2010-05-29 07:25:38 +00:00
m_From = m_Pos;
m_Pos = To;
m_Energy = -1;
}
}
//m_Owner = -1;
}
2010-05-29 07:25:38 +00:00
void CLaser::Reset()
{
2010-05-29 07:25:38 +00:00
GameServer()->m_World.DestroyEntity(this);
}
2010-05-29 07:25:38 +00:00
void CLaser::Tick()
{
2010-05-29 07:25:38 +00:00
if(Server()->Tick() > m_EvalTick+(Server()->TickSpeed()*GameServer()->Tuning()->m_LaserBounceDelay)/1000.0f)
DoBounce();
}
2010-05-29 07:25:38 +00:00
void CLaser::Snap(int SnappingClient)
{
2010-05-29 07:25:38 +00:00
if(NetworkClipped(SnappingClient))
return;
CCharacter * Char = GameServer()->GetPlayerChar(SnappingClient);
if(Char && m_Owner != -1 && !Char->GetPlayer()->m_ShowOthers &&
Char->Team() != GameServer()->GetPlayerChar(m_Owner)->Team()) 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)));
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;
}