void nofBuildingWorker::WorkingReady() { // wir arbeiten nicht mehr workplace->is_working = false; // Trage ich eine Ware? if(ware != GD_NOTHING) { noFlag* flag = workplace->GetFlag(); // Ist noch Platz an der Fahne? if(flag->GetNumWares() < 8) { // Ware erzeugen auto* real_ware = new Ware(ware, nullptr, flag); // Inventur entsprechend erhöhen, dabei Schilder unterscheiden! GoodType ware_type = ConvertShields(real_ware->type); gwg->GetPlayer(player).IncreaseInventoryWare(ware_type, 1); // Abnehmer für Ware finden real_ware->SetGoal(gwg->GetPlayer(player).FindClientForWare(real_ware)); // Ware soll ihren weiteren Weg berechnen real_ware->RecalcRoute(); // Ware ablegen flag->AddWare(real_ware); real_ware->WaitAtFlag(flag); // Warenstatistik erhöhen gwg->GetPlayer(this->player).IncreaseMerchandiseStatistic(ware); // Tragen nun keine Ware mehr ware = GD_NOTHING; } } // Wieder reingehen StartWalking(Direction::NORTHWEST); state = STATE_ENTERBUILDING; }
/// A ware changed its route and doesn't want to use the ship anymore void nobHarborBuilding::WareDontWantToTravelByShip(Ware * ware) { // Maybe this building is already destroyed if(gwg->GetGOT(x,y) != GOT_NOB_HARBORBUILDING) return; // Ware aus unserer Liste streichen wares_for_ships.remove(ware); // Will die Ware jetzt vielleicht zu uns? if(ware->goal == this) { // Dann hier gleich einliefern AddWare(ware); // and dont forget to reduce our visual count - addware will increase both and the ware waiting for a ship added to the visual count! --goods.goods[ConvertShields(ware->type)]; } // Oder will sie wieder raus? else { waiting_wares.push_back(ware); AddLeavingEvent(); } }
/// Storniert die Bestellung für eine bestimmte Ware, die mit einem Schiff transportiert werden soll void nobHarborBuilding::CancelWareForShip(Ware* ware) { // Ware aus der Liste entfernen wares_for_ships.remove(ware); // Ware zur Inventur hinzufügen // Anzahl davon wieder hochsetzen ++real_goods.goods[ConvertShields(ware->type)]; }
void nobBaseWarehouse::CancelWare(Ware* ware) { // Ware aus den Waiting-Wares entfernen RTTR_Assert(helpers::contains(waiting_wares, ware)); waiting_wares.remove(ware); // Anzahl davon wieder hochsetzen inventory.real.Add(ConvertShields(ware->type)); }
/// Fügt eine Ware hinzu, die mit dem Schiff verschickt werden soll void nobHarborBuilding::AddWareForShip(Ware * ware) { wares_for_ships.push_back(ware); // Anzahl visuell erhöhen ++goods.goods[ConvertShields(ware->type)]; ware->WaitForShip(this); OrderShip(); }
/// Storniert die Bestellung für eine bestimmte Ware, die mit einem Schiff transportiert werden soll void nobHarborBuilding::CancelWareForShip(Ware* ware) { // Ware aus der Liste entfernen RTTR_Assert(helpers::contains(wares_for_ships, ware)); wares_for_ships.remove(ware); // Ware zur Inventur hinzufügen // Anzahl davon wieder hochsetzen inventory.real.Add(ConvertShields(ware->type)); }
void nobBaseWarehouse::AddWaitingWare(Ware*& ware) { waiting_wares.push_back(ware); ware->WaitInWarehouse(this); // Wenn gerade keiner rausgeht, muss neues Event angemeldet werden AddLeavingEvent(); // Die visuelle Warenanzahl wieder erhöhen inventory.visual.Add(ConvertShields(ware->type)); ware = NULL; // Take ownership }
/// Fügt eine Ware hinzu, die mit dem Schiff verschickt werden soll void nobHarborBuilding::AddWareForShip(Ware*& ware) { wares_for_ships.push_back(ware); // Anzahl visuell erhöhen inventory.visual.Add(ConvertShields(ware->type)); ware->WaitForShip(this); OrderShip(); // Take ownership ware = NULL; }
iwTrade::iwTrade(const nobBaseWarehouse& wh, const GameWorldViewer& gwv, GameCommandFactory& gcFactory) : IngameWindow(wh.CreateGUIID(), (unsigned short) - 2, (unsigned short) - 2, 400, 194, _("Trade"), LOADER.GetImageN("resource", 41)), wh(wh), gwv(gwv), gcFactory(gcFactory), possibleSrcWarehouses(gwv.GetPlayer().GetWarehousesForTrading(wh)) { // Get title of the player SetTitle(_("Trade with %s") + gwv.GetWorld().GetPlayer(wh.GetPlayer()).name); // Gebäudebild und dessen Schatten AddImage( 0, 100, 144, LOADER.GetNationImage(wh.GetNation(), 250 + 5 * wh.GetBuildingType())); const unsigned left_column = 200; this->AddComboBox(4, left_column, 84, 160, 18, TC_GREY, NormalFont, 90); // Ware/Figure names this->AddText(1, left_column, 30, "Deal in:", COLOR_YELLOW, glArchivItem_Font::DF_LEFT, NormalFont); ctrlComboBox* box = this->AddComboBox(2, left_column, 44, 160, 18, TC_GREY, NormalFont, 200); // Ware or figure? box->AddString(_("Wares")); box->AddString(_("Settlers")); this->AddText(3, left_column, 70, "Type:", COLOR_YELLOW, glArchivItem_Font::DF_LEFT, NormalFont); // Create possible wares, figures for(unsigned i = 0; i < WARE_TYPES_COUNT; ++i) { // Only add one shield type if(GoodType(i) != ConvertShields(GoodType(i))) continue; // Don't add nothing or empty water if(i == GD_NOTHING || i == GD_WATEREMPTY) continue; wares.push_back(GoodType(i)); } for(unsigned i = 0; i < JOB_TYPES_COUNT; ++i) { // Can't trade boat carriers if(i == JOB_BOATCARRIER) continue; jobs.push_back(Job(i)); } AddImage(5, left_column + 20, 130, NULL, _("Ware you like to trade")); AddEdit(6, left_column + 34, 120, 39 , 20, TC_GREY, NormalFont)->SetNumberOnly(true); AddText(7, left_column + 75, 125, "/ 20", COLOR_YELLOW, glArchivItem_Font::DF_LEFT, NormalFont); AddTextButton(8, left_column, 150, 150, 22, TC_GREEN2, _("Send"), NormalFont); // Choose wares at first box->SetSelection(0); Msg_ComboSelectItem(2, 0); }
iwTrade::iwTrade(const nobBaseWarehouse& wh, const GameWorldViewer& gwv, GameCommandFactory& gcFactory) : IngameWindow(wh.CreateGUIID(), IngameWindow::posAtMouse, Extent(400, 194), _("Trade"), LOADER.GetImageN("resource", 41)), wh(wh), gwv(gwv), gcFactory(gcFactory), possibleSrcWarehouses(gwv.GetPlayer().GetWarehousesForTrading(wh)) { // Get title of the player SetTitle((boost::format(_("Trade with %s")) % gwv.GetWorld().GetPlayer(wh.GetPlayer()).name).str()); // Gebäudebild und dessen Schatten AddImage(0, DrawPoint(100, 144), LOADER.GetNationImage(wh.GetNation(), 250 + 5 * wh.GetBuildingType())); const unsigned left_column = 200; AddComboBox(4, DrawPoint(left_column, 84), Extent(160, 18), TC_GREY, NormalFont, 90); // Ware/Figure names AddText(1, DrawPoint(left_column, 30), "Deal in:", COLOR_YELLOW, FontStyle::LEFT, NormalFont); ctrlComboBox* box = this->AddComboBox(2, DrawPoint(left_column, 44), Extent(160, 18), TC_GREY, NormalFont, 200); // Ware or figure? box->AddString(_("Wares")); box->AddString(_("Settlers")); AddText(3, DrawPoint(left_column, 70), "Type:", COLOR_YELLOW, FontStyle::LEFT, NormalFont); // Create possible wares, figures for(unsigned i = 0; i < NUM_WARE_TYPES; ++i) { // Only add one shield type if(GoodType(i) != ConvertShields(GoodType(i))) continue; // Don't add empty water if(i == GD_WATEREMPTY) continue; wares.push_back(GoodType(i)); } for(unsigned i = 0; i < NUM_JOB_TYPES; ++i) { // Can't trade boat carriers if(i == JOB_BOATCARRIER) continue; jobs.push_back(Job(i)); } AddImage(5, DrawPoint(left_column + 20, 130), static_cast<ITexture*>(nullptr), _("Ware you like to trade")); AddEdit(6, DrawPoint(left_column + 34, 120), Extent(39, 20), TC_GREY, NormalFont)->SetNumberOnly(true); AddText(7, DrawPoint(left_column + 75, 125), "/ 20", COLOR_YELLOW, FontStyle::LEFT, NormalFont); AddTextButton(8, DrawPoint(left_column, 150), Extent(150, 22), TC_GREEN2, _("Send"), NormalFont); // Choose wares at first box->SetSelection(0); Msg_ComboSelectItem(2, 0); }
void nobBaseWarehouse::AddWare(Ware*& ware) { // Ware not dependent anymore (only if we had a goal) if(ware->GetGoal()) { RTTR_Assert(ware->GetGoal() == this); // The goal should be here RemoveDependentWare(ware); } else RTTR_Assert(!IsWareDependent(ware)); // Die Schilde der verschiedenen Nation in eine "Schild-Sorte" (den der Römer) umwandeln! GoodType type = ConvertShields(ware->type); gwg->GetPlayer(player).RemoveWare(ware); deletePtr(ware); inventory.Add(type); CheckUsesForNewWare(type); }
/// Schiff ist angekommen void nobHarborBuilding::ShipArrived(noShip * ship) { // Verfügbare Aufgaben abklappern // Steht Expedition zum Start bereit? if(expedition.active && expedition.builder && expedition.boards == BUILDING_COSTS[nation][BLD_HARBORBUILDING].boards && expedition.stones == BUILDING_COSTS[nation][BLD_HARBORBUILDING].stones) { // Aufräumen am Hafen expedition.active = false; // Expedition starten ship->StartExpedition(); } // Oder auch eine Erkundungs-Expedition else if(IsExplorationExpeditionReady()) { // Aufräumen am Hafen exploration_expedition.active = false; // Expedition starten ship->StartExplorationExpedition(); assert(goods.people[JOB_SCOUT] >= exploration_expedition.scouts); goods.people[JOB_SCOUT] -= exploration_expedition.scouts; } // Gibt es Waren oder Figuren, die ein Schiff von hier aus nutzen wollen? else if(wares_for_ships.size() || figures_for_ships.size()) { // Das Ziel wird nach der ersten Figur bzw. ersten Ware gewählt // actually since the wares might not yet have informed the harbor that their target harbor was destroyed we pick the first figure/ware with a valid target instead Point<MapCoord> dest; bool gotdest=false; for(std::list<FigureForShip>::iterator it=figures_for_ships.begin();it!=figures_for_ships.end();it++) { noBase * nb = gwg->GetNO(it->dest.x,it->dest.y); if(nb->GetGOT() == GOT_NOB_HARBORBUILDING) { dest=it->dest; gotdest=true; break; } } for(std::list<Ware*>::iterator it=wares_for_ships.begin();!gotdest&&it!=wares_for_ships.end();it++) { noBase * nb = gwg->GetNO((*it)->GetNextHarbor().x,(*it)->GetNextHarbor().y); if(nb->GetGOT() == GOT_NOB_HARBORBUILDING) { dest=(*it)->GetNextHarbor(); gotdest=true; break; } } if(gotdest) { std::list<noFigure*> figures; // Figuren auswählen, die zu diesem Ziel wollen for(std::list<FigureForShip>::iterator it = figures_for_ships.begin(); it!=figures_for_ships.end() && figures.size() < SHIP_CAPACITY[players->getElement(player)->nation];) { if(it->dest == dest) { figures.push_back(it->fig); it->fig->StartShipJourney(dest); --goods.people[it->fig->GetJobType()]; it = figures_for_ships.erase(it); } else ++it; } // Und noch die Waren auswählen std::list<Ware*> wares; for(std::list<Ware*>::iterator it = wares_for_ships.begin(); it!=wares_for_ships.end() && figures.size()+wares.size() < SHIP_CAPACITY[players->getElement(player)->nation];) { if((*it)->GetNextHarbor() == dest) { wares.push_back(*it); (*it)->StartShipJourney(); --goods.goods[ConvertShields((*it)->type)]; it = wares_for_ships.erase(it); } else ++it; } // Und das Schiff starten lassen ship->PrepareTransport(dest,figures,wares); }// Oder vielleicht Schiffs-Angreifer? (copy paste of the last part) else if(soldiers_for_ships.size()) { // Ein Ziel (das des ersten Soldaten in der Liste) auswählen und alle übrigen // Soldaten mit dem gleichen Ziel mit auf das Schiff laden std::list<noFigure*> attackers; Point<MapCoord> ship_dest = soldiers_for_ships.begin()->dest; for(std::list<SoldierForShip>::iterator it = soldiers_for_ships.begin();it!=soldiers_for_ships.end();) { if(it->dest == ship_dest) { --goods.people[it->attacker->GetJobType()]; attackers.push_back(it->attacker); it = soldiers_for_ships.erase(it); } else ++it; } ship->PrepareSeaAttack(ship_dest,attackers); } } // Oder vielleicht Schiffs-Angreifer? else if(soldiers_for_ships.size()) { // Ein Ziel (das des ersten Soldaten in der Liste) auswählen und alle übrigen // Soldaten mit dem gleichen Ziel mit auf das Schiff laden std::list<noFigure*> attackers; Point<MapCoord> ship_dest = soldiers_for_ships.begin()->dest; for(std::list<SoldierForShip>::iterator it = soldiers_for_ships.begin();it!=soldiers_for_ships.end();) { if(it->dest == ship_dest) { --goods.people[it->attacker->GetJobType()]; attackers.push_back(it->attacker); it = soldiers_for_ships.erase(it); } else ++it; } ship->PrepareSeaAttack(ship_dest,attackers); } }
/// Erhält die Waren von einem Schiff und nimmt diese in den Warenbestand auf void nobHarborBuilding::ReceiveGoodsFromShip(const std::list<noFigure*> figures, const std::list<Ware*> wares) { // Menschen zur Ausgehliste hinzufügen for(std::list<noFigure*>::const_iterator it = figures.begin();it!=figures.end();++it) { if((*it)->GetJobType() == JOB_BOATCARRIER) { ++goods.people[JOB_HELPER]; ++goods.goods[GD_BOAT]; } else ++goods.people[(*it)->GetJobType()]; // Wenn es kein Ziel mehr hat, sprich keinen weiteren Weg, kann es direkt hier gelagert // werden if ((*it)->HasNoGoal() || ((*it)->GetGoal() == this)) { AddFigure(*it, false); } else { Point<MapCoord> next_harbor = (*it)->ExamineRouteBeforeShipping(); unsigned char next_dir = (*it)->GetDir(); if (next_dir == 4) { AddLeavingFigure(*it); (*it)->ShipJourneyEnded(); } else if (next_dir == SHIP_DIR) { AddFigureForShip(*it, next_harbor); } else { AddFigure(*it, false); } } } // Waren zur Warteliste hinzufügen for(std::list<Ware*>::const_iterator it = wares.begin();it!=wares.end();++it) { // Optische Warenwerte entsprechend erhöhen ++goods.goods[ConvertShields((*it)->type)]; if((*it)->ShipJorneyEnded(this)) { // Ware will die weitere Reise antreten, also muss sie zur Liste der rausgetragenen Waren // hinzugefügt werden waiting_wares.push_back(*it); } else { // Ansonsten fügen wir die Ware einfach zu unserem Inventar dazu RemoveDependentWare(*it); ++real_goods.goods[ConvertShields((*it)->type)]; players->getElement(player)->RemoveWare(*it); delete *it; } } // Ggf. neues Rausgeh-Event anmelden, was notwendig ist, wenn z.B. nur Waren zur Liste hinzugefügt wurden AddLeavingEvent(); }
void nobBaseWarehouse::HandleLeaveEvent() { #if RTTR_ENABLE_ASSERTS // Harbors have more queues. Ignore for now if(GetGOT() != GOT_NOB_HARBORBUILDING) { Inventory should = inventory.real; for(std::list<noFigure*>::iterator it = leave_house.begin(); it != leave_house.end(); ++it) { // Don't count warehouse workers if(!(*it)->MemberOfWarehouse()){ if((*it)->GetJobType() == JOB_BOATCARRIER) should.Add(JOB_HELPER); else should.Add((*it)->GetJobType()); } } for(unsigned i = 0; i < JOB_TYPES_COUNT; i++) RTTR_Assert(should.people[i] == inventory.visual.people[i]); } #endif // Falls eine Bestellung storniert wurde if(leave_house.empty() && waiting_wares.empty()) { go_out = false; return; } // Fight or something in front of the house and we are not defending? if(!gwg->IsRoadNodeForFigures(gwg->GetNeighbour(pos, 4), 4)) { // there's a fight bool found = false; // try to find a defender and make him leave the house first for(std::list<noFigure*>::iterator it = leave_house.begin(); it != leave_house.end(); ++it) { if(((*it)->GetGOT() == GOT_NOF_AGGRESSIVEDEFENDER) || ((*it)->GetGOT() == GOT_NOF_DEFENDER)) { // remove defender from list, insert him again in front of all others leave_house.push_front(*it); leave_house.erase(it); found = true; break; } } // no defender found? trigger next leaving event :) if(!found) { go_out = false; AddLeavingEvent(); return; } } // Figuren kommen zuerst raus if(!leave_house.empty()) { noFigure* fig = leave_house.front(); gwg->AddFigure(fig, pos); // Init road walking for figures walking on roads if(fig->IsWalkingOnRoad()) fig->InitializeRoadWalking(routes[4], 0, true); fig->ActAtFirst(); // Bei Lagerhausarbeitern das nicht abziehen! if(!fig->MemberOfWarehouse()) { // War das ein Boot-Träger? if(fig->GetJobType() == JOB_BOATCARRIER) { // Remove helper and boat separately inventory.visual.Remove(JOB_HELPER); inventory.visual.Remove(GD_BOAT); } else inventory.visual.Remove(fig->GetJobType()); if(fig->GetGOT() == GOT_NOF_TRADEDONKEY) { // Trade donkey carrying wares? GoodType carriedWare = static_cast<nofTradeDonkey*>(fig)->GetCarriedWare(); if(carriedWare != GD_NOTHING) inventory.visual.Remove(carriedWare); } } leave_house.pop_front(); } else { // Ist noch Platz an der Flagge? if(GetFlag()->GetWareCount() < 8) { // Dann Ware raustragen lassen Ware* ware = waiting_wares.front(); nofWarehouseWorker* worker = new nofWarehouseWorker(pos, player, ware, 0); gwg->AddFigure(worker, pos); inventory.visual.Remove(ConvertShields(ware->type)); worker->WalkToGoal(); ware->Carry(GetFlag()); waiting_wares.pop_front(); } else { // Kein Platz mehr für Waren --> keiner brauch mehr rauszukommen, und Figuren gibts ja auch keine mehr go_out = false; } } // Wenn keine Figuren und Waren mehr da sind (bzw die Flagge vorm Haus voll ist), brauch auch keiner mehr rauszukommen if(leave_house.empty() && waiting_wares.empty()) go_out = false; if(go_out) leaving_event = em->AddEvent(this, LEAVE_INTERVAL + RANDOM.Rand(__FILE__, __LINE__, GetObjId(), LEAVE_INTERVAL_RAND)); }
InventorySetting nobBaseWarehouse::GetInventorySetting(const GoodType ware) const { return inventorySettings.wares[ConvertShields(ware)]; }
/// Schiff ist angekommen void nobHarborBuilding::ShipArrived(noShip* ship) { // get a new job - priority is given according to this list: attack,expedition,exploration,transport // any attackers ready? if(!soldiers_for_ships.empty()) { // load all soldiers that share the same target as the first soldier in the list std::list<noFigure*> attackers; MapPoint ship_dest = soldiers_for_ships.begin()->dest; for(std::list<SoldierForShip>::iterator it = soldiers_for_ships.begin(); it != soldiers_for_ships.end();) { if(it->dest == ship_dest) { inventory.visual.Remove(it->attacker->GetJobType()); attackers.push_back(it->attacker); it = soldiers_for_ships.erase(it); } else ++it; } ship->PrepareSeaAttack(GetHarborPosID(), ship_dest, attackers); return; } //Expedition ready? if(expedition.active && expedition.builder && expedition.boards == BUILDING_COSTS[nation][BLD_HARBORBUILDING].boards && expedition.stones == BUILDING_COSTS[nation][BLD_HARBORBUILDING].stones) { // Aufräumen am Hafen expedition.active = false; // Expedition starten ship->StartExpedition(GetHarborPosID()); return; } // Exploration-Expedition ready? if(IsExplorationExpeditionReady()) { // Aufräumen am Hafen exploration_expedition.active = false; // Expedition starten ship->StartExplorationExpedition(GetHarborPosID()); inventory.visual.Remove(JOB_SCOUT, exploration_expedition.scouts); return; } // Gibt es Waren oder Figuren, die ein Schiff von hier aus nutzen wollen? if(!wares_for_ships.empty() || !figures_for_ships.empty()) { // Das Ziel wird nach der ersten Figur bzw. ersten Ware gewählt // actually since the wares might not yet have informed the harbor that their target harbor was destroyed we pick the first figure/ware with a valid target instead MapPoint dest; bool gotdest = false; for(std::list<FigureForShip>::iterator it = figures_for_ships.begin(); it != figures_for_ships.end(); ++it) { noBase* nb = gwg->GetNO(it->dest); if(nb->GetGOT() == GOT_NOB_HARBORBUILDING && gwg->GetNode(it->dest).owner == player + 1) //target is a harbor and owned by the same player { dest = it->dest; gotdest = true; break; } } for(std::list<Ware*>::iterator it = wares_for_ships.begin(); !gotdest && it != wares_for_ships.end(); ++it) { noBase* nb = gwg->GetNO((*it)->GetNextHarbor()); if(nb->GetGOT() == GOT_NOB_HARBORBUILDING && gwg->GetNode((*it)->GetNextHarbor()).owner == player + 1) { dest = (*it)->GetNextHarbor(); gotdest = true; break; } } if(gotdest) { std::list<noFigure*> figures; // Figuren auswählen, die zu diesem Ziel wollen for(std::list<FigureForShip>::iterator it = figures_for_ships.begin(); it != figures_for_ships.end() && figures.size() < SHIP_CAPACITY;) { if(it->dest == dest) { figures.push_back(it->fig); it->fig->StartShipJourney(); inventory.visual.Remove(it->fig->GetJobType()); it = figures_for_ships.erase(it); } else ++it; } // Und noch die Waren auswählen std::list<Ware*> wares; for(std::list<Ware*>::iterator it = wares_for_ships.begin(); it != wares_for_ships.end() && figures.size() + wares.size() < SHIP_CAPACITY;) { if((*it)->GetNextHarbor() == dest) { wares.push_back(*it); (*it)->StartShipJourney(); inventory.visual.Remove(ConvertShields((*it)->type)); it = wares_for_ships.erase(it); } else ++it; } // Und das Schiff starten lassen ship->PrepareTransport(GetHarborPosID(), dest, figures, wares); } } }