예제 #1
0
/// Weist das Schiff an, eine Expedition abzubrechen (nur wenn es steht) und zum
/// Hafen zurückzukehren
void noShip::CancelExpedition()
{
    // Protect against double execution
    if(state != STATE_EXPEDITION_WAITING)
        return;

    // We are waiting. There should be no event!
    RTTR_Assert(!current_ev);

    // Zum Heimathafen zurückkehren
    // Oder sind wir schon dort?
    if(goal_harborId == home_harbor)
    {
        route_.clear();
        curRouteIdx = 0;
        state = STATE_EXPEDITION_DRIVING; //just in case the home harbor was destroyed
        HandleState_ExpeditionDriving();
    }
    else
    {
        state = STATE_EXPEDITION_DRIVING;
        goal_harborId = home_harbor;
        StartDrivingToHarborPlace();
        HandleState_ExpeditionDriving();
    }
}
예제 #2
0
void noShip::Driven()
{
    MapPoint enemy_territory_discovered(0xffff, 0xffff);
    gwg->RecalcMovingVisibilities(pos, player, GetVisualRange(), GetCurMoveDir(), &enemy_territory_discovered);

    // Feindliches Territorium entdeckt?
    if(enemy_territory_discovered.x != 0xffff)
    {
        // Send message if necessary
        if(players->getElement(player)->ShipDiscoveredHostileTerritory
                (enemy_territory_discovered) && player == GAMECLIENT.GetPlayerID())
            GAMECLIENT.SendPostMessage(new PostMsgWithLocation(_("A ship disovered an enemy territory"), PMC_MILITARY, enemy_territory_discovered));

    }

    switch(state)
    {
        case STATE_GOTOHARBOR: HandleState_GoToHarbor(); break;
        case STATE_EXPEDITION_DRIVING: HandleState_ExpeditionDriving(); break;
        case STATE_EXPLORATIONEXPEDITION_DRIVING: HandleState_ExplorationExpeditionDriving(); break;
        case STATE_TRANSPORT_DRIVING: HandleState_TransportDriving(); break;
        case STATE_SEAATTACK_DRIVINGTODESTINATION: HandleState_SeaAttackDriving(); break;
        case STATE_SEAATTACK_RETURN: HandleState_SeaAttackReturn(); break;
        default:
            break;
    }
}
예제 #3
0
void noShip::Driven()
{
    MapPoint enemy_territory_discovered(MapPoint::Invalid());
    gwg->RecalcMovingVisibilities(pos, player, GetVisualRange(), GetCurMoveDir(), &enemy_territory_discovered);

    // Feindliches Territorium entdeckt?
    if(enemy_territory_discovered.isValid())
    {
        // Send message if necessary
        if(gwg->GetPlayer(player).ShipDiscoveredHostileTerritory(enemy_territory_discovered))
            SendPostMessage(player, new PostMsg(GetEvMgr().GetCurrentGF(), _("A ship disovered an enemy territory"), PostCategory::Military, enemy_territory_discovered));
    }

    switch(state)
    {
        case STATE_GOTOHARBOR: HandleState_GoToHarbor(); break;
        case STATE_EXPEDITION_DRIVING: HandleState_ExpeditionDriving(); break;
        case STATE_EXPLORATIONEXPEDITION_DRIVING: HandleState_ExplorationExpeditionDriving(); break;
        case STATE_TRANSPORT_DRIVING: HandleState_TransportDriving(); break;
        case STATE_SEAATTACK_DRIVINGTODESTINATION: HandleState_SeaAttackDriving(); break;
        case STATE_SEAATTACK_RETURN_DRIVING: HandleState_SeaAttackReturn(); break;
        default:
            RTTR_Assert(false);
            break;
    }
}
예제 #4
0
void noShip::FindUnloadGoal(State newState)
{
    state = newState;
    // Das Schiff muss einen Notlandeplatz ansteuern
    // Neuen Hafen suchen
    if(gwg->GetPlayer(player).FindHarborForUnloading(this, pos, &goal_harborId, &route_, NULL))
    {
        curRouteIdx = 0;
        home_harbor = goal_harborId; // To allow unloading here
        if(state == STATE_EXPEDITION_DRIVING)
            HandleState_ExpeditionDriving();
        else if(state == STATE_TRANSPORT_DRIVING)
            HandleState_TransportDriving();
        else if(state == STATE_SEAATTACK_RETURN_DRIVING)
            HandleState_SeaAttackReturn();
        else
        {
            RTTR_Assert(false);
            LOG.write("Bug detected: Invalid state for FindUnloadGoal");
            FindUnloadGoal(STATE_TRANSPORT_DRIVING);
        }
    }
    else
    {
        // Ansonsten als verloren markieren, damit uns später Bescheid gesagt wird
        // wenn es einen neuen Hafen gibt
        home_harbor = goal_harborId = 0;
        lost = true;
    }
}
예제 #5
0
void noShip::HandleState_ExpeditionDriving()
{
    Result res;
    // Zum Heimathafen fahren?
    if(home_harbor == goal_harbor_id)
        res = DriveToHarbour();
    else
        res = DriveToHarbourPlace();

    switch(res)
    {
        default: return;
        case GOAL_REACHED:
        {
            // Haben wir unsere Expedition beendet?
            if(home_harbor == goal_harbor_id)
            {
                // Sachen wieder in den Hafen verladen
                state = STATE_EXPEDITION_UNLOADING;
                current_ev = em->AddEvent(this, UNLOADING_TIME, 1);
            }
            else
            {
                // Warten auf weitere Anweisungen
                state = STATE_EXPEDITION_WAITING;

                // Spieler benachrichtigen
                if(GAMECLIENT.GetPlayerID() == this->player)
                    GAMECLIENT.SendPostMessage(new ShipPostMsg(_("A ship has reached the destination of its expedition."), PMC_GENERAL, GAMECLIENT.GetPlayer(player).nation, pos));

                // KI Event senden
                GAMECLIENT.SendAIEvent(new AIEvent::Location(AIEvent::ExpeditionWaiting, pos), player);
            }
        } break;
        case NO_ROUTE_FOUND:
        {
            MapPoint goal(gwg->GetHarborPoint(goal_harbor_id));
            // Nichts machen und idlen
            StartIdling();
        } break;
        case HARBOR_DOESNT_EXIST: //should only happen when an expedition is cancelled and the home harbor no longer exists
        {
            // Kein Heimathafen mehr?
            // Das Schiff muss einen Notlandeplatz ansteuern
            if(players->getElement(player)->FindHarborForUnloading(this, pos, &goal_harbor_id, &route_, NULL))
            {
                curRouteIdx = 0;
                home_harbor = goal_harbor_id; //set new home=goal so we will actually unload once we reach the goal
                HandleState_ExpeditionDriving();
            }
            else
            {
                // Ansonsten als verloren markieren, damit uns später Bescheid gesagt wird
                // wenn es einen neuen Hafen gibt
                lost = true;
            }
        } break;
    }
}
예제 #6
0
/// Weist das Schiff an, eine Expedition abzubrechen (nur wenn es steht) und zum
/// Hafen zurückzukehren
void noShip::CancelExpedition()
{
    // Zum Heimathafen zurückkehren
    // Oder sind wir schon dort?
    if(goal_harbor_id == home_harbor)
    {
        route_.clear();
        curRouteIdx = 0;
        state = STATE_EXPEDITION_DRIVING; //just in case the home harbor was destroyed
        HandleState_ExpeditionDriving();
    }
    else
    {
        state = STATE_EXPEDITION_DRIVING;
        goal_harbor_id = home_harbor;
        StartDrivingToHarborPlace();
        HandleState_ExpeditionDriving();
    }
}
예제 #7
0
void noShip::HandleState_ExpeditionDriving()
{
    Result res;
    // Zum Heimathafen fahren?
    if(home_harbor == goal_harborId)
        res = DriveToHarbour();
    else
        res = DriveToHarbourPlace();

    switch(res)
    {
        case DRIVING: return;
        case GOAL_REACHED:
        {
            // Haben wir unsere Expedition beendet?
            if(home_harbor == goal_harborId)
            {
                // Sachen wieder in den Hafen verladen
                state = STATE_EXPEDITION_UNLOADING;
                current_ev = GetEvMgr().AddEvent(this, UNLOADING_TIME, 1);
            }
            else
            {
                // Warten auf weitere Anweisungen
                state = STATE_EXPEDITION_WAITING;

                // Spieler benachrichtigen
                SendPostMessage(player, new ShipPostMsg(GetEvMgr().GetCurrentGF(), _("A ship has reached the destination of its expedition."), PostCategory::Economy, *this));
                gwg->GetNotifications().publish(ExpeditionNote(ExpeditionNote::Waiting, player, pos));
            }
        } break;
        case NO_ROUTE_FOUND:
        case HARBOR_DOESNT_EXIST: //should only happen when an expedition is cancelled and the home harbor no longer exists
        {
            if(home_harbor != goal_harborId && home_harbor != 0)
            {
                // Try to go back
                goal_harborId = home_harbor;
                HandleState_ExpeditionDriving();
            }else
                FindUnloadGoal(STATE_EXPEDITION_DRIVING); // Unload anywhere!
        } break;
    }
}
예제 #8
0
void noShip::HandleEvent(const unsigned int id)
{
    current_ev = 0;

    switch(id)
    {
            // Laufevent
        case 0:
        {
            // neue Position einnehmen
            Walk();

            // entscheiden, was als nächstes zu tun ist
            Driven();
        } break;
        default:
        {
            switch(state)
            {
                default: break;
                case STATE_EXPEDITION_LOADING:
                {
                    // Schiff ist nun bereit und Expedition kann beginnen
                    state = STATE_EXPEDITION_WAITING;

                    // Spieler benachrichtigen
                    if(GAMECLIENT.GetPlayerID() == this->player)
                        GAMECLIENT.SendPostMessage(new ShipPostMsg(_("A ship is ready for an expedition."), PMC_GENERAL, GAMECLIENT.GetPlayer(player).nation, pos));

                    // KI Event senden
                    GAMECLIENT.SendAIEvent(new AIEvent::Location(AIEvent::ExpeditionWaiting, pos), player);
                } break;
                case STATE_EXPLORATIONEXPEDITION_LOADING:
                {
                    // Schiff ist nun bereit und Expedition kann beginnen
                    ContinueExplorationExpedition();
                } break;
                case STATE_EXPLORATIONEXPEDITION_WAITING:
                {
                    // Schiff ist nun bereit und Expedition kann beginnen
                    ContinueExplorationExpedition();
                } break;

                case STATE_EXPEDITION_UNLOADING:
                {
                    // Hafen herausfinden
                    MapPoint goal_pos(gwg->GetHarborPoint(goal_harbor_id));
                    noBase* hb = gwg->GetNO(goal_pos);

                    if(hb->GetGOT() == GOT_NOB_HARBORBUILDING)
                    {
                        Goods goods;
                        memset(&goods, 0, sizeof(Goods));
                        unsigned char nation = players->getElement(player)->nation;
                        goods.goods[GD_BOARDS] = BUILDING_COSTS[nation][BLD_HARBORBUILDING].boards;
                        goods.goods[GD_STONES] = BUILDING_COSTS[nation][BLD_HARBORBUILDING].stones;
                        goods.people[JOB_BUILDER] = 1;
                        static_cast<nobBaseWarehouse*>(hb)->AddGoods(goods);
                        // Wieder idlen und ggf. neuen Job suchen
                        StartIdling();
                        players->getElement(player)->GetJobForShip(this);
                    }
                    else
                    {
                        // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state
                        state = STATE_EXPEDITION_DRIVING;
                        HandleState_ExpeditionDriving();
                    }

                } break;
                case STATE_EXPLORATIONEXPEDITION_UNLOADING:
                {
                    // Hafen herausfinden
                    MapPoint goal_pos(gwg->GetHarborPoint(goal_harbor_id));
                    noBase* hb = gwg->GetNO(goal_pos);

                    unsigned old_visual_range = GetVisualRange();

                    if(hb->GetGOT() == GOT_NOB_HARBORBUILDING)
                    {
                        // Späher wieder entladen
                        Goods goods;
                        memset(&goods, 0, sizeof(Goods));
                        goods.people[JOB_SCOUT] = SCOUTS_EXPLORATION_EXPEDITION;
                        static_cast<nobBaseWarehouse*>(hb)->AddGoods(goods);
                        // Wieder idlen und ggf. neuen Job suchen
                        StartIdling();
                        players->getElement(player)->GetJobForShip(this);
                    }
                    else
                    {
                        // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state
                        state = STATE_EXPLORATIONEXPEDITION_DRIVING;
                        HandleState_ExplorationExpeditionDriving();
                    }

                    // Sichtbarkeiten neu berechnen
                    gwg->RecalcVisibilitiesAroundPoint(pos, old_visual_range, player, NULL);


                } break;
                case STATE_TRANSPORT_LOADING:
                {
                    StartTransport();
                } break;
                case STATE_TRANSPORT_UNLOADING:
                {
                    // Hafen herausfinden
                    remaining_sea_attackers = 0; //can be 1 in case we had sea attackers on board - set to 1 for a special check when the return harbor is destroyed to set the returning attackers goal to 0
                    MapPoint goal_pos(gwg->GetHarborPoint(goal_harbor_id));
                    noBase* hb = gwg->GetNO(goal_pos);
                    if(hb->GetGOT() == GOT_NOB_HARBORBUILDING)
                    {
                        static_cast<nobHarborBuilding*>(hb)->ReceiveGoodsFromShip(figures, wares);
                        figures.clear();
                        wares.clear();

                        // Hafen bescheid sagen, dass er das Schiff nun nutzen kann
                        static_cast<nobHarborBuilding*>(hb)->ShipArrived(this);

                        // Hafen hat keinen Job für uns?
                        if (state == STATE_TRANSPORT_UNLOADING)
                        {
                            // Wieder idlen und ggf. neuen Job suchen
                            StartIdling();
                            players->getElement(player)->GetJobForShip(this);
                        }
                    }
                    else
                    {
                        // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state
                        state = STATE_TRANSPORT_DRIVING;
                        HandleState_TransportDriving();
                    }


                } break;
                case STATE_SEAATTACK_LOADING:
                {
                    StartSeaAttack();
                } break;
                case STATE_SEAATTACK_WAITING:
                {
                    // Nächsten Soldaten nach draußen beordern
                    if(figures.empty())
                        break;

                    nofAttacker* attacker = static_cast<nofAttacker*>(*figures.begin());
                    // Evtl. ist ein Angreifer schon fertig und wieder an Board gegangen
                    // der darf dann natürlich nicht noch einmal raus, sonst kann die schöne Reise
                    // böse enden
                    if(attacker->IsSeaAttackCompleted())
                        break;

                    figures.pop_front();
                    gwg->AddFigure(attacker, pos);

                    current_ev = em->AddEvent(this, 30, 1);
                    attacker->StartAttackOnOtherIsland(pos, GetObjId());
                    ;
                };
                case STATE_SEAATTACK_UNLOADING:
                {
                } break;
            }
        } break;

    }

}
예제 #9
0
void noShip::HandleEvent(const unsigned int id)
{
    RTTR_Assert(current_ev);
    RTTR_Assert(current_ev->id == id);
    current_ev = NULL;

    if(id == 0)
    {
        // Move event
        // neue Position einnehmen
        Walk();
        // entscheiden, was als nächstes zu tun ist
        Driven();
    }else
    {
        switch(state)
        {
        default: 
            RTTR_Assert(false);
            LOG.write("Bug detected: Invalid state in ship event");
            break;
        case STATE_EXPEDITION_LOADING:
            // Schiff ist nun bereit und Expedition kann beginnen
            state = STATE_EXPEDITION_WAITING;

            // Spieler benachrichtigen
            SendPostMessage(player, new ShipPostMsg(GetEvMgr().GetCurrentGF(), _("A ship is ready for an expedition."), PostCategory::Economy, *this));
            gwg->GetNotifications().publish(ExpeditionNote(ExpeditionNote::Waiting, player, pos));
            break;
        case STATE_EXPLORATIONEXPEDITION_LOADING:
        case STATE_EXPLORATIONEXPEDITION_WAITING:
            // Schiff ist nun bereit und Expedition kann beginnen
            ContinueExplorationExpedition();
            break;
        case STATE_EXPEDITION_UNLOADING:
        {
            // Hafen herausfinden
            noBase* hb = goal_harborId ? gwg->GetNO(gwg->GetHarborPoint(goal_harborId)) : NULL;

            if(hb && hb->GetGOT() == GOT_NOB_HARBORBUILDING)
            {
                Inventory goods;
                unsigned char nation = gwg->GetPlayer(player).nation;
                goods.goods[GD_BOARDS] = BUILDING_COSTS[nation][BLD_HARBORBUILDING].boards;
                goods.goods[GD_STONES] = BUILDING_COSTS[nation][BLD_HARBORBUILDING].stones;
                goods.people[JOB_BUILDER] = 1;
                static_cast<nobBaseWarehouse*>(hb)->AddGoods(goods, false);
                // Wieder idlen und ggf. neuen Job suchen
                StartIdling();
                gwg->GetPlayer(player).GetJobForShip(this);
            }
            else
            {
                // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state
                state = STATE_EXPEDITION_DRIVING;
                HandleState_ExpeditionDriving();
            }
            break;
        }
        case STATE_EXPLORATIONEXPEDITION_UNLOADING:
        {
            // Hafen herausfinden
            noBase* hb = goal_harborId ? gwg->GetNO(gwg->GetHarborPoint(goal_harborId)): NULL;

            unsigned old_visual_range = GetVisualRange();

            if(hb && hb->GetGOT() == GOT_NOB_HARBORBUILDING)
            {
                // Späher wieder entladen
                Inventory goods;
                goods.people[JOB_SCOUT] = gwg->GetGGS().GetNumScoutsExedition();
                static_cast<nobBaseWarehouse*>(hb)->AddGoods(goods, false);
                // Wieder idlen und ggf. neuen Job suchen
                StartIdling();
                gwg->GetPlayer(player).GetJobForShip(this);
            }
            else
            {
                // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state
                state = STATE_EXPLORATIONEXPEDITION_DRIVING;
                HandleState_ExplorationExpeditionDriving();
            }

            // Sichtbarkeiten neu berechnen
            gwg->RecalcVisibilitiesAroundPoint(pos, old_visual_range, player, NULL);

            break;
        }
        case STATE_TRANSPORT_LOADING:
            StartTransport();
            break;
        case STATE_TRANSPORT_UNLOADING:
        case STATE_SEAATTACK_UNLOADING:
        {
            // Hafen herausfinden
            RTTR_Assert(state == STATE_SEAATTACK_UNLOADING || remaining_sea_attackers == 0);
            noBase* hb = goal_harborId ? gwg->GetNO(gwg->GetHarborPoint(goal_harborId)): NULL;
            if(hb && hb->GetGOT() == GOT_NOB_HARBORBUILDING)
            {
                static_cast<nobHarborBuilding*>(hb)->ReceiveGoodsFromShip(figures, wares);
                figures.clear();
                wares.clear();

                state = STATE_TRANSPORT_UNLOADING;
                // Hafen bescheid sagen, dass er das Schiff nun nutzen kann
                static_cast<nobHarborBuilding*>(hb)->ShipArrived(this);

                // Hafen hat keinen Job für uns?
                if (state == STATE_TRANSPORT_UNLOADING)
                {
                    // Wieder idlen und ggf. neuen Job suchen
                    StartIdling();
                    gwg->GetPlayer(player).GetJobForShip(this);
                }
            }
            else
            {
                // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state
                if(state == STATE_TRANSPORT_UNLOADING)
                    FindUnloadGoal(STATE_TRANSPORT_DRIVING);
                else
                    FindUnloadGoal(STATE_SEAATTACK_RETURN_DRIVING);
            }
            break;
        }
        case STATE_SEAATTACK_LOADING:
            StartSeaAttack();
            break;
        case STATE_SEAATTACK_WAITING:
        {
            // Nächsten Soldaten nach draußen beordern
            if(figures.empty())
                break;

            nofAttacker* attacker = static_cast<nofAttacker*>(figures.front());
            // Evtl. ist ein Angreifer schon fertig und wieder an Board gegangen
            // der darf dann natürlich nicht noch einmal raus, sonst kann die schöne Reise
            // böse enden
            if(attacker->IsSeaAttackCompleted())
                break;

            figures.pop_front();
            gwg->AddFigure(attacker, pos);

            current_ev = GetEvMgr().AddEvent(this, 30, 1);
            attacker->StartAttackOnOtherIsland(pos, GetObjId());
            break;
        }
        }
    }
}