Exemple #1
0
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);
}
Exemple #2
0
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);
}
Exemple #3
0
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;
    }
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
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();
}
Exemple #11
0
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;
}
Exemple #12
0
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;
}
Exemple #13
0
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));
    }
Exemple #15
0
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);
    }
}
Exemple #16
0
    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;
    }
Exemple #17
0
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()));
    }
}
Exemple #18
0
    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;
    }
Exemple #19
0
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;
}
Exemple #20
0
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());
}
Exemple #21
0
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());
}
Exemple #22
0
    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;
    }
Exemple #23
0
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);
        }
    }
}
Exemple #24
0
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;
            }
        }
    }
Exemple #27
0
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
}
Exemple #28
0
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);
}
Exemple #29
0
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);
}
Exemple #30
0
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();
                }
    }
}