/// Sichtbarkeiten berechnen für Figuren mit Sichtradius (Soldaten, Erkunder) vor dem Laufen void noFigure::CalcVisibilities(const MapPoint pt) { // Sichtbarkeiten neu berechnen für Erkunder und Soldaten if(GetVisualRange()) // An alter Position neu berechnen gwg->RecalcVisibilitiesAroundPoint(pt, GetVisualRange(), player, NULL); }
void noFigure::HandleEvent(const unsigned int id) { // Bei ID = 0 ists ein Laufevent, bei allen anderen an abgeleitete Klassen weiterleiten if(id) { HandleDerivedEvent(id); } else { current_ev = NULL; WalkFigure(); // Alte Richtung und Position für die Berechnung der Sichtbarkeiten merken unsigned char old_dir = GetCurMoveDir(); MapPoint old_pos(pos); switch(fs) { case FS_GOHOME: case FS_GOTOGOAL: { WalkToGoal(); } break; case FS_JOB: { Walked(); break; } case FS_WANDER: { Wander(); break; } } // Ggf. Sichtbereich testen if(GetVisualRange()) { // Use old position (don't use this->x/y because it might be different now // Figure could be in a ship etc.) gwg->RecalcMovingVisibilities(old_pos, player, GetVisualRange(), old_dir, NULL); std::vector<noBase*> figures = gwg->GetDynamicObjectsFrom(old_pos); // Wenn Figur verschwunden ist, muss ihr ehemaliger gesamter Sichtbereich noch einmal // neue berechnet werden if(!helpers::contains(figures, this)) CalcVisibilities(old_pos); } } }
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; } }
/// Startet eine Erkundungs-Expedition void noShip::StartExplorationExpedition() { /// Schiff wird "beladen", also kurze Zeit am Hafen stehen, bevor wir bereit sind state = STATE_EXPLORATIONEXPEDITION_LOADING; current_ev = em->AddEvent(this, LOADING_TIME, 1); covered_distance = 0; home_harbor = goal_harbor_id; // Sichtbarkeiten neu berechnen gwg->SetVisibilitiesAroundPoint(pos, GetVisualRange(), player); }
void noShip::HandleState_ExplorationExpeditionDriving() { Result res; // Zum Heimathafen fahren? if(home_harbor == goal_harbor_id && covered_distance >= MAX_EXPLORATION_EXPEDITION_DISTANCE) res = DriveToHarbour(); else res = DriveToHarbourPlace(); switch(res) { default: return; case GOAL_REACHED: { // Haben wir unsere Expedition beendet? if(home_harbor == goal_harbor_id && covered_distance >= MAX_EXPLORATION_EXPEDITION_DISTANCE) { // Dann sind wir fertig -> wieder entladen state = STATE_EXPLORATIONEXPEDITION_UNLOADING; current_ev = em->AddEvent(this, UNLOADING_TIME, 1); } else { // Strecke, die wir gefahren sind, draufaddieren covered_distance += route_.size(); // Erstmal kurz ausruhen an diesem Punkt und das Rohr ausfahren, um ein bisschen // auf der Insel zu gucken state = STATE_EXPLORATIONEXPEDITION_WAITING; current_ev = em->AddEvent(this, EXPLORATION_EXPEDITION_WAITING_TIME, 1); } } break; case NO_ROUTE_FOUND: { MapPoint goal(gwg->GetHarborPoint(goal_harbor_id)); unsigned old_visual_range = GetVisualRange(); // Nichts machen und idlen StartIdling(); // Sichtbarkeiten neu berechnen gwg->RecalcVisibilitiesAroundPoint(pos, old_visual_range, player, NULL); } break; case HARBOR_DOESNT_EXIST: { // Neuen Hafen suchen if(players->getElement(player)->FindHarborForUnloading (this, pos, &goal_harbor_id, &route_, NULL)) HandleState_TransportDriving(); else // Ansonsten als verloren markieren, damit uns später Bescheid gesagt wird // wenn es einen neuen Hafen gibt lost = true; } break; } }
/// Startet eine Erkundungs-Expedition void noShip::StartExplorationExpedition(unsigned homeHarborId) { /// Schiff wird "beladen", also kurze Zeit am Hafen stehen, bevor wir bereit sind state = STATE_EXPLORATIONEXPEDITION_LOADING; current_ev = GetEvMgr().AddEvent(this, LOADING_TIME, 1); covered_distance = 0; RTTR_Assert(homeHarborId); RTTR_Assert(pos == gwg->GetCoastalPoint(homeHarborId, seaId_)); home_harbor = homeHarborId; goal_harborId = homeHarborId; // This is current goal (commands are relative to current goal) // Sichtbarkeiten neu berechnen gwg->SetVisibilitiesAroundPoint(pos, GetVisualRange(), player); }
void noShip::HandleState_ExplorationExpeditionDriving() { Result res; // Zum Heimathafen fahren? if(home_harbor == goal_harborId && covered_distance >= MAX_EXPLORATION_EXPEDITION_DISTANCE) res = DriveToHarbour(); else res = DriveToHarbourPlace(); switch(res) { case DRIVING: return; case GOAL_REACHED: { // Haben wir unsere Expedition beendet? if(home_harbor == goal_harborId && covered_distance >= MAX_EXPLORATION_EXPEDITION_DISTANCE) { // Dann sind wir fertig -> wieder entladen state = STATE_EXPLORATIONEXPEDITION_UNLOADING; current_ev = GetEvMgr().AddEvent(this, UNLOADING_TIME, 1); } else { // Strecke, die wir gefahren sind, draufaddieren covered_distance += route_.size(); // Erstmal kurz ausruhen an diesem Punkt und das Rohr ausfahren, um ein bisschen // auf der Insel zu gucken state = STATE_EXPLORATIONEXPEDITION_WAITING; current_ev = GetEvMgr().AddEvent(this, EXPLORATION_EXPEDITION_WAITING_TIME, 1); } } break; case NO_ROUTE_FOUND: case HARBOR_DOESNT_EXIST: gwg->RecalcVisibilitiesAroundPoint(pos, GetVisualRange(), player, NULL); StartIdling(); 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; } } } }