GoodType nofMetalworker::GetOrderedTool() { // qx:tools int prio = -1; int tool = -1; GameClientPlayer& owner = gwg->GetPlayer(player); for (unsigned i = 0; i < TOOL_COUNT; ++i) { if (owner.tools_ordered[i] > 0 && (owner.toolsSettings_[i] > prio) ) { prio = owner.toolsSettings_[i]; tool = i; } } if (tool != -1) { --owner.tools_ordered[tool]; if (ToolsOrderedTotal() == 0) SendPostMessage(player, new PostMsg(GetEvMgr().GetCurrentGF(), _("Completed the ordered amount of tools."), PMC_GENERAL)); gwg->GetNotifications().publish(ToolNote(ToolNote::OrderCompleted, player)); return TOOLS_SETTINGS_IDS[tool]; } return GD_NOTHING; }
/// Das Schiff wird um eine Stufe weitergebaut void noShipBuildingSite::MakeBuildStep() { ++progress; // Schiff fertiggestellt? if(progress > PROGRESS_PARTS[0] + PROGRESS_PARTS[1] + PROGRESS_PARTS[2]) { // Replace me by ship GetEvMgr().AddToKillList(this); gwg->SetNO(pos, NULL); noShip* ship = new noShip(pos, player); gwg->AddFigure(ship, pos); // Schiff registrieren lassen gwg->GetPlayer(player).RegisterShip(ship); // BQ neu berechnen, da Schiff nicht mehr blockiert gwg->RecalcBQAroundPointBig(pos); // Spieler über Fertigstellung benachrichtigen SendPostMessage(player, new ShipPostMsg(GetEvMgr().GetCurrentGF(), _("A new ship is ready"), PostCategory::Economy, *ship)); gwg->GetNotifications().publish(ShipNote(ShipNote::Constructed, player, pos)); } }
void nobUsual::OnOutOfResources() { // Post verschicken, keine Rohstoffe mehr da if(outOfRessourcesMsgSent) return; outOfRessourcesMsgSent = true; productivity = 0; std::fill(last_productivities.begin(), last_productivities.end(), 0); const char* error; if(GetBuildingType() == BLD_WELL) error = _("This well has dried out"); else if(BuildingProperties::IsMine(GetBuildingType())) error = _("This mine is exhausted"); else if(GetBuildingType() == BLD_QUARRY) error = _("No more stones in range"); else if(GetBuildingType() == BLD_FISHERY) error = _("No more fishes in range"); else return; SendPostMessage(player, new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), error, PostCategory::Economy, *this)); gwg->GetNotifications().publish(BuildingNote(BuildingNote::NoRessources, player, GetPos(), GetBuildingType())); if(GAMECLIENT.GetPlayerId() == player && gwg->GetGGS().isEnabled(AddonId::DEMOLISH_BLD_WO_RES)) { GAMECLIENT.DestroyBuilding(GetPos()); } }
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::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 nofGeologist::SetSign(Resource resources) { RTTR_Assert(resources.getType() != Resource::Fish); // Shall never happen // Bestimmte Objekte können gelöscht werden NodalObjectType noType = gwg->GetNO(pos)->GetType(); if(noType != NOP_NOTHING && noType != NOP_ENVIRONMENT) return; gwg->DestroyNO(pos, false); // Schild setzen gwg->SetNO(pos, new noSign(pos, resources)); // If nothing found, there is nothing left to do if(resources.getAmount() == 0u) return; if(!resAlreadyFound[resources.getType()] && !IsSignInArea(resources.getType())) { const char* msg; switch(resources.getType()) { case Resource::Iron: msg = _("Found iron ore"); break; case Resource::Gold: msg = _("Found gold"); break; case Resource::Coal: msg = _("Found coal"); break; case Resource::Granite: msg = _("Found granite"); break; case Resource::Water: msg = _("Found water"); break; default: RTTR_Assert(false); return; } if(resources.getType() != Resource::Water || gwg->GetGGS().getSelection(AddonId::EXHAUSTIBLE_WATER) != 1) { SendPostMessage(player, new PostMsg(GetEvMgr().GetCurrentGF(), msg, PostCategory::Geologist, pos)); } gwg->GetNotifications().publish(ResourceNote(player, pos, resources)); if(gwg->HasLua()) gwg->GetLua().EventResourceFound(this->player, pos, resources.getType(), resources.getAmount()); } resAlreadyFound[resources.getType()] = true; }
void nobMilitary::HitOfCatapultStone() { // Ein Soldat weniger, falls es noch welche gibt if(!troops.empty()) { nofPassiveSoldier* soldier = *troops.begin(); helpers::pop_front(troops); // Shortcut for Die(): No need to remove from world as it is inside and we can delete it right away soldier->RemoveFromInventory(); soldier->LeftBuilding(); soldier->Destroy(); deletePtr(soldier); } // If there are troops left, order some more, else this will be destroyed if(!troops.empty()) RegulateTroops(); // Post verschicken SendPostMessage(player, new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("A catapult is firing upon us!"), PMC_MILITARY, *this)); }
GoodType nofMetalworker::GetOrderedTool() { GamePlayer& owner = gwg->GetPlayer(player); std::vector<uint8_t> random_array; for(unsigned i = 0; i < NUM_TOOLS; ++i) { if(owner.GetToolsOrdered(i) == 0) continue; unsigned toolPriority = std::max(owner.GetToolPriority(i), 1u); random_array.insert(random_array.end(), toolPriority, i); } if(random_array.empty()) return GD_NOTHING; unsigned toolIdx = random_array[RANDOM_RAND(GetObjId(), random_array.size())]; owner.ToolOrderProcessed(toolIdx); if(!HasToolOrder()) SendPostMessage(player, new PostMsg(GetEvMgr().GetCurrentGF(), _("Completed the ordered amount of tools."), PostCategory::Economy)); return TOOLS[toolIdx]; }
void nobMilitary::AddPassiveSoldier(nofPassiveSoldier* soldier) { RTTR_Assert(soldier->GetPlayer() == player); RTTR_Assert(troops.size() < unsigned(TROOPS_COUNT[nation][size])); troops.insert(soldier); // und aus den bestllten Truppen raushauen, da er ja jetzt hier ist ordered_troops.erase(soldier); // Wurde dieses Gebäude zum ersten Mal besetzt? if(new_built) { SendPostMessage(player, new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("Military building occupied"), PMC_MILITARY, *this)); // Ist nun besetzt new_built = false; // Landgrenzen verschieben gwg->RecalcTerritory(*this, false, true); // Tür zumachen CloseDoor(); // Fanfarensound abspieln, falls das Militärgebäude im Sichtbereich ist und unseres ist gwg->MilitaryBuildingCaptured(pos, player); gwg->GetNotifications().publish(BuildingNote(BuildingNote::Captured, player, pos, type_)); } else { // Evtl. Soldaten befördern PrepareUpgrading(); } if( mAutoTrain ) RegulateTroops(); // Goldmünzen suchen, evtl sinds ja neue Soldaten SearchCoins(); }
/// Ist am Militärgebäude angekommen void nofAttacker::ReachedDestination() { // Sind wir direkt an der Flagge? if(pos == attacked_goal->GetFlag()->GetPos()) { // Building already captured? Continue capturing // This can only be a far away attacker if(attacked_goal->GetPlayer() == player) { state = STATE_ATTACKING_CAPTURINGNEXT; RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal)); auto* goal = static_cast<nobMilitary*>(attacked_goal); RTTR_Assert(goal->IsFarAwayCapturer(this)); // Start walking first so the flag is free StartWalking(Direction::NORTHWEST); // Then tell the building goal->FarAwayCapturerReachedGoal(this); return; } // Post schicken "Wir werden angegriffen" TODO evtl. unschön, da jeder Attacker das dann aufruft SendPostMessage(attacked_goal->GetPlayer(), new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("We are under attack!"), PostCategory::Military, *attacked_goal)); // Dann Verteidiger rufen if(attacked_goal->CallDefender(this)) { // Verteidiger gefunden --> hinstellen und auf ihn warten SwitchStateAttackingWaitingForDefender(); } else { // kein Verteidiger gefunden --> ins Gebäude laufen und es erobern state = STATE_ATTACKING_CAPTURINGFIRST; StartWalking(Direction::NORTHWEST); // Normalen Militärgebäuden schonmal Bescheid sagen if(attacked_goal->GetGOT() == GOT_NOB_MILITARY) static_cast<nobMilitary*>(attacked_goal)->PrepareCapturing(); } } else { // dann hinstellen und warten, bis wir an die Reihe kommmen mit Kämpfen und außerdem diesen Platz // reservieren, damit sich kein anderer noch hier hinstellt state = STATE_ATTACKING_WAITINGAROUNDBUILDING; // zur Flagge hin ausrichten Direction dir(Direction::WEST); MapPoint attFlagPos = attacked_goal->GetFlag()->GetPos(); if(pos.y == attFlagPos.y && pos.x <= attFlagPos.x) dir = Direction::EAST; else if(pos.y == attFlagPos.y && pos.x > attFlagPos.x) dir = Direction::WEST; else if(pos.y < attFlagPos.y && pos.x < attFlagPos.x) dir = Direction::SOUTHEAST; else if(pos.y < attFlagPos.y && pos.x > attFlagPos.x) dir = Direction::SOUTHWEST; else if(pos.y > attFlagPos.y && pos.x < attFlagPos.x) dir = Direction::NORTHEAST; else if(pos.y > attFlagPos.y && pos.x > attFlagPos.x) dir = Direction::NORTHWEST; else /* (pos.x == attFlagPos.x)*/ { if(pos.y < attFlagPos.y && !(safeDiff(pos.y, attFlagPos.y) & 1)) dir = Direction::SOUTHEAST; else if(pos.y < attFlagPos.y && (safeDiff(pos.y, attFlagPos.y) & 1)) { if(pos.y & 1) dir = Direction::SOUTHWEST; else dir = Direction::SOUTHEAST; } else if(pos.y > attFlagPos.y && !(safeDiff(pos.y, attFlagPos.y) & 1)) dir = Direction::NORTHEAST; else /* (pos.y > attFlagPos.y && (safeDiff(pos.y, attFlagPos.y) & 1))*/ { if(pos.y & 1) dir = Direction::NORTHWEST; else dir = Direction::NORTHEAST; } } FaceDir(dir); if(attacked_goal->GetPlayer() == player) { // Building already captured? -> Then we might be a far-away-capturer // -> Tell the building, that we are here RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal)); auto* goal = static_cast<nobMilitary*>(attacked_goal); if(goal->IsFarAwayCapturer(this)) goal->FarAwayCapturerReachedGoal(this); } } }
void nofAttacker::Walked() { ExpelEnemies(); // Was bestimmtes machen, je nachdem welchen Status wir gerade haben switch(state) { default: nofActiveSoldier::Walked(); break; case STATE_ATTACKING_WALKINGTOGOAL: { MissAttackingWalk(); } break; case STATE_ATTACKING_ATTACKINGFLAG: { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } MapPoint goalFlagPos = attacked_goal->GetFlag()->GetPos(); // RTTR_Assert(enemy->GetGOT() == GOT_NOF_DEFENDER); // Are we at the flag? nofDefender* defender = nullptr; // Look for defenders at this position const std::list<noBase*>& figures = gwg->GetFigures(goalFlagPos); for(auto figure : figures) { if(figure->GetGOT() == GOT_NOF_DEFENDER) { // Is the defender waiting at the flag? // (could be wandering around or something) if(static_cast<nofDefender*>(figure)->IsWaitingAtFlag()) { defender = static_cast<nofDefender*>(figure); } } } if(pos == goalFlagPos) { if(defender) { // Start fight with the defender gwg->AddFigure(pos, new noFighting(this, defender)); // Set the appropriate states state = STATE_ATTACKING_FIGHTINGVSDEFENDER; defender->FightStarted(); } else // No defender at the flag? // -> Order new defenders or capture the building ContinueAtFlag(); } else { unsigned char dir = gwg->FindHumanPath(pos, goalFlagPos, 5, true); if(dir == 0xFF) { // es wurde kein Weg mehr gefunden --> neues Plätzchen suchen und warten state = STATE_ATTACKING_WALKINGTOGOAL; MissAttackingWalk(); // der Verteidiger muss darüber informiert werden if(defender) defender->AttackerArrested(); } else { // Hinlaufen StartWalking(Direction(dir)); } } } break; case STATE_ATTACKING_CAPTURINGFIRST: { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } // Wenn schon welche drin sind, ist wieder ein feindlicher reingegangen if(attacked_goal->DefendersAvailable()) { // Wieder rausgehen, Platz reservieren if(attacked_goal->GetGOT() == GOT_NOB_MILITARY) static_cast<nobMilitary*>(attacked_goal)->StopCapturing(); state = STATE_ATTACKING_WALKINGTOGOAL; StartWalking(Direction::SOUTHEAST); return; } else { // Ist das Gebäude ein "normales Militärgebäude", das wir da erobert haben? if(BuildingProperties::IsMilitary(attacked_goal->GetBuildingType())) { RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal)); // Meinem Heimatgebäude Bescheid sagen, dass ich nicht mehr komme (falls es noch eins gibt) if(building) building->SoldierLost(this); CancelAtHuntingDefender(); // Ggf. Schiff Bescheid sagen (Schiffs-Angreifer) if(ship_obj_id) CancelAtShip(); // Gebäude einnehmen auto* goal = static_cast<nobMilitary*>(attacked_goal); goal->Capture(player); // This is the new home building = attacked_goal; // mich zum Gebäude hinzufügen und von der Karte entfernen attacked_goal->AddActiveSoldier(this); RemoveFromAttackedGoal(); // Tell that we arrived and probably call other capturers goal->CapturingSoldierArrived(); gwg->RemoveFigure(pos, this); } // oder ein Hauptquartier oder Hafen? else { // Inform the owner of the building const std::string msg = (attacked_goal->GetGOT() == GOT_NOB_HQ) ? _("Our headquarters was destroyed!") : _("This harbor building was destroyed"); SendPostMessage(attacked_goal->GetPlayer(), new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), msg, PostCategory::Military, *attacked_goal)); // abreißen nobBaseMilitary* tmp_goal = attacked_goal; // attacked_goal wird evtl auf 0 gesetzt! tmp_goal->Destroy(); delete tmp_goal; attacked_goal = nullptr; ReturnHomeMissionAttacking(); } } } break; case STATE_ATTACKING_CAPTURINGNEXT: { CapturingWalking(); } break; case STATE_SEAATTACKING_GOTOHARBOR: // geht von seinem Heimatmilitärgebäude zum Starthafen { // Gucken, ob der Abflughafen auch noch steht und sich in unserer Hand befindet bool valid_harbor = true; noBase* hb = gwg->GetNO(harborPos); if(hb->GetGOT() != GOT_NOB_HARBORBUILDING) valid_harbor = false; else if(static_cast<nobHarborBuilding*>(hb)->GetPlayer() != player) valid_harbor = false; // Nicht mehr oder das angegriffene Gebäude kaputt? Dann müssen wir die ganze Aktion abbrechen if(!valid_harbor || !attacked_goal) { // Dann gehen wir halt wieder nach Hause ReturnHomeMissionAttacking(); return; } // Sind wir schon da? if(pos == harborPos) { // Uns zum Hafen hinzufügen state = STATE_SEAATTACKING_WAITINHARBOR; gwg->RemoveFigure(pos, this); gwg->GetSpecObj<nobHarborBuilding>(pos)->AddSeaAttacker(this); return; } // Erstmal Flagge ansteuern MapPoint harborFlagPos = gwg->GetNeighbour(harborPos, Direction::SOUTHEAST); // Wenn wir an der Flagge bereits sind, in den Hafen eintreten if(pos == harborFlagPos) StartWalking(Direction::NORTHWEST); else { // Weg zum Hafen suchen unsigned char dir = gwg->FindHumanPath(pos, harborFlagPos, MAX_ATTACKING_RUN_DISTANCE, false, nullptr); if(dir == 0xff) { // Kein Weg gefunden? Dann auch abbrechen! ReturnHomeMissionAttacking(); return; } // Und schön weiterlaufen StartWalking(Direction(dir)); } } break; case STATE_SEAATTACKING_WAITINHARBOR: // wartet im Hafen auf das ankommende Schiff { } break; case STATE_SEAATTACKING_ONSHIP: // befindet sich auf dem Schiff auf dem Weg zum Zielpunkt { // Auweia, das darf nicht passieren RTTR_Assert(false); } break; case STATE_SEAATTACKING_RETURNTOSHIP: // befindet sich an der Zielposition auf dem Weg zurück zum Schiff { HandleState_SeaAttack_ReturnToShip(); } 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; } } } }
void nobMilitary::Capture(const unsigned char new_owner) { RTTR_Assert(IsCaptured()); captured_not_built = true; mAutoTrain = false; mAutoTrainVirtual = false; // Goldmünzen in der Inventur vom alten Spieler abziehen und dem neuen hinzufügen gwg->GetPlayer(player).DecreaseInventoryWare(GD_COINS, coins); gwg->GetPlayer(new_owner).IncreaseInventoryWare(GD_COINS, coins); // Soldaten, die auf Mission sind, Bescheid sagen for(std::list<nofActiveSoldier*>::iterator it = troops_on_mission.begin(); it != troops_on_mission.end(); ++it) (*it)->HomeDestroyed(); // Bestellungen die hierher unterwegs sind canceln CancelOrders(); // Aggressiv-Verteidigenden Soldaten Bescheid sagen, dass sie nach Hause gehen können for(std::list<nofAggressiveDefender*>::iterator it = aggressive_defenders.begin(); it != aggressive_defenders.end(); ++it) (*it)->AttackedGoalDestroyed(); troops_on_mission.clear(); aggressive_defenders.clear(); // In der Wirtschaftsverwaltung dieses Gebäude jetzt zum neuen Spieler zählen und beim alten raushauen gwg->GetPlayer(player).RemoveMilitaryBuilding(this); gwg->GetPlayer(new_owner).AddMilitaryBuilding(this); // Alten Besitzer merken unsigned char old_player = player; // neuer Spieler player = new_owner; // Flagge davor auch übernehmen GetFlag()->Capture(new_owner); // Territorium neu berechnen gwg->RecalcTerritory(*this, false, false); // Sichtbarkeiten berechnen für alten Spieler gwg->RecalcVisibilitiesAroundPoint(pos, GetMilitaryRadius() + VISUALRANGE_MILITARY + 1, old_player, NULL); // Grenzflagge entsprechend neu setzen von den Feinden LookForEnemyBuildings(); // und von den Verbündeten (da ja ein Feindgebäude weg ist)! sortedMilitaryBlds buildings = gwg->LookForMilitaryBuildings(pos, 4); for(sortedMilitaryBlds::iterator it = buildings.begin(); it != buildings.end(); ++it) { // verbündetes Gebäude? if(gwg->GetPlayer((*it)->GetPlayer()).IsPlayerAttackable(old_player) && (*it)->GetBuildingType() >= BLD_BARRACKS && (*it)->GetBuildingType() <= BLD_FORTRESS) // Grenzflaggen von dem neu berechnen static_cast<nobMilitary*>(*it)->LookForEnemyBuildings(); } // ehemalige Leute dieses Gebäudes nach Hause schicken, die ggf. grad auf dem Weg rein/raus waren MapPoint coords[2] = {pos, MapPoint(gwg->GetNeighbour(pos, 4))}; for(unsigned short i = 0; i < 2; ++i) { const std::list<noBase*>& figures = gwg->GetFigures(coords[i]); for(std::list<noBase*>::const_iterator it = figures.begin(); it != figures.end(); ++it) { if((*it)->GetType() == NOP_FIGURE) { if(static_cast<noFigure*>(*it)->GetCurrentRoad() == routes[4] && static_cast<noFigure*>(*it)->GetPlayer() != new_owner) { static_cast<noFigure*>(*it)->Abrogate(); static_cast<noFigure*>(*it)->StartWandering(); } } } } // Send all allied aggressors home (we own the building now!) for(std::list<nofAttacker*>::iterator it = aggressors.begin(); it != aggressors.end();) { nofAttacker* attacker = *it; // dont remove attackers owned by players not allied with the new owner! unsigned char attPlayer = attacker->GetPlayer(); if(attPlayer != player && !gwg->GetPlayer(attPlayer).IsPlayerAttackable(player)) { it = aggressors.erase(it); attacker->CapturedBuildingFull(); }else ++it; } // Fanfarensound abspieln, falls das Militärgebäude im Sichtbereich ist und unseres ist gwg->MilitaryBuildingCaptured(pos, player); // Post verschicken, an den alten Besitzer und an den neuen Besitzer SendPostMessage(old_player, new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("Military building lost"), PMC_MILITARY, *this)); SendPostMessage(player, new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("Military building captured"), PMC_MILITARY, *this)); // ggf. Fenster schließen vom alten Spieler gwg->ImportantObjectDestroyed(pos); gwg->GetNotifications().publish(BuildingNote(BuildingNote::Captured, player, pos, type_)); gwg->GetNotifications().publish(BuildingNote(BuildingNote::Lost, old_player, pos, type_)); }