// TODO: should be more general CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2& NewPos, CCharacter *pNotThis, int CollideWith, class CCharacter *pThisOnly) { // Find other players float ClosestLen = distance(Pos0, Pos1) * 100.0f; vec2 LineDir = normalize(Pos1-Pos0); CCharacter *pClosest = 0; CCharacter *p = (CCharacter *)FindFirst(ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(p == pNotThis) continue; if(CollideWith != -1 && !p->CanCollide(CollideWith)) continue; vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, p->m_Pos); float Len = distance(p->m_Pos, IntersectPos); if(Len < p->m_ProximityRadius+Radius) { Len = distance(Pos0, IntersectPos); if(Len < ClosestLen) { NewPos = IntersectPos; ClosestLen = Len; pClosest = p; } if(pThisOnly && p == pThisOnly) return p; } } return pClosest; }
void CProjectile::Snap(int SnappingClient) { float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed(); if(NetworkClipped(SnappingClient, GetPos(Ct))) return; CCharacter* pSnapChar = GameServer()->GetPlayerChar(SnappingClient); int Tick = (Server()->Tick()%Server()->TickSpeed())%((m_Explosive)?6:20); if (pSnapChar && pSnapChar->IsAlive() && (m_Layer == LAYER_SWITCH && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[pSnapChar->Team()] && (!Tick))) return; if(pSnapChar && m_Owner != -1 && !pSnapChar->CanCollide(m_Owner)) return; CNetObj_Projectile *pProj = static_cast<CNetObj_Projectile *>(Server()->SnapNewItem(NETOBJTYPE_PROJECTILE, m_ID, sizeof(CNetObj_Projectile))); if(pProj) FillInfo(pProj); }
void CLaser::Snap(int SnappingClient) { if(NetworkClipped(SnappingClient)) return; CCharacter * SnappingChar = GameServer()->GetPlayerChar(SnappingClient); CCharacter * OwnerChar = 0; if(m_Owner >= 0) OwnerChar = GameServer()->GetPlayerChar(m_Owner); if(!OwnerChar) return; if(SnappingChar && !SnappingChar->CanCollide(m_Owner)) return; CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, m_ID, sizeof(CNetObj_Laser))); if(!pObj) return; 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; }
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; int Collide = GameServer()->Collision()->IntersectLine(PrevPos, CurPos, &ColPos, &NewPos, false); CCharacter *pOwnerChar = 0; if(m_Owner >= 0) pOwnerChar = GameServer()->GetPlayerChar(m_Owner); CCharacter *pTargetChr = GameServer()->m_World.IntersectCharacter(PrevPos, ColPos, m_Freeze ? 1.0f : 6.0f, ColPos, pOwnerChar); if(m_LifeSpan > -1) m_LifeSpan--; int TeamMask = -1; bool isWeaponCollide = false; if ( pOwnerChar && pTargetChr && pOwnerChar->IsAlive() && pTargetChr->IsAlive() && !pTargetChr->CanCollide(m_Owner) ) { isWeaponCollide = true; //TeamMask = OwnerChar->Teams()->TeamMask( OwnerChar->Team()); } if (pOwnerChar && pOwnerChar->IsAlive()) { TeamMask = pOwnerChar->Teams()->TeamMask(pOwnerChar->Team(), -1, m_Owner); } if( ((pTargetChr && (pOwnerChar ? !(pOwnerChar->m_Hit&CCharacter::DISABLE_HIT_GRENADE) : g_Config.m_SvHit || m_Owner == -1 || pTargetChr == pOwnerChar)) || Collide || GameLayerClipped(CurPos)) && !isWeaponCollide) { if(m_Explosive/*??*/ && (!pTargetChr || (pTargetChr && !m_Freeze))) { GameServer()->CreateExplosion(ColPos, m_Owner, m_Weapon, m_Owner == -1, (!pTargetChr ? -1 : pTargetChr->Team()), (m_Owner != -1)? TeamMask : -1); GameServer()->CreateSound(ColPos, m_SoundImpact, (m_Owner != -1)? TeamMask : -1); } else if(pTargetChr && m_Freeze && ((m_Layer == LAYER_SWITCH && GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[pTargetChr->Team()]) || m_Layer != LAYER_SWITCH)) pTargetChr->Freeze(); if(Collide && m_Bouncing != 0) { m_StartTick = Server()->Tick(); m_Pos = NewPos+(-(m_Direction*4)); if (m_Bouncing == 1) m_Direction.x = -m_Direction.x; else if(m_Bouncing == 2) m_Direction.y =- m_Direction.y; if (fabs(m_Direction.x) < 1e-6) m_Direction.x = 0; if (fabs(m_Direction.y) < 1e-6) m_Direction.y = 0; m_Pos += m_Direction; } else if (m_Weapon == WEAPON_GUN) { GameServer()->CreateDamageInd(CurPos, -atan2(m_Direction.x, m_Direction.y), 10, (m_Owner != -1)? TeamMask : -1); GameServer()->m_World.DestroyEntity(this); } else if (!m_Freeze) GameServer()->m_World.DestroyEntity(this); } if(m_LifeSpan == -1) { GameServer()->m_World.DestroyEntity(this); } }