/// 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(); } }
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; } }
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; } }
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; } }
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; } }
/// 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(); } }
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; } }
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; } }
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; } } } }