#include #include #include #include "projectile.h" CProjectile::CProjectile( CGameWorld *pGameWorld, int Type, int Owner, vec2 Pos, vec2 Dir, int Span, bool Freeze, bool Explosive, float Force, int SoundImpact, int Weapon) : CEntity(pGameWorld, NETOBJTYPE_PROJECTILE) { m_Type = Type; m_Pos = Pos; m_Direction = Dir; m_LifeSpan = Span; m_Owner = Owner; m_Force = Force; //m_Damage = Damage; m_Freeze = Freeze; m_SoundImpact = SoundImpact; m_Weapon = Weapon; m_StartTick = Server()->Tick(); m_Explosive = Explosive; m_BouncePos=vec2(0,0); m_ReBouncePos=vec2(0,0); m_AvgPos=vec2(0,0); m_LastBounce=vec2(0,0); m_PrevLastBounce=vec2(0,0); GameWorld()->InsertEntity(this); } void CProjectile::Reset() { if(m_LifeSpan > -2) GameServer()->m_World.DestroyEntity(this); } vec2 CProjectile::GetPos(float Time) { float Curvature = 0; float Speed = 0; switch(m_Type) { case WEAPON_GRENADE: Curvature = GameServer()->Tuning()->m_GrenadeCurvature; Speed = GameServer()->Tuning()->m_GrenadeSpeed; break; case WEAPON_SHOTGUN: Curvature = GameServer()->Tuning()->m_ShotgunCurvature; Speed = GameServer()->Tuning()->m_ShotgunSpeed; break; case WEAPON_GUN: Curvature = GameServer()->Tuning()->m_GunCurvature; Speed = GameServer()->Tuning()->m_GunSpeed; break; } return CalcPos(m_Pos, m_Direction, Curvature, Speed, Time); } void CProjectile::SetBouncing(int Value) { m_Bouncing = Value; } void CProjectile::Tick() { float Pt = (Server()->Tick()-m_StartTick-1)/(float)Server()->TickSpeed(); float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed(); vec2 PrevPos = GetPos(Pt); vec2 CurPos = GetPos(Ct); vec2 ColPos; vec2 NewPos; vec2 Speed = CurPos - PrevPos; int Collide = GameServer()->Collision()->IntersectLine(PrevPos, CurPos, &ColPos, &NewPos,false); CCharacter *OwnerChar; if(m_Owner >= 0) OwnerChar = GameServer()->GetPlayerChar(m_Owner); CCharacter *TargetChr = GameServer()->m_World.IntersectCharacter(PrevPos, ColPos, (m_Freeze) ? 1.0f : 6.0f, ColPos, OwnerChar); if(m_LifeSpan > -1) m_LifeSpan--; if( (TargetChr && (g_Config.m_SvHit || TargetChr == OwnerChar)) || Collide) { if(m_Explosive/*??*/ && (!TargetChr || (TargetChr && !m_Freeze))) { GameServer()->CreateExplosion(ColPos, m_Owner, m_Weapon, false); GameServer()->CreateSound(ColPos, m_SoundImpact); } else if(TargetChr && m_Freeze) TargetChr->Freeze(Server()->TickSpeed()*3); if (Collide && m_Bouncing != 0) { m_StartTick = Server()->Tick(); m_Pos = NewPos; if (m_Bouncing == 1) { m_Direction.x = -m_Direction.x; m_LastBounce = m_Pos; if(!m_BouncePos.x) m_BouncePos=m_Pos; else if (!m_ReBouncePos.x) m_ReBouncePos=m_Pos; else if(!m_AvgPos.x) m_AvgPos = vec2((m_BouncePos.x+m_ReBouncePos.x)/2,(m_BouncePos.y+m_ReBouncePos.y)/2); } else if (m_Bouncing == 2) { m_LastBounce = m_Pos; m_Direction.y =- m_Direction.y; if(!m_BouncePos.y) m_BouncePos=m_Pos; else if (!m_ReBouncePos.y) m_ReBouncePos=m_Pos; else if(!m_AvgPos.y) m_AvgPos = vec2((m_BouncePos.x+m_ReBouncePos.x)/2,(m_BouncePos.y+m_ReBouncePos.y)/2); } m_Pos += m_Direction; } else if (m_Weapon == WEAPON_GUN) { GameServer()->CreateDamageInd(CurPos, -atan2(m_Direction.x, m_Direction.y), 10); GameServer()->m_World.DestroyEntity(this); } else if (!m_Freeze) GameServer()->m_World.DestroyEntity(this); } if (m_LifeSpan == -1) { GameServer()->m_World.DestroyEntity(this); } if((!(m_PrevLastBounce == m_BouncePos && m_LastBounce == m_ReBouncePos) && !(m_LastBounce == m_BouncePos && m_PrevLastBounce == m_ReBouncePos))&&m_AvgPos.x) m_Pos=m_AvgPos; m_PrevLastBounce=m_LastBounce; } void CProjectile::FillInfo(CNetObj_Projectile *pProj) { pProj->m_X = (int)m_Pos.x; pProj->m_Y = (int)m_Pos.y; pProj->m_VelX = (int)(m_Direction.x*100.0f); pProj->m_VelY = (int)(m_Direction.y*100.0f); pProj->m_StartTick = m_StartTick; pProj->m_Type = m_Type; } void CProjectile::Snap(int SnappingClient) { float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed(); if(NetworkClipped(SnappingClient, GetPos(Ct))) return; CNetObj_Projectile *pProj = static_cast(Server()->SnapNewItem(NETOBJTYPE_PROJECTILE, m_Id, sizeof(CNetObj_Projectile))); FillInfo(pProj); }