void CombatShip::Damage(const CombatFighterPtr& source) { float damage = source->Stats().m_anti_ship_damage * source->Formation()->size(); float shield_damage = std::min(damage, GetShip()->CurrentMeterValue(METER_SHIELD)); GetShip()->GetMeter(METER_SHIELD)->AddToCurrent(-shield_damage); damage -= shield_damage; GetShip()->GetMeter(METER_STRUCTURE)->AddToCurrent(-damage); }
void CombatShip::Damage(float d, DamageSource source) { assert(0.0f < d); if (source == PD_DAMAGE) d *= PD_VS_SHIP_FACTOR; float shield_damage = std::min(d, GetShip()->CurrentMeterValue(METER_SHIELD)); GetShip()->GetMeter(METER_SHIELD)->AddToCurrent(-shield_damage); d -= shield_damage; GetShip()->GetMeter(METER_STRUCTURE)->AddToCurrent(-d); }
void CombatShip::FireAt(CombatObjectPtr target) { float range_squared = (target->position() - position()).lengthSquared(); float structure_factor = FractionalStructure(); for (CombatShip::SRVec::reverse_iterator it = m_unfired_SR_weapons.rbegin(); it != m_unfired_SR_weapons.rend(); ++it) { if (range_squared < it->m_range * it->m_range) { Listener().ShipFired(shared_from_this(), target, it->m_name); target->Damage(it->m_damage, CombatObject::NON_PD_DAMAGE); } else { m_unfired_SR_weapons.resize(std::distance(it, m_unfired_SR_weapons.rend())); break; } } std::size_t i = 0; for (std::multimap<float, const PartType*>::const_iterator it = GetShip()->Design()->LRWeapons().begin(); it != GetShip()->Design()->LRWeapons().end(); ++it, ++i) { if (m_next_LR_fire_turns[i] < m_turn) { float weapon_range_squared = it->first * it->first; if (range_squared < weapon_range_squared) { OpenSteer::Vec3 direction = (target->position() - position()).normalize(); MissilePtr missile( new Missile(GetShip(), *it->second, target, position(), direction, *m_pathing_engine)); m_pathing_engine->AddObject(missile); GetShip()->RemoveMissiles(it->second->Name(), 1); if (m_next_LR_fire_turns[i] == INVALID_TURN) m_next_LR_fire_turns[i] = m_turn; m_next_LR_fire_turns[i] += GetShip()->GetPartMeter(METER_ROF, it->second->Name())->Current() * structure_factor; Listener().MissileLaunched(missile); } } } for (CombatShip::PDList::iterator it = m_unfired_PD_weapons.begin(); it != m_unfired_PD_weapons.end(); ++it) { if (range_squared < it->m_range * it->m_range) { Listener().ShipFired(shared_from_this(), target, it->m_name); target->Damage(it->m_damage, CombatObject::PD_DAMAGE); } else { m_unfired_PD_weapons.erase(it, m_unfired_PD_weapons.end()); break; } } }
int IssueNewFleetOrder(const std::string& fleet_name, const std::vector<int>& ship_ids) { if (ship_ids.empty()) { Logger().errorStream() << "AIInterface::IssueNewFleetOrder : passed empty vector of ship_ids"; return 0; } if (fleet_name.empty()) { Logger().errorStream() << "AIInterface::IssueNewFleetOrder : tried to create a nameless fleet"; return 0; } int empire_id = AIClientApp::GetApp()->EmpireID(); TemporaryPtr<const Ship> ship = TemporaryPtr<Ship>(); // make sure all ships exist and are owned just by this player for (std::vector<int>::const_iterator it = ship_ids.begin(); it != ship_ids.end(); ++it) { ship = GetShip(*it); if (!ship) { Logger().errorStream() << "AIInterface::IssueNewFleetOrder : passed an invalid ship_id"; return 0; } if (!ship->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueNewFleetOrder : passed ship_id of ship not owned by player"; return 0; } } // make sure all ships are at a system, and that all are at the same system int system_id = ship->SystemID(); if (system_id == INVALID_OBJECT_ID) { Logger().errorStream() << "AIInterface::IssueNewFleetOrder : passed ship_ids of ships at different locations"; return 0; } std::vector<int>::const_iterator it = ship_ids.begin(); for (++it; it != ship_ids.end(); ++it) { TemporaryPtr<const Ship> ship2 = GetShip(*it); if (ship2->SystemID() != system_id) { Logger().errorStream() << "AIInterface::IssueNewFleetOrder : passed ship_ids of ships at different locations"; return 0; } } int new_fleet_id = ClientApp::GetApp()->GetNewObjectID(); AIClientApp::GetApp()->Orders().IssueOrder(OrderPtr(new NewFleetOrder(empire_id, fleet_name, new_fleet_id, system_id, ship_ids))); return new_fleet_id; }
double Fleet::MaxFuel() const { if (NumShips() < 1) return 0.0; // determine the maximum amount of fuel that can be stored by the ship in the fleet that // can store the least amount of fuel double max_fuel = Meter::LARGE_VALUE; bool is_fleet_scrapped = true; for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) { const Ship* ship = GetShip(*ship_it); if (!ship) { Logger().errorStream() << "Fleet::MaxFuel couldn't get ship with id " << *ship_it; continue; } const Meter* meter = ship->UniverseObject::GetMeter(METER_FUEL); if (!meter) { Logger().errorStream() << "Fleet::MaxFuel skipping ship with no fuel meter"; continue; } if (!ship->OrderedScrapped()) { max_fuel = std::min(max_fuel, meter->Current()); is_fleet_scrapped = false; } } if (is_fleet_scrapped) { max_fuel = 0.0; } return max_fuel; }
bool BombardOrder::UndoImpl() const { TemporaryPtr<Planet> planet = GetPlanet(m_planet); if (!planet) { ErrorLogger() << "BombardOrder::UndoImpl couldn't get planet with id " << m_planet; return false; } TemporaryPtr<Ship> ship = GetShip(m_ship); if (!ship) { ErrorLogger() << "BombardOrder::UndoImpl couldn't get ship with id " << m_ship; return false; } if (ship->OrderedBombardPlanet() != m_planet) { ErrorLogger() << "BombardOrder::UndoImpl ship is not about to bombard planet"; return false; } planet->SetIsAboutToBeBombarded(false); ship->ClearBombardPlanet(); if (TemporaryPtr<Fleet> fleet = GetFleet(ship->FleetID())) fleet->StateChangedSignal(); return true; }
bool ColonizeOrder::UndoImpl() const { TemporaryPtr<Planet> planet = GetPlanet(m_planet); if (!planet) { ErrorLogger() << "ColonizeOrder::UndoImpl couldn't get planet with id " << m_planet; return false; } if (!planet->IsAboutToBeColonized()) { ErrorLogger() << "ColonizeOrder::UndoImpl planet is not about to be colonized..."; return false; } TemporaryPtr<Ship> ship = GetShip(m_ship); if (!ship) { ErrorLogger() << "ColonizeOrder::UndoImpl couldn't get ship with id " << m_ship; return false; } if (ship->OrderedColonizePlanet() != m_planet) { ErrorLogger() << "ColonizeOrder::UndoImpl ship is not about to colonize planet"; return false; } planet->SetIsAboutToBeColonized(false); ship->ClearColonizePlanet(); if (TemporaryPtr<Fleet> fleet = GetFleet(ship->FleetID())) fleet->StateChangedSignal(); return true; }
bool Fleet::HasColonyShips() const { for (Fleet::const_iterator it = begin(); it != end(); it++) if (const Ship* ship = GetShip(*it)) if (ship->CanColonize()) return true; return false; }
bool Fleet::HasTroopShips() const { for (Fleet::const_iterator it = begin(); it != end(); it++) if (const Ship* ship = GetShip(*it)) if (ship->HasTroops()) return true; return false; }
void Fleet::AddShip(int ship_id) { if (this->Contains(ship_id)) { Logger().debugStream() << "Fleet::AddShip this fleet '" << this->Name() << "' already contained ship '" << ship_id << "'"; return; } Ship* ship = GetShip(ship_id); if (!ship) { Logger().errorStream() << "Fleet::AddShips() : Attempted to add an id (" << ship_id << ") of a non-ship object to a fleet."; return; } //Logger().debugStream() << "Fleet '" << this->Name() << "' adding ship: " << ship_id; // remove ship from old fleet if (Fleet* old_fleet = GetFleet(ship->FleetID())) old_fleet->RemoveShip(ship_id); // ensure ship is in same system as this fleet int ship_system_id = ship->SystemID(); int this_fleet_system_id = this->SystemID(); if (ship_system_id != this_fleet_system_id) if (System* system = GetSystem(this_fleet_system_id)) system->Insert(ship); // sets ship's system, remove from old system (if any) and moves ship to system's location (if necessary) // add ship to this fleet, and set its internal fleet record ship->SetFleetID(ID()); m_ships.insert(ship_id); RecalculateFleetSpeed(); StateChangedSignal(); }
double Fleet::Fuel() const { if (NumShips() < 1) return 0.0; // determine fuel available to fleet (fuel of the ship that has the least fuel in the fleet) double fuel = Meter::LARGE_VALUE; bool is_fleet_scrapped = true; for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) { const Ship* ship = GetShip(*ship_it); if (!ship) { Logger().errorStream() << "Fleet::Fuel couldn't get ship with id " << *ship_it; continue; } const Meter* meter = ship->UniverseObject::GetMeter(METER_FUEL); if (!meter) { Logger().errorStream() << "Fleet::Fuel skipping ship with no fuel meter"; continue; } if (!ship->OrderedScrapped()) { fuel = std::min(fuel, meter->Current()); is_fleet_scrapped = false; } } if (is_fleet_scrapped) { fuel = 0.0; } return fuel; }
bool Fleet::HasArmedShips() const { for (Fleet::const_iterator it = begin(); it != end(); it++) { if (const Ship* ship = GetShip(*it)) if (ship->IsArmed()) return true; } return false; }
void BombardOrder::ExecuteImpl() const { ValidateEmpireID(); int empire_id = EmpireID(); TemporaryPtr<Ship> ship = GetShip(m_ship); if (!ship) { ErrorLogger() << "BombardOrder::ExecuteImpl couldn't get ship with id " << m_ship; return; } if (!ship->CanBombard()) { ErrorLogger() << "BombardOrder::ExecuteImpl got ship that can't bombard"; return; } if (!ship->OwnedBy(empire_id)) { ErrorLogger() << "BombardOrder::ExecuteImpl got ship that isn't owned by the order-issuing empire"; return; } TemporaryPtr<Planet> planet = GetPlanet(m_planet); if (!planet) { ErrorLogger() << "BombardOrder::ExecuteImpl couldn't get planet with id " << m_planet; return; } if (planet->OwnedBy(empire_id)) { ErrorLogger() << "BombardOrder::ExecuteImpl given planet that is already owned by the order-issuing empire"; return; } if (!planet->Unowned() && Empires().GetDiplomaticStatus(planet->Owner(), empire_id) != DIPLO_WAR) { ErrorLogger() << "BombardOrder::ExecuteImpl given planet owned by an empire not at war with order-issuing empire"; return; } if (GetUniverse().GetObjectVisibilityByEmpire(m_planet, empire_id) < VIS_BASIC_VISIBILITY) { ErrorLogger() << "BombardOrder::ExecuteImpl given planet that empire reportedly has insufficient visibility of, but will be allowed to proceed pending investigation"; //return; } int ship_system_id = ship->SystemID(); if (ship_system_id == INVALID_OBJECT_ID) { ErrorLogger() << "BombardOrder::ExecuteImpl given id of ship not in a system"; return; } int planet_system_id = planet->SystemID(); if (ship_system_id != planet_system_id) { ErrorLogger() << "BombardOrder::ExecuteImpl given ids of ship and planet not in the same system"; return; } // note: multiple ships, from same or different empires, can invade the same planet on the same turn DebugLogger() << "BombardOrder::ExecuteImpl set for ship " << m_ship << " " << ship->Name() << " to bombard planet " << m_planet << " " << planet->Name(); planet->SetIsAboutToBeBombarded(true); ship->SetBombardPlanet(m_planet); if (TemporaryPtr<Fleet> fleet = GetFleet(ship->FleetID())) fleet->StateChangedSignal(); }
virtual void Spawn() { yspeed = qlerp(qfrand(), FIGHTER_1_Y_SPEED_MIN, FIGHTER_1_Y_SPEED_MAX); startTime = GetGameContext()->GetGameTime() + qfrand() * 1.0f; salvoCount = 0; movingDown = qbrand(); float yspeed = movingDown ? -FIGHTER_1_X_SPEED : FIGHTER_1_X_SPEED; GetShip()->SetVelocity(Vector2D(FIGHTER_1_X_SPEED, yspeed)); }
void CombatShip::LaunchFighters() { // Note that this just launches the fighters that can be launched on this // turn. There is currently no code that accounts for turns(!), so we're // only launching part of the fighters here and not providing for the // launches of the rest. for (FighterMap::iterator it = m_unlaunched_fighters.begin(); it != m_unlaunched_fighters.end(); ++it) { const PartType* part = GetPartType(it->first); assert(part && part->Class() == PC_FIGHTERS); std::vector<CombatFighterPtr>& fighters_vec = it->second.second; std::size_t num_fighters = fighters_vec.size(); double launch_rate = GetShip()->GetPartMeter(METER_LAUNCH_RATE, part->Name())->Current(); std::size_t launch_size = std::min<std::size_t>(num_fighters, launch_rate * it->second.first); std::size_t formation_size = std::min(CombatFighter::FORMATION_SIZE, launch_size); std::size_t num_formations = launch_size / formation_size; std::size_t final_formation_size = launch_size % formation_size; if (final_formation_size) ++num_formations; else final_formation_size = formation_size; for (std::size_t j = 0; j < num_formations; ++j) { std::size_t size = j == num_formations - 1 ? final_formation_size : formation_size; std::set<CombatFighterFormationPtr>::iterator formation_it = m_launched_formations.insert( m_pathing_engine->CreateFighterFormation( shared_from_this(), fighters_vec.end() - size, fighters_vec.end())).first; fighters_vec.resize(fighters_vec.size() - size); m_pathing_engine->AddFighterFormation(*formation_it); } GetShip()->RemoveFighters(it->first, launch_size); } }
int IssueBombardOrder(int ship_id, int planet_id) { int empire_id = AIClientApp::GetApp()->EmpireID(); // make sure ship_id is a ship... TemporaryPtr<const Ship> ship = GetShip(ship_id); if (!ship) { Logger().errorStream() << "AIInterface::IssueBombardOrder : passed an invalid ship_id"; return 0; } if (ship->TotalWeaponsDamage() <= 0) { Logger().errorStream() << "AIInterface::IssueBombardOrder : ship can't attack / bombard"; return 0; } if (!ship->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueBombardOrder : ship isn't owned by the order-issuing empire"; return 0; } // verify that planet exists and is occupied by another empire TemporaryPtr<const Planet> planet = GetPlanet(planet_id); if (!planet) { Logger().errorStream() << "AIInterface::IssueBombardOrder : no planet with passed planet_id"; return 0; } if (planet->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueBombardOrder : planet is already owned by the order-issuing empire"; return 0; } if (!planet->Unowned() && Empires().GetDiplomaticStatus(planet->Owner(), empire_id) != DIPLO_WAR) { Logger().errorStream() << "AIInterface::IssueBombardOrder : planet owned by an empire not at war with order-issuing empire"; return 0; } if (GetUniverse().GetObjectVisibilityByEmpire(planet_id, empire_id) < VIS_BASIC_VISIBILITY) { Logger().errorStream() << "AIInterface::IssueBombardOrder : planet that empire reportedly has insufficient visibility of, but will be allowed to proceed pending investigation"; //return; } int ship_system_id = ship->SystemID(); if (ship_system_id == INVALID_OBJECT_ID) { Logger().errorStream() << "AIInterface::IssueBombardOrder : given id of ship not in a system"; return 0; } int planet_system_id = planet->SystemID(); if (ship_system_id != planet_system_id) { Logger().errorStream() << "AIInterface::IssueBombardOrder : given ids of ship and planet not in the same system"; return 0; } AIClientApp::GetApp()->Orders().IssueOrder(OrderPtr(new BombardOrder(empire_id, ship_id, planet_id))); return 1; }
void CombatShip::TurnStarted(unsigned int number) { m_turn = number; m_turn_start_structure = Structure(); if (m_turn - m_enter_starlane_start_turn == ENTER_STARLANE_DELAY_TURNS) { Listener().ShipEnteredStarlane(shared_from_this()); delete m_proximity_token; m_proximity_token = 0; m_pathing_engine->RemoveObject(shared_from_this()); } else { const ShipDesign& design = *GetShip()->Design(); m_unfired_SR_weapons.resize(design.SRWeapons().size()); m_unfired_PD_weapons.clear(); std::transform(design.SRWeapons().begin(), design.SRWeapons().end(), m_unfired_SR_weapons.begin(), CopyStats<DirectFireStats>(GetShip(), FractionalStructure())); std::transform(design.PDWeapons().begin(), design.PDWeapons().end(), std::back_inserter(m_unfired_PD_weapons), CopyStats<DirectFireStats>(GetShip(), FractionalStructure())); } }
int IssueColonizeOrder(int ship_id, int planet_id) { int empire_id = AIClientApp::GetApp()->EmpireID(); // make sure ship_id is a ship... TemporaryPtr<const Ship> ship = GetShip(ship_id); if (!ship) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : passed an invalid ship_id"; return 0; } // get fleet of ship TemporaryPtr<const Fleet> fleet = GetFleet(ship->FleetID()); if (!fleet) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : ship with passed ship_id has invalid fleet_id"; return 0; } // make sure player owns ship and its fleet if (!fleet->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : empire does not own fleet of passed ship"; return 0; } if (!ship->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : empire does not own passed ship"; return 0; } // verify that planet exists and is un-occupied. TemporaryPtr<const Planet> planet = GetPlanet(planet_id); if (!planet) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : no planet with passed planet_id"; return 0; } if ((!planet->Unowned()) && !( planet->OwnedBy(empire_id) && planet->CurrentMeterValue(METER_POPULATION)==0)) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : planet with passed planet_id "<<planet_id<<" is already owned, or colonized by own empire"; return 0; } // verify that planet is in same system as the fleet if (planet->SystemID() != fleet->SystemID()) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : fleet and planet are not in the same system"; return 0; } if (ship->SystemID() == INVALID_OBJECT_ID) { Logger().errorStream() << "AIInterface::IssueColonizeOrder : ship is not in a system"; return 0; } AIClientApp::GetApp()->Orders().IssueOrder(OrderPtr(new ColonizeOrder(empire_id, ship_id, planet_id))); return 1; }
bool ScrapOrder::UndoImpl() const { ValidateEmpireID(); int empire_id = EmpireID(); if (TemporaryPtr<Ship> ship = GetShip(m_object_id)) { if (ship->OwnedBy(empire_id)) ship->SetOrderedScrapped(false); } else if (TemporaryPtr<Building> building = GetBuilding(m_object_id)) { if (building->OwnedBy(empire_id)) building->SetOrderedScrapped(false); } else { return false; } return true; }
void CombatShip::update(const float elapsed_time, bool force) { OpenSteer::Vec3 steer = m_last_steer; if (force || m_pathing_engine->UpdateNumber() % PathingEngine::UPDATE_SETS == serialNumber % PathingEngine::UPDATE_SETS) { if (m_last_queue_update_turn != m_turn) UpdateMissionQueue(); if (GetShip()->IsArmed()) FireAtHostiles(); steer = Steer(); } applySteeringForce(steer, elapsed_time); m_last_steer = steer; m_proximity_token->UpdatePosition(position()); }
void CombatShip::RecoverFighters(const CombatFighterFormationPtr& formation) { assert(!formation->empty()); m_launched_formations.erase(formation); m_pathing_engine->RemoveFighterFormation(formation); FighterMap::value_type& map_entry = *m_unlaunched_fighters.find((*formation->begin())->PartName()); std::vector<CombatFighterPtr>& fighter_vec = map_entry.second.second; fighter_vec.insert(fighter_vec.end(), formation->begin(), formation->end()); for (CombatFighterFormation::const_iterator it = formation->begin(); it != formation->end(); ++it) { (*it)->ExitSpace(); } GetShip()->AddFighters(map_entry.first, formation->size()); }
int IssueFleetTransferOrder(int ship_id, int new_fleet_id) { int empire_id = AIClientApp::GetApp()->EmpireID(); TemporaryPtr<const Ship> ship = GetShip(ship_id); if (!ship) { Logger().errorStream() << "AIInterface::IssueFleetTransferOrder : passed an invalid ship_id " << ship_id; return 0; } int ship_sys_id = ship->SystemID(); if (ship_sys_id == INVALID_OBJECT_ID) { Logger().errorStream() << "AIInterface::IssueFleetTransferOrder : ship is not in a system"; return 0; } if (!ship->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueFleetTransferOrder : passed ship_id of ship not owned by player"; return 0; } TemporaryPtr<const Fleet> fleet = GetFleet(new_fleet_id); if (!fleet) { Logger().errorStream() << "AIInterface::IssueFleetTransferOrder : passed an invalid new_fleet_id " << new_fleet_id; return 0; } int fleet_sys_id = fleet->SystemID(); if (fleet_sys_id == INVALID_OBJECT_ID) { Logger().errorStream() << "AIInterface::IssueFleetTransferOrder : new fleet is not in a system"; return 0; } if (!fleet->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueFleetTransferOrder : passed fleet_id "<< new_fleet_id << " of fleet not owned by player"; return 0; } if (fleet_sys_id != ship_sys_id) { Logger().errorStream() << "AIInterface::IssueFleetTransferOrder : new fleet in system " << fleet_sys_id << " and ship in system "<< ship_sys_id << " are not in the same system"; return 0; } std::vector<int> ship_ids; ship_ids.push_back(ship_id); AIClientApp::GetApp()->Orders().IssueOrder(OrderPtr(new FleetTransferOrder(empire_id, new_fleet_id, ship_ids))); return 1; }
void ScrapOrder::ExecuteImpl() const { ValidateEmpireID(); int empire_id = EmpireID(); if (TemporaryPtr<Ship> ship = GetShip(m_object_id)) { if (ship->SystemID() != INVALID_OBJECT_ID && ship->OwnedBy(empire_id)) { ship->SetOrderedScrapped(true); //DebugLogger() << "ScrapOrder::ExecuteImpl empire: " << empire_id // << " on ship: " << ship->ID() << " at system: " << ship->SystemID() // << " ... ordered scrapped?: " << ship->OrderedScrapped(); } } else if (TemporaryPtr<Building> building = GetBuilding(m_object_id)) { int planet_id = building->PlanetID(); if (TemporaryPtr<const Planet> planet = GetPlanet(planet_id)) { if (building->OwnedBy(empire_id) && planet->OwnedBy(empire_id)) building->SetOrderedScrapped(true); } } }
void Fleet::RecalculateFleetSpeed() { if ((m_ships.empty())) { m_speed = 0.0; return; } bool isFleetScrapped = true; m_speed = MAX_SHIP_SPEED; // max speed no ship can go faster than for (ShipIDSet::iterator it = m_ships.begin(); it != m_ships.end(); ++it) { if (const Ship* ship = GetShip(*it)) { if (!ship->OrderedScrapped()) { if (ship->Speed() < m_speed) m_speed = ship->Speed(); isFleetScrapped = false; } } } if (isFleetScrapped) m_speed = 0.0; }
void JFHumanController::DoAction(EJFActions action,bool on) { math::vector3d currentAccel=GetShip()->GetAccelState(); switch(action) { case EJF_Up: currentAccel.z=(on==true? 1:0); break; case EJF_Down: currentAccel.z=(on==true? -1:0); break; case EJF_Left: currentAccel.x=(on==true? -1:0); break; case EJF_Right: currentAccel.x=(on==true? 1:0); break; case EJF_Brake: GetShip()->Brake(on); break; case EJF_Turbo: GetShip()->Turbo(on); break; case EJF_Shoot: GetShip()->Shoot(on); break; case EJF_NextWeapon: if(on) GetShip()->SetNextWeapon(); break; case EJF_PrevWeapon: if(on) GetShip()->SetPrevWeapon(); break; } GetShip()->SetAccelState(currentAccel); }
virtual void OnSimulate(float frametime) { float originy = GetShip()->GetOrigin().y; float sizeyhalf = GetShip()->GetSize().y * 0.5f; if (!movingDown && originy - sizeyhalf < Camera::GetInstance()->GetWorldMins().y) { movingDown = true; GetShip()->SetVelocity(Vector2D(FIGHTER_1_X_SPEED, yspeed)); } else if (movingDown && originy + sizeyhalf > Camera::GetInstance()->GetWorldMaxs().y) { movingDown = false; GetShip()->SetVelocity(Vector2D(FIGHTER_1_X_SPEED, -yspeed)); } if (!IsShipFullyVisible()) { return; } if (startTime > GetGameContext()->GetGameTime()) { return; } if (GetShip()->CanShoot()) { GetShip()->Shoot(Vector2D(-1, 0), 20.0f); salvoCount++; if (salvoCount >= 3) { salvoCount = 0; startTime = GetGameContext()->GetGameTime() + 1.5f; } } }
CombatInfo::CombatInfo(int system_id_) : system_id(system_id_) { const Universe& universe = GetUniverse(); const ObjectMap& universe_objects = universe.Objects(); const System* system = universe_objects.Object<System>(system_id); if (!system) { Logger().errorStream() << "CombatInfo constructed with invalid system id: " << system_id; return; } // add copy of system to full / complete objects in combat System* copy_system = system->Clone(); objects.Insert(system_id, copy_system); // find ships and their owners in system std::vector<int> ship_ids = system->FindObjectIDs<Ship>(); for (std::vector<int>::const_iterator it = ship_ids.begin(); it != ship_ids.end(); ++it) { int ship_id = *it; const Ship* ship = GetShip(ship_id); if (!ship) { Logger().errorStream() << "CombatInfo::CombatInfo couldn't get ship with id " << ship_id << " in system " << system->Name() << " (" << system_id << ")"; continue; } // add owner to empires that have assets in this battle empire_ids.insert(ship->Owner()); // add copy of ship to full / complete copy of objects in system Ship* copy = ship->Clone(); objects.Insert(ship_id, copy); } // find planets and their owners in system std::vector<int> planet_ids = system->FindObjectIDs<Planet>(); for (std::vector<int>::const_iterator it = planet_ids.begin(); it != planet_ids.end(); ++it) { int planet_id = *it; const Planet* planet = GetPlanet(planet_id); if (!planet) { Logger().errorStream() << "CombatInfo::CombatInfo couldn't get planet with id " << planet_id << " in system " << system->Name() << " (" << system_id << ")"; continue; } // if planet is populated, add owner to empires that have assets in this battle if (planet->CurrentMeterValue(METER_POPULATION) > 0.0) empire_ids.insert(planet->Owner()); // add copy of ship to full / complete copy of objects in system Planet* copy = planet->Clone(); objects.Insert(planet_id, copy); } // TODO: should buildings be considered separately? // now that all participants in the battle have been found, loop through // objects again to assemble each participant empire's latest // known information about all objects in this battle // system for (std::set<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) { int empire_id = *empire_it; if (empire_id == ALL_EMPIRES) continue; System* visibility_limited_copy = system->Clone(empire_id); empire_known_objects[empire_id].Insert(system_id, visibility_limited_copy); } // ships for (std::vector<int>::const_iterator it = ship_ids.begin(); it != ship_ids.end(); ++it) { int ship_id = *it; const Ship* ship = GetShip(ship_id); if (!ship) { Logger().errorStream() << "CombatInfo::CombatInfo couldn't get ship with id " << ship_id << " in system " << system->Name() << " (" << system_id << ")"; continue; } const Fleet* fleet = GetFleet(ship->FleetID()); if (!fleet) { Logger().errorStream() << "CombatInfo::CombatInfo couldn't get fleet with id " << ship->FleetID() << " in system " << system->Name() << " (" << system_id << ")"; continue; } for (std::set<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) { int empire_id = *empire_it; if (empire_id == ALL_EMPIRES) continue; if (universe.GetObjectVisibilityByEmpire(ship_id, empire_id) >= VIS_BASIC_VISIBILITY || (fleet->Aggressive() && (empire_id == ALL_EMPIRES || fleet->Unowned() || Empires().GetDiplomaticStatus(empire_id, fleet->Owner()) == DIPLO_WAR))) { Ship* visibility_limited_copy = ship->Clone(empire_id); empire_known_objects[empire_id].Insert(ship_id, visibility_limited_copy); } } } // planets for (std::vector<int>::const_iterator it = planet_ids.begin(); it != planet_ids.end(); ++it) { int planet_id = *it; const Planet* planet = GetPlanet(planet_id); if (!planet) { Logger().errorStream() << "CombatInfo::CombatInfo couldn't get planet with id " << planet_id << " in system " << system->Name() << " (" << system_id << ")"; continue; } for (std::set<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) { int empire_id = *empire_it; if (empire_id == ALL_EMPIRES) continue; if (universe.GetObjectVisibilityByEmpire(planet_id, empire_id) >= VIS_BASIC_VISIBILITY) { Planet* visibility_limited_copy = planet->Clone(empire_id); empire_known_objects[empire_id].Insert(planet_id, visibility_limited_copy); } } } // after battle is simulated, any changes to latest known or actual objects // will be copied back to the main Universe's ObjectMap and the Universe's // empire latest known objects ObjectMap }
void FleetButton::Init(const std::vector<int>& fleet_IDs, SizeType size_type) { if (!scanline_shader && GetOptionsDB().Get<bool>("UI.system-fog-of-war")) { boost::filesystem::path shader_path = GetRootDataDir() / "default" / "shaders" / "scanlines.frag"; std::string shader_text; ReadFile(shader_path, shader_text); scanline_shader = boost::shared_ptr<ShaderProgram>( ShaderProgram::shaderProgramFactory("", shader_text)); } // get fleets std::vector<TemporaryPtr<const Fleet> > fleets; for (std::vector<int>::const_iterator it = fleet_IDs.begin(); it != fleet_IDs.end(); ++it) { TemporaryPtr<const Fleet> fleet = GetFleet(*it); if (!fleet) { Logger().errorStream() << "FleetButton::FleetButton couldn't get fleet with id " << *it; continue; } m_fleets.push_back(*it); fleets.push_back(fleet); } // determine owner(s) of fleet(s). Only care whether or not there is more than one owner, as owner // is used to determine colouration int owner_id = ALL_EMPIRES; int multiple_owners = false; if (fleets.empty()) { // leave as ALL_EMPIRES } else if (fleets.size() == 1) { owner_id = (*fleets.begin())->Owner(); } else { owner_id = (*fleets.begin())->Owner(); // use ALL_EMPIRES if there are multiple owners (including no owner and an owner) for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet->Owner() != owner_id) { owner_id = ALL_EMPIRES; multiple_owners = true; break; } } } // get fleet colour if (multiple_owners) { SetColor(GG::CLR_WHITE); } else if (owner_id == ALL_EMPIRES) { // all ships owned by now empire bool monsters = true; // find if any ship in fleets in button is not a monster for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; for (std::set<int>::const_iterator ship_it = fleet->ShipIDs().begin(); ship_it != fleet->ShipIDs().end(); ++ship_it) { if (TemporaryPtr<const Ship> ship = GetShip(*ship_it)) { if (!ship->IsMonster()) { monsters = false; break; } } } } if (monsters) SetColor(GG::CLR_RED); else SetColor(GG::CLR_WHITE); } else { // single empire owner if (const Empire* empire = Empires().Lookup(owner_id)) SetColor(empire->Color()); else SetColor(GG::CLR_GRAY); // should never be necessary... but just in case } // select icon(s) for fleet(s) int num_ships = 0; for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet) num_ships += fleet->NumShips(); } m_size_icon = FleetSizeIcon(num_ships, size_type); m_head_icons = FleetHeadIcons(fleets, size_type); // resize to fit icon by first determining necessary size, and then resizing GG::X texture_width(0); GG::Y texture_height(0); if (!m_head_icons.empty()) { texture_width = m_head_icons.front()->DefaultWidth(); texture_height = m_head_icons.front()->DefaultHeight(); } if (m_size_icon) { texture_width = std::max(texture_width, m_size_icon->DefaultWidth()); texture_height = std::max(texture_height, m_size_icon->DefaultHeight()); } // determine if fleet icon should be rotated. this should be done if the fleet is moving along // a starlane, which is the case if the fleet is not in a system and has a valid next system GG::Pt direction_vector(GG::X(0), GG::Y(1)); // default, unrotated button orientation TemporaryPtr<const Fleet> first_fleet; if (!m_fleets.empty()) first_fleet = *fleets.begin(); if (first_fleet && first_fleet->SystemID() == INVALID_OBJECT_ID) { int next_sys_id = first_fleet->NextSystemID(); if (TemporaryPtr<const UniverseObject> obj = GetUniverseObject(next_sys_id)) { // fleet is not in a system and has a valid next destination, so can orient it in that direction // fleet icons might not appear on the screen in the exact place corresponding to their // actual universe position, but if they're moving along a starlane, this code will assume // their apparent position will only be different from their true position in a direction // parallel with the starlane, so the direction from their true position to their destination // position can be used to get a direction vector to orient the icon double dest_x = obj->X(), dest_y = obj->Y(); double cur_x = first_fleet->X(), cur_y = first_fleet->Y(); const MapWnd* map_wnd = ClientUI::GetClientUI()->GetMapWnd(); GG::Pt dest = map_wnd->ScreenCoordsFromUniversePosition(dest_x, dest_y); GG::Pt cur = map_wnd->ScreenCoordsFromUniversePosition(cur_x, cur_y); direction_vector = dest - cur; } } // check for unrotated texture if (Value(direction_vector.x) == 0) { // not rotated. can do simple texture blits m_vertex_components.clear(); } else { // texture is rotated, so need some extra math // get rotated corner vetex x and y components (x1, y1, x2, y2, x3, y3, x4, y4) for texture of appropriate size m_vertex_components = VectorAlignedQuadVertices(direction_vector, Value(texture_height), Value(texture_width)); } // size icon according to texture size (average two dimensions) int diameter = static_cast<int>((Value(texture_width) + Value(texture_height)) / 2.0); Resize(GG::Pt(GG::X(diameter), GG::Y(diameter))); // get selection indicator texture m_selection_texture = ClientUI::GetTexture(ClientUI::ArtDir() / "icons" / "fleet" / "fleet_selection.png", true); }
void FleetButton::Init(const std::vector<int>& fleet_IDs, SizeType size_type) { //std::cout << "FleetButton::Init" << std::endl; // get fleets std::vector<TemporaryPtr<const Fleet> > fleets; for (std::vector<int>::const_iterator it = fleet_IDs.begin(); it != fleet_IDs.end(); ++it) { TemporaryPtr<const Fleet> fleet = GetFleet(*it); if (!fleet) { ErrorLogger() << "FleetButton::FleetButton couldn't get fleet with id " << *it; continue; } m_fleets.push_back(*it); fleets.push_back(fleet); } // determine owner(s) of fleet(s). Only care whether or not there is more than one owner, as owner // is used to determine colouration int owner_id = ALL_EMPIRES; int multiple_owners = false; if (fleets.empty()) { // leave as ALL_EMPIRES } else if (fleets.size() == 1) { owner_id = (*fleets.begin())->Owner(); } else { owner_id = (*fleets.begin())->Owner(); // use ALL_EMPIRES if there are multiple owners (including no owner and an owner) for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet->Owner() != owner_id) { owner_id = ALL_EMPIRES; multiple_owners = true; break; } } } // get fleet colour if (multiple_owners) { SetColor(GG::CLR_WHITE); } else if (owner_id == ALL_EMPIRES) { // all ships owned by now empire bool monsters = true; // find if any ship in fleets in button is not a monster for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; for (std::set<int>::const_iterator ship_it = fleet->ShipIDs().begin(); ship_it != fleet->ShipIDs().end(); ++ship_it) { if (TemporaryPtr<const Ship> ship = GetShip(*ship_it)) { if (!ship->IsMonster()) { monsters = false; break; } } } } if (monsters) SetColor(GG::CLR_RED); else SetColor(GG::CLR_WHITE); } else { // single empire owner if (const Empire* empire = GetEmpire(owner_id)) SetColor(empire->Color()); else SetColor(GG::CLR_GRAY); // should never be necessary... but just in case } // determine direction button should be rotated to orient along a starlane GLfloat pointing_angle = 0.0f; TemporaryPtr<const Fleet> first_fleet; if (!m_fleets.empty()) first_fleet = *fleets.begin(); if (first_fleet && first_fleet->SystemID() == INVALID_OBJECT_ID && first_fleet->NextSystemID() != INVALID_OBJECT_ID) { int next_sys_id = first_fleet->NextSystemID(); if (TemporaryPtr<const UniverseObject> obj = GetUniverseObject(next_sys_id)) { // fleet is not in a system and has a valid next destination, so can orient it in that direction // fleet icons might not appear on the screen in the exact place corresponding to their // actual universe position, but if they're moving along a starlane, this code will assume // their apparent position will only be different from their true position in a direction // parallel with the starlane, so the direction from their true position to their destination // position can be used to get a direction vector to orient the icon float dest_x = obj->X(), dest_y = obj->Y(); float cur_x = first_fleet->X(), cur_y = first_fleet->Y(); const MapWnd* map_wnd = ClientUI::GetClientUI()->GetMapWnd(); GG::Pt dest = map_wnd->ScreenCoordsFromUniversePosition(dest_x, dest_y); GG::Pt cur = map_wnd->ScreenCoordsFromUniversePosition(cur_x, cur_y); GG::Pt direction_vector = dest - cur; if (direction_vector.x != GG::X0 || direction_vector.y != GG::Y0) pointing_angle = 360.0f / TWO_PI * std::atan2(static_cast<float>(Value(direction_vector.y)), static_cast<float>(Value(direction_vector.x))) + 90; } } // select icon(s) for fleet(s) int num_ships = 0; for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet) num_ships += fleet->NumShips(); } boost::shared_ptr<GG::Texture> size_texture = FleetSizeIcon(num_ships, size_type); std::vector<boost::shared_ptr<GG::Texture> > head_textures = FleetHeadIcons(fleets, size_type); // add RotatingGraphics for all icons needed if (size_texture) { RotatingGraphic* icon = new RotatingGraphic(size_texture, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); icon->SetPhaseOffset(pointing_angle); icon->SetRPM(0.0f); icon->SetColor(this->Color()); m_icons.push_back(icon); Resize(GG::Pt(size_texture->DefaultWidth(), size_texture->DefaultHeight())); AttachChild(icon); } for (std::vector<boost::shared_ptr<GG::Texture> >::const_iterator it = head_textures.begin(); it != head_textures.end(); ++it) { RotatingGraphic* icon = new RotatingGraphic(*it, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); icon->SetPhaseOffset(pointing_angle); icon->SetRPM(0.0f); icon->SetColor(this->Color()); m_icons.push_back(icon); if (Width() < (*it)->DefaultWidth()) Resize(GG::Pt((*it)->DefaultWidth(), (*it)->DefaultHeight())); AttachChild(icon); } // set up selection indicator m_selection_indicator = new RotatingGraphic(FleetSelectionIndicatorIcon(), GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); m_selection_indicator->SetRPM(ClientUI::SystemSelectionIndicatorRPM()); LayoutIcons(); // Scanlines for not currently-visible objects? int empire_id = HumanClientApp::GetApp()->EmpireID(); if (empire_id == ALL_EMPIRES || !GetOptionsDB().Get<bool>("UI.system-fog-of-war")) return; bool at_least_one_fleet_visible = false; for (std::vector<int>::const_iterator it = m_fleets.begin(); it != m_fleets.end(); ++it) { if (GetUniverse().GetObjectVisibilityByEmpire(*it, empire_id) >= VIS_BASIC_VISIBILITY) { at_least_one_fleet_visible = true; break; } } // Create scanline renderer control m_scanline_control = new ScanlineControl(GG::X0, GG::Y0, Width(), Height()); if (!at_least_one_fleet_visible) AttachChild(m_scanline_control); }
void Fleet::MovementPhase() { //Logger().debugStream() << "Fleet::MovementPhase this: " << this->Name() << " id: " << this->ID(); m_arrived_this_turn = false; m_arrival_starlane = INVALID_OBJECT_ID; int prev_prev_system = m_prev_system; Empire* empire = Empires().Lookup(this->Owner()); // if owner of fleet can resupply ships at the location of this fleet, then // resupply all ships in this fleet if (empire && empire->FleetOrResourceSupplyableAtSystem(this->SystemID())) for (Fleet::const_iterator ship_it = this->begin(); ship_it != this->end(); ++ship_it) if (Ship* ship = GetShip(*ship_it)) ship->Resupply(); System* current_system = GetSystem(SystemID()); System* const initial_system = current_system; std::list<MovePathNode> move_path = this->MovePath(); std::list<MovePathNode>::const_iterator it = move_path.begin(); std::list<MovePathNode>::const_iterator next_it = it; if (next_it != move_path.end()) ++next_it; // is the ship stuck in a system for a whole turn? if (current_system) { // in a system. if there is no system after the current one in the // path, or the current and next nodes have the same system id, that // is an actual system, then won't be moving this turn. if ((next_it == move_path.end()) || (it->object_id != INVALID_OBJECT_ID && it->object_id == next_it->object_id) ) { // fuel regeneration for ships in stationary fleet if (this->FinalDestinationID() == INVALID_OBJECT_ID || this->FinalDestinationID() == this->SystemID()) { for (Fleet::const_iterator ship_it = this->begin(); ship_it != this->end(); ++ship_it) { if (Ship* ship = GetShip(*ship_it)) if (Meter* fuel_meter = ship->UniverseObject::GetMeter(METER_FUEL)) { fuel_meter->AddToCurrent(0.1001); fuel_meter->BackPropegate(); } } } return; } } // if fleet not moving, nothing more to do. if (move_path.empty() || move_path.size() == 1) { //Logger().debugStream() << "Fleet::MovementPhase: Fleet move path is empty or has only one entry. doing nothing"; return; } //Logger().debugStream() << "Fleet::MovementPhase move path:"; //for (std::list<MovePathNode>::const_iterator it = move_path.begin(); it != move_path.end(); ++it) // Logger().debugStream() << "... (" << it->x << ", " << it->y << ") at object id: " << it->object_id << " eta: " << it->eta << (it->turn_end ? " (end of turn)" : " (during turn)"); // move fleet in sequence to MovePathNodes it can reach this turn double fuel_consumed = 0.0; for (it = move_path.begin(); it != move_path.end(); ++it) { next_it = it; ++next_it; System* system = GetSystem(it->object_id); //Logger().debugStream() << "... node " << (system ? system->Name() : "no system"); // is this system the last node reached this turn? either it's an end of turn node, // or there are no more nodes after this one on path bool node_is_next_stop = (it->turn_end || next_it == move_path.end()); if (system) { // node is a system. explore system for all owners of this fleet if (empire) empire->AddExploredSystem(it->object_id); prev_prev_system = m_prev_system; m_prev_system = system->ID(); // passing a system, so update previous system of this fleet bool resupply_here = empire ? empire->FleetOrResourceSupplyableAtSystem(system->ID()) : false; // if this system can provide supplies, reset consumed fuel and refuel ships if (resupply_here) { //Logger().debugStream() << " ... node has fuel supply. consumed fuel for movement reset to 0 and fleet resupplied"; fuel_consumed = 0.0; for (Fleet::const_iterator ship_it = this->begin(); ship_it != this->end(); ++ship_it) { Ship* ship = GetShip(*ship_it); assert(ship); ship->Resupply(); } } if (node_is_next_stop) { // is system the last node reached this turn? system->Insert(this); // fleet ends turn at this node. insert fleet into system current_system = system; //Logger().debugStream() << "... ... inserted fleet into system"; break; } else { // fleet will continue past this system this turn. //Logger().debugStream() << "... ... moved fleet to system (not inserted)"; if (!resupply_here) { fuel_consumed += 1.0; //Logger().debugStream() << "... ... consuming 1 unit of fuel to continue moving. total fuel consumed now: " << fuel_consumed; } else { //Logger().debugStream() << "... ... not consuming fuel to depart resupply system"; } } } else { // node is not a system. if (node_is_next_stop) { // node is not a system, but is it the last node reached this turn? MoveTo(it->x, it->y); // fleet ends turn at this node. move fleet here //Logger().debugStream() << "... ... moved fleet to position"; break; } } } //Logger().debugStream() << "Fleet::MovementPhase rest of move path:"; //for (std::list<MovePathNode>::const_iterator it2 = it; it2 != move_path.end(); ++it2) // Logger().debugStream() << "... (" << it2->x << ", " << it2->y << ") at object id: " << it2->object_id << " eta: " << it2->eta << (it2->turn_end ? " (end of turn)" : " (during turn)"); // update next system if (m_moving_to != SystemID() && next_it != move_path.end() && it != move_path.end()) { // there is another system later on the path to aim for. find it for (; next_it != move_path.end(); ++next_it) { if (GetSystem(next_it->object_id)) { //Logger().debugStream() << "___ setting m_next_system to " << next_it->object_id; m_next_system = next_it->object_id; break; } } } else { // no more systems on path m_arrived_this_turn = current_system != initial_system; m_arrival_starlane = prev_prev_system; m_moving_to = m_next_system = m_prev_system = INVALID_OBJECT_ID; } // consume fuel from ships in fleet if (fuel_consumed > 0.0) { for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) if (Ship* ship = GetShip(*ship_it)) if (Meter* meter = ship->UniverseObject::GetMeter(METER_FUEL)) { meter->AddToCurrent(-fuel_consumed); meter->BackPropegate(); } } }