| 45 | } |
| 46 | |
| 47 | void CGun::Fire() |
| 48 | { |
| 49 | // Create a list of players who are in the range of the turret |
| 50 | CEntity *apPlayersInRange[MAX_CLIENTS]; |
| 51 | std::fill(std::begin(apPlayersInRange), std::end(apPlayersInRange), nullptr); |
| 52 | |
| 53 | int NumPlayersInRange = GameServer()->m_World.FindEntities(m_Pos, g_Config.m_SvPlasmaRange, |
| 54 | apPlayersInRange, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); |
| 55 | |
| 56 | // The closest player (within range) in a team is selected as the target |
| 57 | int aTargetIdInTeam[MAX_CLIENTS]; |
| 58 | bool aIsTarget[MAX_CLIENTS]; |
| 59 | int aMinDistInTeam[MAX_CLIENTS]; |
| 60 | std::fill(std::begin(aMinDistInTeam), std::end(aMinDistInTeam), 0); |
| 61 | std::fill(std::begin(aIsTarget), std::end(aIsTarget), false); |
| 62 | std::fill(std::begin(aTargetIdInTeam), std::end(aTargetIdInTeam), -1); |
| 63 | |
| 64 | for(int i = 0; i < NumPlayersInRange; i++) |
| 65 | { |
| 66 | CCharacter *pTarget = static_cast<CCharacter *>(apPlayersInRange[i]); |
| 67 | const int &TargetTeam = pTarget->Team(); |
| 68 | // Do not fire at super players |
| 69 | if(TargetTeam == TEAM_SUPER) |
| 70 | { |
| 71 | continue; |
| 72 | } |
| 73 | // If the turret is disabled for the target's team, the turret will not fire |
| 74 | if(m_Layer == LAYER_SWITCH && m_Number > 0 && |
| 75 | !Switchers()[m_Number].m_aStatus[TargetTeam]) |
| 76 | { |
| 77 | continue; |
| 78 | } |
| 79 | |
| 80 | // Turrets can only shoot at a speed of sv_plasma_per_sec |
| 81 | const int &TargetClientId = pTarget->GetPlayer()->GetCid(); |
| 82 | const bool &TargetIsSolo = pTarget->Teams()->m_Core.GetSolo(TargetClientId); |
| 83 | if((TargetIsSolo && |
| 84 | m_aLastFireSolo[TargetClientId] + Server()->TickSpeed() / g_Config.m_SvPlasmaPerSec > Server()->Tick()) || |
| 85 | (!TargetIsSolo && |
| 86 | m_aLastFireTeam[TargetTeam] + Server()->TickSpeed() / g_Config.m_SvPlasmaPerSec > Server()->Tick())) |
| 87 | { |
| 88 | continue; |
| 89 | } |
| 90 | |
| 91 | // Turrets can shoot only at reachable, alive players |
| 92 | int IsReachable = !GameServer()->Collision()->IntersectLine(m_Pos, pTarget->m_Pos, nullptr, nullptr); |
| 93 | if(IsReachable && pTarget->IsAlive()) |
| 94 | { |
| 95 | // Turrets fire on solo players regardless of the rest of the team |
| 96 | if(TargetIsSolo) |
| 97 | { |
| 98 | aIsTarget[TargetClientId] = true; |
| 99 | m_aLastFireSolo[TargetClientId] = Server()->Tick(); |
| 100 | } |
| 101 | else |
| 102 | { |
| 103 | int Distance = distance(pTarget->m_Pos, m_Pos); |
| 104 | if(aMinDistInTeam[TargetTeam] == 0 || aMinDistInTeam[TargetTeam] > Distance) |
nothing calls this directly
no test coverage detected