widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #17121
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
Benedikt Straub has proposed merging lp:~widelands-dev/widelands/constructionsite_options into lp:widelands.
Commit message:
Allow players to define settings for and to enhance buildings under construction
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #1597310 in widelands: "Possibility to set building options when building is under construction"
https://bugs.launchpad.net/widelands/+bug/1597310
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/constructionsite_options/+merge/367428
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/constructionsite_options into lp:widelands.
=== modified file 'src/ai/defaultai_seafaring.cc'
--- src/ai/defaultai_seafaring.cc 2019-02-23 11:00:49 +0000
+++ src/ai/defaultai_seafaring.cc 2019-05-14 17:38:23 +0000
@@ -346,7 +346,7 @@
if (site->bo->is(BuildingAttribute::kShipyard)) {
for (uint32_t k = 0; k < site->bo->inputs.size(); ++k) {
game().send_player_set_ware_priority(
- *site->site, wwWARE, site->bo->inputs.at(k), HIGH_PRIORITY);
+ *site->site, wwWARE, site->bo->inputs.at(k), kPriorityHigh);
}
}
}
=== modified file 'src/economy/economy.cc'
--- src/economy/economy.cc 2019-04-09 16:43:49 +0000
+++ src/economy/economy.cc 2019-05-14 17:38:23 +0000
@@ -971,7 +971,7 @@
static bool accept_warehouse_if_policy(Warehouse& wh,
WareWorker type,
DescriptionIndex ware,
- Warehouse::StockPolicy policy) {
+ StockPolicy policy) {
return wh.get_stock_policy(type, ware) == policy;
}
@@ -1005,8 +1005,8 @@
for (uint32_t nwh = 0; nwh < warehouses_.size(); ++nwh) {
Warehouse* wh = warehouses_[nwh];
- Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware);
- if (policy == Warehouse::StockPolicy::kPrefer) {
+ StockPolicy policy = wh->get_stock_policy(type, ware);
+ if (policy == StockPolicy::kPrefer) {
haveprefer = true;
// Getting count of worker/ware
@@ -1022,7 +1022,7 @@
preferred_wh_stock = current_stock;
}
}
- if (policy == Warehouse::StockPolicy::kNormal)
+ if (policy == StockPolicy::kNormal)
havenormal = true;
}
if (!havenormal && !haveprefer && type == wwWARE)
@@ -1037,7 +1037,7 @@
(!havenormal) ?
WarehouseAcceptFn() :
boost::bind(&accept_warehouse_if_policy, _1, type, ware,
- Warehouse::StockPolicy::kNormal));
+ StockPolicy::kNormal));
}
if (!wh) {
log("Warning: Economy::handle_active_supplies "
=== modified file 'src/economy/request.cc'
--- src/economy/request.cc 2019-02-23 11:00:49 +0000
+++ src/economy/request.cc 2019-05-14 17:38:23 +0000
@@ -262,7 +262,7 @@
int32_t Request::get_priority(int32_t cost) const {
int MAX_IDLE_PRIORITY = 100;
bool is_construction_site = false;
- int32_t modifier = DEFAULT_PRIORITY;
+ int32_t modifier = kPriorityNormal;
if (target_building_) {
modifier = target_building_->get_priority(get_type(), get_index());
=== modified file 'src/logic/editor_game_base.cc'
--- src/logic/editor_game_base.cc 2019-04-26 05:52:49 +0000
+++ src/logic/editor_game_base.cc 2019-05-14 17:38:23 +0000
@@ -38,6 +38,7 @@
#include "logic/map_objects/map_object.h"
#include "logic/map_objects/tribes/battle.h"
#include "logic/map_objects/tribes/building.h"
+#include "logic/map_objects/tribes/constructionsite.h"
#include "logic/map_objects/tribes/dismantlesite.h"
#include "logic/map_objects/tribes/tribe_descr.h"
#include "logic/map_objects/tribes/tribes.h"
@@ -349,10 +350,15 @@
PlayerNumber const owner,
DescriptionIndex idx,
bool loading,
- Building::FormerBuildings former_buildings) {
+ Building::FormerBuildings former_buildings,
+ const BuildingSettings* settings) {
Player* plr = get_player(owner);
const TribeDescr& tribe = plr->tribe();
- return tribe.get_building_descr(idx)->create(*this, plr, c, true, loading, former_buildings);
+ Building& b = tribe.get_building_descr(idx)->create(*this, plr, c, true, loading, former_buildings);
+ if (settings) {
+ dynamic_cast<ConstructionSite&>(b).apply_settings(*settings);
+ }
+ return b;
}
/**
=== modified file 'src/logic/editor_game_base.h'
--- src/logic/editor_game_base.h 2019-02-27 19:00:36 +0000
+++ src/logic/editor_game_base.h 2019-05-14 17:38:23 +0000
@@ -56,6 +56,7 @@
class TribeDescr;
struct Flag;
struct AttackController;
+struct BuildingSettings;
struct NoteFieldPossession {
CAN_BE_SENT_AS_NOTE(NoteId::FieldPossession)
@@ -130,7 +131,8 @@
PlayerNumber,
DescriptionIndex,
bool loading = false,
- Building::FormerBuildings former_buildings = Building::FormerBuildings());
+ Building::FormerBuildings former_buildings = Building::FormerBuildings(),
+ const BuildingSettings* settings = nullptr);
Building&
warp_dismantlesite(const Coords&,
PlayerNumber,
=== modified file 'src/logic/game.cc'
--- src/logic/game.cc 2019-05-11 18:19:20 +0000
+++ src/logic/game.cc 2019-05-14 17:38:23 +0000
@@ -56,6 +56,7 @@
#include "logic/map_objects/tribes/soldier.h"
#include "logic/map_objects/tribes/trainingsite.h"
#include "logic/map_objects/tribes/tribe_descr.h"
+#include "logic/map_objects/tribes/warehouse.h"
#include "logic/player.h"
#include "logic/playercommand.h"
#include "logic/replay.h"
@@ -859,6 +860,47 @@
*new CmdProposeTrade(get_gametime(), object->get_owner()->player_number(), trade));
}
+void Game::send_player_constructionsite_soldier_capacity(ConstructionSite& cs, uint32_t c) {
+ send_player_command(*new CmdConstructionsiteSoldierCapacity(
+ get_gametime(), cs.get_owner()->player_number(), cs, c));
+}
+
+void Game::send_player_constructionsite_prefer_heroes(ConstructionSite& cs, bool h) {
+ send_player_command(*new CmdConstructionsitePreferHeroes(
+ get_gametime(), cs.get_owner()->player_number(), cs, h));
+}
+
+void Game::send_player_constructionsite_launch_expedition(ConstructionSite& cs, bool l) {
+ send_player_command(*new CmdConstructionsiteLaunchExpedition(
+ get_gametime(), cs.get_owner()->player_number(), cs, l));
+}
+
+void Game::send_player_constructionsite_stock_policy(
+ ConstructionSite& cs, WareWorker ww, DescriptionIndex di, StockPolicy pol) {
+ send_player_command(*new CmdConstructionsiteStockPolicy(
+ get_gametime(), cs.get_owner()->player_number(), cs, ww, di, pol));
+}
+
+void Game::send_player_constructionsite_input_queue_priority(
+ ConstructionSite& cs, WareWorker ww, DescriptionIndex di, int32_t p) {
+ send_player_command(*new CmdConstructionsiteInputQueuePriority(
+ get_gametime(), cs.get_owner()->player_number(), cs, ww, di, p));
+}
+
+void Game::send_player_constructionsite_input_queue_max_fill(
+ ConstructionSite& cs, WareWorker ww, DescriptionIndex di, uint32_t max) {
+ send_player_command(*new CmdConstructionsiteInputQueueMaxFill(
+ get_gametime(), cs.get_owner()->player_number(), cs, ww, di, max));
+}
+
+void Game::send_player_constructionsite_enhance(ConstructionSite& cs) {
+ send_player_command(*new CmdConstructionsiteEnhance(get_gametime(), cs.get_owner()->player_number(), cs));
+}
+
+void Game::send_player_constructionsite_startstop(ConstructionSite& cs, bool stop) {
+ send_player_command(*new CmdConstructionsiteStartStop(get_gametime(), cs.get_owner()->player_number(), cs, stop));
+}
+
int Game::propose_trade(const Trade& trade) {
// TODO(sirver,trading): Check if a trade is possible (i.e. if there is a
// path between the two markets);
=== modified file 'src/logic/game.h'
--- src/logic/game.h 2019-05-07 12:14:02 +0000
+++ src/logic/game.h 2019-05-14 17:38:23 +0000
@@ -46,6 +46,7 @@
// See forester_cache_
constexpr int16_t kInvalidForesterEntry = -1;
+class ConstructionSite;
struct Flag;
struct Path;
struct PlayerImmovable;
@@ -56,6 +57,7 @@
struct PlayerEndStatus;
class TrainingSite;
class MilitarySite;
+enum class StockPolicy;
enum {
gs_notrunning = 0, // game is being prepared
@@ -282,6 +284,16 @@
void send_player_cancel_expedition_ship(Ship&);
void send_player_propose_trade(const Trade& trade);
+ void send_player_constructionsite_soldier_capacity(ConstructionSite&, uint32_t);
+ void send_player_constructionsite_prefer_heroes(ConstructionSite&, bool);
+ void send_player_constructionsite_launch_expedition(ConstructionSite&, bool);
+ void send_player_constructionsite_stock_policy(
+ ConstructionSite&, WareWorker, DescriptionIndex, StockPolicy);
+ void send_player_constructionsite_input_queue_priority(ConstructionSite&, WareWorker, DescriptionIndex, int32_t);
+ void send_player_constructionsite_input_queue_max_fill(ConstructionSite&, WareWorker, DescriptionIndex, uint32_t);
+ void send_player_constructionsite_enhance(ConstructionSite&);
+ void send_player_constructionsite_startstop(ConstructionSite&, bool);
+
InteractivePlayer* get_ipl();
SaveHandler& save_handler() {
=== modified file 'src/logic/map_objects/CMakeLists.txt'
--- src/logic/map_objects/CMakeLists.txt 2019-05-05 18:53:14 +0000
+++ src/logic/map_objects/CMakeLists.txt 2019-05-14 17:38:23 +0000
@@ -49,6 +49,8 @@
tribes/bill_of_materials.h
tribes/building.cc
tribes/building.h
+ tribes/building_settings.cc
+ tribes/building_settings.h
tribes/carrier.cc
tribes/carrier.h
tribes/constructionsite.cc
=== modified file 'src/logic/map_objects/tribes/building.cc'
--- src/logic/map_objects/tribes/building.cc 2019-05-05 14:05:07 +0000
+++ src/logic/map_objects/tribes/building.cc 2019-05-14 17:38:23 +0000
@@ -638,13 +638,13 @@
int32_t
Building::get_priority(WareWorker type, DescriptionIndex const ware_index, bool adjust) const {
- int32_t priority = DEFAULT_PRIORITY;
+ int32_t priority = kPriorityNormal;
if (type == wwWARE) {
// if priority is defined for specific ware,
// combine base priority and ware priority
std::map<DescriptionIndex, int32_t>::const_iterator it = ware_priorities_.find(ware_index);
if (it != ware_priorities_.end())
- priority = adjust ? (priority * it->second / DEFAULT_PRIORITY) : it->second;
+ priority = adjust ? (priority * it->second / kPriorityNormal) : it->second;
}
return priority;
@@ -660,7 +660,7 @@
std::map<DescriptionIndex, int32_t>& ware_priorities = p[wwWARE];
std::map<DescriptionIndex, int32_t>::const_iterator it;
for (it = ware_priorities_.begin(); it != ware_priorities_.end(); ++it) {
- if (it->second == DEFAULT_PRIORITY)
+ if (it->second == kPriorityNormal)
continue;
ware_priorities[it->first] = it->second;
}
=== modified file 'src/logic/map_objects/tribes/building.h'
--- src/logic/map_objects/tribes/building.h 2019-05-11 12:37:45 +0000
+++ src/logic/map_objects/tribes/building.h 2019-05-14 17:38:23 +0000
@@ -31,6 +31,7 @@
#include "logic/map_objects/buildcost.h"
#include "logic/map_objects/immovable.h"
#include "logic/map_objects/tribes/attack_target.h"
+#include "logic/map_objects/tribes/building_settings.h"
#include "logic/map_objects/tribes/bill_of_materials.h"
#include "logic/map_objects/tribes/soldiercontrol.h"
#include "logic/map_objects/tribes/wareworker.h"
@@ -51,9 +52,9 @@
class Building;
-#define LOW_PRIORITY 2
-#define DEFAULT_PRIORITY 4
-#define HIGH_PRIORITY 8
+constexpr int32_t kPriorityLow = 2;
+constexpr int32_t kPriorityNormal = 4;
+constexpr int32_t kPriorityHigh = 8;
/*
* Common to all buildings!
@@ -266,8 +267,8 @@
// Get/Set the priority for this waretype for this building. 'type' defines
// if this is for a worker or a ware, 'index' is the type of worker or ware.
- // If 'adjust' is false, the three possible states HIGH_PRIORITY,
- // DEFAULT_PRIORITY and LOW_PRIORITY are returned, otherwise numerical
+ // If 'adjust' is false, the three possible states kPriorityHigh,
+ // kPriorityNormal and kPriorityLow are returned, otherwise numerical
// values adjusted to the preciousness of the ware in general are returned.
virtual int32_t get_priority(WareWorker type, DescriptionIndex, bool adjust = true) const;
void set_priority(int32_t type, DescriptionIndex ware_index, int32_t new_priority);
@@ -301,6 +302,10 @@
void add_worker(Worker&) override;
void remove_worker(Worker&) override;
+ virtual const BuildingSettings* create_building_settings() const {
+ return nullptr;
+ }
+
// AttackTarget object associated with this building. If the building can
// never be attacked (for example productionsites) this will be nullptr.
const AttackTarget* attack_target() const {
=== added file 'src/logic/map_objects/tribes/building_settings.cc'
--- src/logic/map_objects/tribes/building_settings.cc 1970-01-01 00:00:00 +0000
+++ src/logic/map_objects/tribes/building_settings.cc 2019-05-14 17:38:23 +0000
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2002-2019 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "logic/map_objects/tribes/building_settings.h"
+
+#include "io/fileread.h"
+#include "io/filewrite.h"
+#include "logic/game.h"
+#include "logic/game_data_error.h"
+#include "logic/map_objects/tribes/militarysite.h"
+#include "logic/map_objects/tribes/productionsite.h"
+#include "logic/map_objects/tribes/trainingsite.h"
+#include "logic/map_objects/tribes/tribe_descr.h"
+#include "logic/map_objects/tribes/warehouse.h"
+
+namespace Widelands {
+
+ProductionsiteSettings::ProductionsiteSettings(const ProductionSiteDescr& descr)
+ : BuildingSettings(descr.name()), stopped(false) {
+ for (WareRange i(descr.input_wares()); i; ++i) {
+ ware_queues.push_back(std::make_pair(i.current->first,
+ InputQueueSetting{i.current->second, i.current->second, kPriorityNormal}));
+ }
+ for (WareRange i(descr.input_workers()); i; ++i) {
+ worker_queues.push_back(std::make_pair(i.current->first,
+ InputQueueSetting{i.current->second, i.current->second, kPriorityNormal}));
+ }
+}
+
+MilitarysiteSettings::MilitarysiteSettings(const MilitarySiteDescr& descr)
+ : BuildingSettings(descr.name()),
+ max_capacity(descr.get_max_number_of_soldiers()),
+ desired_capacity(descr.get_max_number_of_soldiers()),
+ prefer_heroes(descr.prefers_heroes_at_start_) {
+}
+
+TrainingsiteSettings::TrainingsiteSettings(const TrainingSiteDescr& descr)
+ : ProductionsiteSettings(descr),
+ max_capacity(descr.get_max_number_of_soldiers()),
+ desired_capacity(descr.get_max_number_of_soldiers()) {
+}
+
+WarehouseSettings::WarehouseSettings(const WarehouseDescr& wh, const TribeDescr& tribe)
+ : BuildingSettings(wh.name()), launch_expedition_allowed(wh.get_isport()), launch_expedition(false) {
+ for (const DescriptionIndex di : tribe.wares()) {
+ ware_preferences.emplace(di, StockPolicy::kNormal);
+ }
+ for (const DescriptionIndex di : tribe.workers()) {
+ worker_preferences.emplace(di, StockPolicy::kNormal);
+ }
+ for (const DescriptionIndex di : tribe.worker_types_without_cost()) {
+ worker_preferences.erase(di);
+ }
+}
+
+void ProductionsiteSettings::apply(const BuildingSettings& bs) {
+ BuildingSettings::apply(bs);
+ if (upcast(const ProductionsiteSettings, s, &bs)) {
+ stopped = s->stopped;
+ for (auto& pair : ware_queues) {
+ for (const auto& other : s->ware_queues) {
+ if (pair.first == other.first) {
+ pair.second.priority = other.second.priority;
+ pair.second.desired_fill = std::min(pair.second.max_fill, other.second.desired_fill);
+ break;
+ }
+ }
+ }
+ for (auto& pair : worker_queues) {
+ for (const auto& other : s->worker_queues) {
+ if (pair.first == other.first) {
+ pair.second.priority = other.second.priority;
+ pair.second.desired_fill = std::min(pair.second.max_fill, other.second.desired_fill);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void TrainingsiteSettings::apply(const BuildingSettings& bs) {
+ ProductionsiteSettings::apply(bs);
+ if (upcast(const TrainingsiteSettings, s, &bs)) {
+ desired_capacity = std::min(max_capacity, s->desired_capacity);
+ }
+}
+
+void MilitarysiteSettings::apply(const BuildingSettings& bs) {
+ BuildingSettings::apply(bs);
+ if (upcast(const MilitarysiteSettings, s, &bs)) {
+ desired_capacity = std::min(max_capacity, s->desired_capacity);
+ prefer_heroes = s->prefer_heroes;
+ }
+}
+
+void WarehouseSettings::apply(const BuildingSettings& bs) {
+ BuildingSettings::apply(bs);
+ if (upcast(const WarehouseSettings, s, &bs)) {
+ for (auto& pair : ware_preferences) {
+ const auto it = s->ware_preferences.find(pair.first);
+ if (it != s->ware_preferences.end()) {
+ pair.second = it->second;
+ }
+ }
+ for (auto& pair : worker_preferences) {
+ const auto it = s->worker_preferences.find(pair.first);
+ if (it != s->worker_preferences.end()) {
+ pair.second = it->second;
+ }
+ }
+ launch_expedition = launch_expedition_allowed && s->launch_expedition;
+ }
+}
+
+// Saveloading
+
+constexpr uint8_t kCurrentPacketVersion = 1;
+constexpr uint8_t kCurrentPacketVersionMilitarysite = 1;
+constexpr uint8_t kCurrentPacketVersionProductionsite = 1;
+constexpr uint8_t kCurrentPacketVersionTrainingsite = 1;
+constexpr uint8_t kCurrentPacketVersionWarehouse = 1;
+
+enum class BuildingType : uint8_t {
+ kWarehouse = 1,
+ kProductionsite = 2,
+ kTrainingsite = 3,
+ kMilitarysite = 4,
+};
+
+// static
+BuildingSettings* BuildingSettings::load(const Game& game, const TribeDescr& tribe, FileRead& fr) {
+ try {
+ const uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersion) {
+ const std::string name(fr.c_string());
+ const DescriptionIndex index = game.tribes().building_index(name);
+ const BuildingType type = static_cast<BuildingType>(fr.unsigned_8());
+ BuildingSettings* result = nullptr;
+ switch (type) {
+ case BuildingType::kTrainingsite: {
+ result = new TrainingsiteSettings(*dynamic_cast<const TrainingSiteDescr*>(
+ game.tribes().get_building_descr(index)));
+ break;
+ }
+ case BuildingType::kProductionsite: {
+ result = new ProductionsiteSettings(*dynamic_cast<const ProductionSiteDescr*>(
+ game.tribes().get_building_descr(index)));
+ break;
+ }
+ case BuildingType::kMilitarysite: {
+ result = new MilitarysiteSettings(*dynamic_cast<const MilitarySiteDescr*>(
+ game.tribes().get_building_descr(index)));
+ break;
+ }
+ case BuildingType::kWarehouse: {
+ result = new WarehouseSettings(*dynamic_cast<const WarehouseDescr*>(
+ game.tribes().get_building_descr(index)), tribe);
+ break;
+ }
+ default:
+ throw wexception("Unknown building category %u (%s)", static_cast<uint8_t>(type), name.c_str());
+ }
+ result->read(game, fr);
+ return result;
+ } else {
+ throw UnhandledVersionError(
+ "BuildingSettings_load", packet_version, kCurrentPacketVersion);
+ }
+ } catch (const WException& e) {
+ throw GameDataError("BuildingSettings_load: %s", e.what());
+ }
+ NEVER_HERE();
+}
+
+void BuildingSettings::read(const Game&, FileRead&) {
+ // Header was peeled away by load()
+}
+
+void BuildingSettings::save(const Game&, FileWrite& fw) const {
+ fw.unsigned_8(kCurrentPacketVersion);
+ fw.c_string(descr_.c_str());
+}
+
+void MilitarysiteSettings::read(const Game& game, FileRead& fr) {
+ BuildingSettings::read(game, fr);
+ try {
+ const uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionMilitarysite) {
+ desired_capacity = fr.unsigned_32();
+ prefer_heroes = fr.unsigned_8();
+ } else {
+ throw UnhandledVersionError(
+ "MilitarysiteSettings", packet_version, kCurrentPacketVersionMilitarysite);
+ }
+ } catch (const WException& e) {
+ throw GameDataError("MilitarysiteSettings: %s", e.what());
+ }
+}
+
+void MilitarysiteSettings::save(const Game& game, FileWrite& fw) const {
+ BuildingSettings::save(game, fw);
+ fw.unsigned_8(static_cast<uint8_t>(BuildingType::kMilitarysite));
+ fw.unsigned_8(kCurrentPacketVersionMilitarysite);
+
+ fw.unsigned_32(desired_capacity);
+ fw.unsigned_8(prefer_heroes ? 1 : 0);
+}
+
+void ProductionsiteSettings::read(const Game& game, FileRead& fr) {
+ BuildingSettings::read(game, fr);
+ try {
+ const uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionProductionsite) {
+ stopped = fr.unsigned_8();
+ const uint32_t nr_wares = fr.unsigned_32();
+ const uint32_t nr_workers = fr.unsigned_32();
+ for (uint32_t i = 0; i < nr_wares; ++i) {
+ const DescriptionIndex di = fr.unsigned_32();
+ const uint32_t fill = fr.unsigned_32();
+ const int32_t priority = fr.signed_32();
+ ware_queues.at(i).first = di;
+ ware_queues.at(i).second.desired_fill = fill;
+ ware_queues.at(i).second.priority = priority;
+ }
+ for (uint32_t i = 0; i < nr_workers; ++i) {
+ const DescriptionIndex di = fr.unsigned_32();
+ const uint32_t fill = fr.unsigned_32();
+ const int32_t priority = fr.signed_32();
+ worker_queues.at(i).first = di;
+ worker_queues.at(i).second.desired_fill = fill;
+ worker_queues.at(i).second.priority = priority;
+ }
+ } else {
+ throw UnhandledVersionError(
+ "ProductionsiteSettings", packet_version, kCurrentPacketVersionProductionsite);
+ }
+ } catch (const WException& e) {
+ throw GameDataError("ProductionsiteSettings: %s", e.what());
+ }
+}
+
+void ProductionsiteSettings::save(const Game& game, FileWrite& fw) const {
+ BuildingSettings::save(game, fw);
+ fw.unsigned_8(static_cast<uint8_t>(BuildingType::kProductionsite));
+ fw.unsigned_8(kCurrentPacketVersionProductionsite);
+
+ fw.unsigned_8(stopped ? 1 : 0);
+ fw.unsigned_32(ware_queues.size());
+ fw.unsigned_32(worker_queues.size());
+ for (const auto& pair : ware_queues) {
+ fw.unsigned_32(pair.first);
+ fw.unsigned_32(pair.second.desired_fill);
+ fw.signed_32(pair.second.priority);
+ }
+ for (const auto& pair : worker_queues) {
+ fw.unsigned_32(pair.first);
+ fw.unsigned_32(pair.second.desired_fill);
+ fw.signed_32(pair.second.priority);
+ }
+}
+
+void TrainingsiteSettings::read(const Game& game, FileRead& fr) {
+ ProductionsiteSettings::read(game, fr);
+ try {
+ const uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionTrainingsite) {
+ desired_capacity = fr.unsigned_32();
+ } else {
+ throw UnhandledVersionError(
+ "TrainingsiteSettings", packet_version, kCurrentPacketVersionTrainingsite);
+ }
+ } catch (const WException& e) {
+ throw GameDataError("TrainingsiteSettings: %s", e.what());
+ }
+}
+
+void TrainingsiteSettings::save(const Game& game, FileWrite& fw) const {
+ ProductionsiteSettings::save(game, fw);
+ fw.unsigned_8(static_cast<uint8_t>(BuildingType::kTrainingsite));
+ fw.unsigned_8(kCurrentPacketVersionTrainingsite);
+ fw.unsigned_32(desired_capacity);
+}
+
+void WarehouseSettings::read(const Game& game, FileRead& fr) {
+ BuildingSettings::read(game, fr);
+ try {
+ const uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionWarehouse) {
+ launch_expedition = fr.unsigned_8();
+ const uint32_t nr_wares = fr.unsigned_32();
+ const uint32_t nr_workers = fr.unsigned_32();
+ for (uint32_t i = 0; i < nr_wares; ++i) {
+ const DescriptionIndex di = fr.unsigned_32();
+ const uint8_t pref = fr.unsigned_8();
+ ware_preferences[di] = static_cast<StockPolicy>(pref);
+ }
+ for (uint32_t i = 0; i < nr_workers; ++i) {
+ const DescriptionIndex di = fr.unsigned_32();
+ const uint8_t pref = fr.unsigned_8();
+ worker_preferences[di] = static_cast<StockPolicy>(pref);
+ }
+ } else {
+ throw UnhandledVersionError(
+ "WarehouseSettings", packet_version, kCurrentPacketVersionWarehouse);
+ }
+ } catch (const WException& e) {
+ throw GameDataError("WarehouseSettings: %s", e.what());
+ }
+}
+
+void WarehouseSettings::save(const Game& game, FileWrite& fw) const {
+ BuildingSettings::save(game, fw);
+ fw.unsigned_8(static_cast<uint8_t>(BuildingType::kWarehouse));
+ fw.unsigned_8(kCurrentPacketVersionWarehouse);
+
+ fw.unsigned_8(launch_expedition ? 1 : 0);
+ fw.unsigned_32(ware_preferences.size());
+ fw.unsigned_32(worker_preferences.size());
+ for (const auto& pair : ware_preferences) {
+ fw.unsigned_32(pair.first);
+ fw.unsigned_8(static_cast<uint8_t>(pair.second));
+ }
+ for (const auto& pair : worker_preferences) {
+ fw.unsigned_32(pair.first);
+ fw.unsigned_8(static_cast<uint8_t>(pair.second));
+ }
+}
+
+} // namespace Widelands
=== added file 'src/logic/map_objects/tribes/building_settings.h'
--- src/logic/map_objects/tribes/building_settings.h 1970-01-01 00:00:00 +0000
+++ src/logic/map_objects/tribes/building_settings.h 2019-05-14 17:38:23 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2002-2019 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_SETTINGS_H
+#define WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_SETTINGS_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "logic/widelands.h"
+
+class FileRead;
+class FileWrite;
+
+namespace Widelands {
+
+class Game;
+class MilitarySiteDescr;
+class ProductionSiteDescr;
+enum class StockPolicy;
+class TrainingSiteDescr;
+class TribeDescr;
+class WarehouseDescr;
+
+struct BuildingSettings {
+ BuildingSettings(const std::string& name) : descr_(name) {
+ }
+ static BuildingSettings* load(const Game&, const TribeDescr&, FileRead&);
+
+ virtual void save(const Game&, FileWrite&) const;
+ virtual void read(const Game&, FileRead&);
+
+ virtual void apply(const BuildingSettings&) {
+ }
+
+private:
+ const std::string descr_;
+};
+
+struct ProductionsiteSettings : public BuildingSettings {
+ ProductionsiteSettings(const ProductionSiteDescr& descr);
+ void apply(const BuildingSettings&) override;
+
+ void save(const Game&, FileWrite&) const override;
+ void read(const Game&, FileRead&) override;
+
+ struct InputQueueSetting {
+ const uint32_t max_fill;
+ uint32_t desired_fill;
+ int32_t priority;
+ };
+ std::vector<std::pair<DescriptionIndex, InputQueueSetting>> ware_queues;
+ std::vector<std::pair<DescriptionIndex, InputQueueSetting>> worker_queues;
+ bool stopped;
+};
+
+struct MilitarysiteSettings : public BuildingSettings {
+ MilitarysiteSettings(const MilitarySiteDescr&);
+ void apply(const BuildingSettings&) override;
+
+ void save(const Game&, FileWrite&) const override;
+ void read(const Game&, FileRead&) override;
+
+ const uint32_t max_capacity;
+ uint32_t desired_capacity;
+ bool prefer_heroes;
+};
+
+struct TrainingsiteSettings : public ProductionsiteSettings {
+ TrainingsiteSettings(const TrainingSiteDescr&);
+ void apply(const BuildingSettings&) override;
+
+ void save(const Game&, FileWrite&) const override;
+ void read(const Game&, FileRead&) override;
+
+ const uint32_t max_capacity;
+ uint32_t desired_capacity;
+};
+
+struct WarehouseSettings : public BuildingSettings {
+ WarehouseSettings(const WarehouseDescr&, const TribeDescr&);
+ void apply(const BuildingSettings&) override;
+
+ void save(const Game&, FileWrite&) const override;
+ void read(const Game&, FileRead&) override;
+
+ std::map<DescriptionIndex, StockPolicy> ware_preferences;
+ std::map<DescriptionIndex, StockPolicy> worker_preferences;
+ const bool launch_expedition_allowed;
+ bool launch_expedition;
+};
+
+} // namespace Widelands
+
+#endif // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_SETTINGS_H
=== modified file 'src/logic/map_objects/tribes/constructionsite.cc'
--- src/logic/map_objects/tribes/constructionsite.cc 2019-04-26 05:52:49 +0000
+++ src/logic/map_objects/tribes/constructionsite.cc 2019-05-14 17:38:23 +0000
@@ -33,6 +33,11 @@
#include "graphic/text_constants.h"
#include "logic/editor_game_base.h"
#include "logic/game.h"
+#include "logic/game_data_error.h"
+#include "logic/map_objects/tribes/militarysite.h"
+#include "logic/map_objects/tribes/partially_finished_building.h"
+#include "logic/map_objects/tribes/productionsite.h"
+#include "logic/map_objects/tribes/trainingsite.h"
#include "logic/map_objects/tribes/tribe_descr.h"
#include "logic/map_objects/tribes/worker.h"
#include "sound/note_sound.h"
@@ -47,32 +52,67 @@
const RGBColor& player_color,
RenderTarget* dst) const {
// Draw the construction site marker
- const uint32_t anim_idx = becomes->is_animation_known("build") ?
- becomes->get_animation("build") :
- becomes->get_unoccupied_animation();
-
- const Animation& anim = g_gr->animations().get_animation(anim_idx);
- const size_t nr_frames = anim.nr_frames();
- const uint32_t cur_frame = totaltime ? completedtime * nr_frames / totaltime : 0;
- uint32_t anim_time = cur_frame * FRAME_LENGTH;
-
- if (cur_frame) { // not the first pic
- // Draw the complete prev pic , so we won't run into trouble if images have different sizes
- dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, anim_idx,
- anim_time - FRAME_LENGTH, &player_color);
+ std::vector<std::pair<uint32_t, uint32_t>> animations;
+ uint32_t total_frames = 0;
+ for (const BuildingDescr* d : intermediates) {
+ const bool known = d->is_animation_known("build");
+ const uint32_t anim_idx = known ?
+ d->get_animation("build") :
+ d->get_unoccupied_animation();
+ // If there is no build animation, we use only the first frame or we
+ // would get many build steps with almost the same image...
+ const uint32_t nrframes = known ? g_gr->animations().get_animation(anim_idx).nr_frames() : 1;
+ assert(nrframes);
+ total_frames += nrframes;
+ animations.push_back(std::make_pair(anim_idx, nrframes));
+ }
+ { // Now the same for the final building
+ const bool known = becomes->is_animation_known("build");
+ const uint32_t anim_idx = known ?
+ becomes->get_animation("build") :
+ becomes->get_unoccupied_animation();
+ const uint32_t nrframes = known ? g_gr->animations().get_animation(anim_idx).nr_frames() : 1;
+ assert(nrframes);
+ total_frames += nrframes;
+ animations.push_back(std::make_pair(anim_idx, nrframes));
+ }
+
+ uint32_t frame_index = totaltime ? std::min(completedtime * total_frames / totaltime, total_frames) : 0;
+ uint32_t animation_index = 0;
+ while (frame_index >= animations[animation_index].second) {
+ frame_index -= animations[animation_index].second;
+ ++animation_index;
+ assert(animation_index < animations.size());
+ }
+ const uint32_t anim_time = frame_index * FRAME_LENGTH;
+
+ if (frame_index > 0) {
+ // Not the first pic within this animation – draw the previous one
+ dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale,
+ animations[animation_index].first, anim_time - FRAME_LENGTH, &player_color);
+ } else if (animation_index > 0) {
+ // The first pic, but not the first series of animations – draw the last pic of the previous series
+ dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale,
+ animations[animation_index - 1].first,
+ FRAME_LENGTH * (animations[animation_index - 1].second - 1), &player_color);
} else if (was) {
- // Is the first picture but there was another building here before,
- // get its most fitting picture and draw it instead.
- dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale,
- was->get_unoccupied_animation(), anim_time - FRAME_LENGTH, &player_color);
+ // First pic in first series, but there was another building here before –
+ // get its most fitting picture and draw it instead
+ const uint32_t unocc = was->get_unoccupied_animation();
+ dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, unocc,
+ FRAME_LENGTH * (g_gr->animations().get_animation(unocc).nr_frames() - 1),
+ &player_color);
}
// Now blit a segment of the current construction phase from the bottom.
- int percent = 100 * completedtime * nr_frames;
+ int percent = 100 * completedtime * total_frames;
if (totaltime) {
percent /= totaltime;
}
- percent -= 100 * cur_frame;
- dst->blit_animation(point_on_dst, coords, scale, anim_idx, anim_time, &player_color, percent);
+ percent -= 100 * frame_index;
+ for (uint32_t i = 0; i < animation_index; ++i) {
+ percent -= 100 * animations[i].second;
+ }
+ dst->blit_animation(point_on_dst, coords, scale, animations[animation_index].first, anim_time, &player_color, percent);
}
/**
@@ -105,7 +145,7 @@
*/
ConstructionSite::ConstructionSite(const ConstructionSiteDescr& cs_descr)
- : PartiallyFinishedBuilding(cs_descr), fetchfromflag_(0), builder_idle_(false) {
+ : PartiallyFinishedBuilding(cs_descr), fetchfromflag_(0), builder_idle_(false), settings_(nullptr) {
}
void ConstructionSite::update_statistics_string(std::string* s) {
@@ -183,6 +223,22 @@
work_steps_ += it->second;
}
+
+ assert(!settings_);
+ if (upcast(const WarehouseDescr, wd, building_)) {
+ settings_.reset(new WarehouseSettings(*wd, owner().tribe()));
+ } else if (upcast(const TrainingSiteDescr, td, building_)) {
+ settings_.reset(new TrainingsiteSettings(*td));
+ } else if (upcast(const ProductionSiteDescr, pd, building_)) {
+ settings_.reset(new ProductionsiteSettings(*pd));
+ } else if (upcast(const MilitarySiteDescr, md, building_)) {
+ settings_.reset(new MilitarysiteSettings(*md));
+ } else {
+ // TODO(Nordfriese): Add support for markets when trading is implemented
+ log("WARNING: Created constructionsite for a %s, which is not of any known building type\n",
+ building_->name().c_str());
+ }
+
return true;
}
@@ -209,6 +265,48 @@
builder->reset_tasks(dynamic_cast<Game&>(egbase));
builder->set_location(&b);
}
+
+ // Apply settings
+ if (settings_) {
+ if (upcast(ProductionsiteSettings, ps, settings_.get())) {
+ for (const auto& pair : ps->ware_queues) {
+ b.inputqueue(pair.first, wwWARE).set_max_fill(pair.second.desired_fill);
+ b.set_priority(wwWARE, pair.first, pair.second.priority);
+ }
+ for (const auto& pair : ps->worker_queues) {
+ b.inputqueue(pair.first, wwWORKER).set_max_fill(pair.second.desired_fill);
+ b.set_priority(wwWORKER, pair.first, pair.second.priority);
+ }
+ if (upcast(TrainingsiteSettings, ts, ps)) {
+ assert(b.soldier_control());
+ assert(ts->desired_capacity >= b.soldier_control()->min_soldier_capacity());
+ assert(ts->desired_capacity <= b.soldier_control()->max_soldier_capacity());
+ b.mutable_soldier_control()->set_soldier_capacity(ts->desired_capacity);
+ }
+ dynamic_cast<ProductionSite&>(b).set_stopped(ps->stopped);
+ } else if (upcast(MilitarysiteSettings, ms, settings_.get())) {
+ assert(b.soldier_control());
+ assert(ms->desired_capacity >= b.soldier_control()->min_soldier_capacity());
+ assert(ms->desired_capacity <= b.soldier_control()->max_soldier_capacity());
+ b.mutable_soldier_control()->set_soldier_capacity(ms->desired_capacity);
+ dynamic_cast<MilitarySite&>(b).set_soldier_preference(ms->prefer_heroes ?
+ SoldierPreference::kHeroes : SoldierPreference::kRookies);
+ } else if (upcast(WarehouseSettings, ws, settings_.get())) {
+ Warehouse& site = dynamic_cast<Warehouse&>(b);
+ for (const auto& pair : ws->ware_preferences) {
+ site.set_ware_policy(pair.first, pair.second);
+ }
+ for (const auto& pair : ws->worker_preferences) {
+ site.set_worker_policy(pair.first, pair.second);
+ }
+ if (ws->launch_expedition) {
+ get_owner()->start_or_cancel_expedition(site);
+ }
+ } else {
+ NEVER_HERE();
+ }
+ }
+
// Open the new building window if needed
Notifications::publish(NoteBuilding(b.serial(), NoteBuilding::Action::kFinishWarp));
}
@@ -216,6 +314,138 @@
/*
===============
+Start building the next enhancement even before the base building is completed.
+===============
+*/
+void ConstructionSite::enhance(Game&) {
+ assert(building_->enhancement() != INVALID_INDEX);
+ Notifications::publish(NoteImmovable(this, NoteImmovable::Ownership::LOST));
+
+ info_.intermediates.push_back(building_);
+ old_buildings_.push_back(owner().tribe().building_index(building_->name()));
+ building_ = owner().tribe().get_building_descr(building_->enhancement());
+ assert(building_);
+ info_.becomes = building_;
+
+ const std::map<DescriptionIndex, uint8_t>& buildcost = building_->enhancement_cost();
+ const size_t buildcost_size = buildcost.size();
+ std::set<DescriptionIndex> new_ware_types;
+ for (std::map<DescriptionIndex, uint8_t>::const_iterator it = buildcost.begin(); it != buildcost.end(); ++it) {
+ bool found = false;
+ for (const auto& queue : wares_) {
+ if (queue->get_index() == it->first) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ new_ware_types.insert(it->first);
+ }
+ }
+
+ const size_t old_size = wares_.size();
+ wares_.resize(old_size + new_ware_types.size());
+ std::map<DescriptionIndex, uint8_t>::const_iterator it = buildcost.begin();
+
+ size_t new_wares_index = 0;
+ for (size_t i = 0; i < buildcost_size; ++i, ++it) {
+ if (new_ware_types.count(it->first)) {
+ WaresQueue& wq = *(wares_[old_size + new_wares_index] = new WaresQueue(*this, it->first, it->second));
+ wq.set_callback(ConstructionSite::wares_queue_callback, this);
+ wq.set_consume_interval(CONSTRUCTIONSITE_STEP_TIME);
+ ++new_wares_index;
+ } else {
+ assert(i >= new_wares_index);
+ WaresQueue& wq = *wares_[i - new_wares_index];
+ wq.set_max_size(wq.get_max_size() + it->second);
+ wq.set_max_fill(wq.get_max_fill() + it->second);
+ }
+ work_steps_ += it->second;
+ }
+
+ BuildingSettings* old_settings = settings_.release();
+ if (upcast(const WarehouseDescr, wd, building_)) {
+ WarehouseSettings* new_settings = new WarehouseSettings(*wd, owner().tribe());
+ settings_.reset(new_settings);
+ if (upcast(WarehouseSettings, ws, old_settings)) {
+ for (const auto& pair : ws->ware_preferences) {
+ new_settings->ware_preferences[pair.first] = pair.second;
+ }
+ for (const auto& pair : ws->worker_preferences) {
+ new_settings->worker_preferences[pair.first] = pair.second;
+ }
+ new_settings->launch_expedition = ws->launch_expedition && building_->get_isport();
+ }
+ } else if (upcast(const TrainingSiteDescr, td, building_)) {
+ TrainingsiteSettings* new_settings = new TrainingsiteSettings(*td);
+ settings_.reset(new_settings);
+ if (upcast(ProductionsiteSettings, ps, old_settings)) {
+ new_settings->stopped = ps->stopped;
+ for (const auto& pair_old : ps->ware_queues) {
+ for (auto& pair_new : new_settings->ware_queues) {
+ if (pair_new.first == pair_old.first) {
+ pair_new.second.priority = pair_old.second.priority;
+ pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill);
+ break;
+ }
+ }
+ }
+ for (const auto& pair_old : ps->worker_queues) {
+ for (auto& pair_new : new_settings->worker_queues) {
+ if (pair_new.first == pair_old.first) {
+ pair_new.second.priority = pair_old.second.priority;
+ pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill);
+ break;
+ }
+ }
+ }
+ if (upcast(TrainingsiteSettings, ts, old_settings)) {
+ new_settings->desired_capacity = std::min(new_settings->max_capacity, ts->desired_capacity);
+ }
+ }
+ } else if (upcast(const ProductionSiteDescr, pd, building_)) {
+ ProductionsiteSettings* new_settings = new ProductionsiteSettings(*pd);
+ settings_.reset(new_settings);
+ if (upcast(ProductionsiteSettings, ps, old_settings)) {
+ new_settings->stopped = ps->stopped;
+ for (const auto& pair_old : ps->ware_queues) {
+ for (auto& pair_new : new_settings->ware_queues) {
+ if (pair_new.first == pair_old.first) {
+ pair_new.second.priority = pair_old.second.priority;
+ pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill);
+ break;
+ }
+ }
+ }
+ for (const auto& pair_old : ps->worker_queues) {
+ for (auto& pair_new : new_settings->worker_queues) {
+ if (pair_new.first == pair_old.first) {
+ pair_new.second.priority = pair_old.second.priority;
+ pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill);
+ break;
+ }
+ }
+ }
+ }
+ } else if (upcast(const MilitarySiteDescr, md, building_)) {
+ MilitarysiteSettings* new_settings = new MilitarysiteSettings(*md);
+ settings_.reset(new_settings);
+ if (upcast(MilitarysiteSettings, ms, old_settings)) {
+ new_settings->desired_capacity = std::max<uint32_t>(1, std::min<uint32_t>(
+ new_settings->max_capacity, ms->desired_capacity));
+ new_settings->prefer_heroes = ms->prefer_heroes;
+ }
+ } else {
+ // TODO(Nordfriese): Add support for markets when trading is implemented
+ log("WARNING: Enhanced constructionsite to a %s, which is not of any known building type\n",
+ building_->name().c_str());
+ }
+ Notifications::publish(NoteImmovable(this, NoteImmovable::Ownership::GAINED));
+ Notifications::publish(NoteBuilding(serial(), NoteBuilding::Action::kChanged));
+}
+
+/*
+===============
Construction sites only burn if some of the work has been completed.
===============
*/
@@ -345,6 +575,16 @@
/*
===============
+Overwrite as many values of the current settings with those of the given settings as possible.
+===============
+*/
+void ConstructionSite::apply_settings(const BuildingSettings& cs) {
+ assert(settings_);
+ settings_->apply(cs);
+}
+
+/*
+===============
Draw the construction site.
===============
*/
=== modified file 'src/logic/map_objects/tribes/constructionsite.h'
--- src/logic/map_objects/tribes/constructionsite.h 2019-05-05 14:05:07 +0000
+++ src/logic/map_objects/tribes/constructionsite.h 2019-05-14 17:38:23 +0000
@@ -20,16 +20,26 @@
#ifndef WL_LOGIC_MAP_OBJECTS_TRIBES_CONSTRUCTIONSITE_H
#define WL_LOGIC_MAP_OBJECTS_TRIBES_CONSTRUCTIONSITE_H
+#include <memory>
#include <vector>
#include "base/macros.h"
+#include "logic/map_objects/tribes/building_settings.h"
#include "logic/map_objects/tribes/partially_finished_building.h"
#include "scripting/lua_table.h"
+class FileRead;
+class FileWrite;
+
namespace Widelands {
class Building;
+class MilitarySiteDescr;
+class ProductionSiteDescr;
class Request;
+enum class StockPolicy;
+class TrainingSiteDescr;
+class WarehouseDescr;
class WaresQueue;
/// Per-player and per-field constructionsite information
@@ -47,6 +57,7 @@
const BuildingDescr*
becomes; // Also works as a marker telling whether there is a construction site.
const BuildingDescr* was; // only valid if "becomes" is an enhanced building.
+ std::vector<const BuildingDescr*> intermediates; // If we enhance a building while it's still under construction
uint32_t totaltime;
uint32_t completedtime;
};
@@ -114,6 +125,13 @@
bool fetch_from_flag(Game&) override;
bool get_building_work(Game&, Worker&, bool success) override;
+ BuildingSettings* get_settings() const {
+ return settings_.get();
+ }
+ void apply_settings(const BuildingSettings&);
+
+ void enhance(Game&);
+
protected:
void update_statistics_string(std::string* statistics_string) override;
@@ -135,6 +153,8 @@
bool builder_idle_; // used to determine whether the builder is idle
ConstructionsiteInformation info_; // asked for by player point of view for the gameview
+
+ std::unique_ptr<BuildingSettings> settings_;
};
} // namespace Widelands
=== modified file 'src/logic/map_objects/tribes/militarysite.cc'
--- src/logic/map_objects/tribes/militarysite.cc 2019-05-11 10:06:28 +0000
+++ src/logic/map_objects/tribes/militarysite.cc 2019-05-14 17:38:23 +0000
@@ -974,6 +974,13 @@
return false;
}
+const BuildingSettings* MilitarySite::create_building_settings() const {
+ MilitarysiteSettings* settings = new MilitarysiteSettings(descr());
+ settings->desired_capacity = std::min(settings->max_capacity, soldier_control_.soldier_capacity());
+ settings->prefer_heroes = soldier_preference_ == SoldierPreference::kHeroes;
+ return settings;
+}
+
// setters
void MilitarySite::set_soldier_preference(SoldierPreference p) {
=== modified file 'src/logic/map_objects/tribes/militarysite.h'
--- src/logic/map_objects/tribes/militarysite.h 2019-05-05 14:05:07 +0000
+++ src/logic/map_objects/tribes/militarysite.h 2019-05-14 17:38:23 +0000
@@ -108,6 +108,8 @@
return soldier_preference_;
}
+ const BuildingSettings* create_building_settings() const override;
+
protected:
void conquer_area(EditorGameBase&);
=== modified file 'src/logic/map_objects/tribes/productionsite.cc'
--- src/logic/map_objects/tribes/productionsite.cc 2019-05-12 09:58:40 +0000
+++ src/logic/map_objects/tribes/productionsite.cc 2019-05-14 17:38:23 +0000
@@ -1017,6 +1017,30 @@
set_production_result("");
}
+const BuildingSettings* ProductionSite::create_building_settings() const {
+ ProductionsiteSettings* settings = new ProductionsiteSettings(descr());
+ settings->stopped = is_stopped_;
+ for (auto& pair : settings->ware_queues) {
+ pair.second.priority = get_priority(wwWARE, pair.first, false);
+ for (const auto& queue : input_queues_) {
+ if (queue->get_type() == wwWARE && queue->get_index() == pair.first) {
+ pair.second.desired_fill = std::min(pair.second.max_fill, queue->get_max_fill());
+ break;
+ }
+ }
+ }
+ for (auto& pair : settings->worker_queues) {
+ pair.second.priority = get_priority(wwWORKER, pair.first, false);
+ for (const auto& queue : input_queues_) {
+ if (queue->get_type() == wwWORKER && queue->get_index() == pair.first) {
+ pair.second.desired_fill = std::min(pair.second.max_fill, queue->get_max_fill());
+ break;
+ }
+ }
+ }
+ return settings;
+}
+
/// Changes the default anim string to \li anim
void ProductionSite::set_default_anim(std::string anim) {
if (default_anim_ == anim)
=== modified file 'src/logic/map_objects/tribes/productionsite.h'
--- src/logic/map_objects/tribes/productionsite.h 2019-05-11 12:37:45 +0000
+++ src/logic/map_objects/tribes/productionsite.h 2019-05-14 17:38:23 +0000
@@ -236,6 +236,8 @@
void set_default_anim(std::string);
+ const BuildingSettings* create_building_settings() const override;
+
protected:
void update_statistics_string(std::string* statistics) override;
=== modified file 'src/logic/map_objects/tribes/trainingsite.cc'
--- src/logic/map_objects/tribes/trainingsite.cc 2019-05-05 14:05:07 +0000
+++ src/logic/map_objects/tribes/trainingsite.cc 2019-05-14 17:38:23 +0000
@@ -525,6 +525,31 @@
}
}
+const BuildingSettings* TrainingSite::create_building_settings() const {
+ TrainingsiteSettings* settings = new TrainingsiteSettings(descr());
+ settings->desired_capacity = std::min(settings->max_capacity, soldier_control_.soldier_capacity());
+ settings->stopped = is_stopped_;
+ for (auto& pair : settings->ware_queues) {
+ pair.second.priority = get_priority(wwWARE, pair.first, false);
+ for (const auto& queue : input_queues_) {
+ if (queue->get_type() == wwWARE && queue->get_index() == pair.first) {
+ pair.second.desired_fill = std::min(pair.second.max_fill, queue->get_max_fill());
+ break;
+ }
+ }
+ }
+ for (auto& pair : settings->worker_queues) {
+ pair.second.priority = get_priority(wwWORKER, pair.first, false);
+ for (const auto& queue : input_queues_) {
+ if (queue->get_type() == wwWORKER && queue->get_index() == pair.first) {
+ pair.second.desired_fill = std::min(pair.second.max_fill, queue->get_max_fill());
+ break;
+ }
+ }
+ }
+ return settings;
+}
+
/**
* In addition to advancing the program, update soldier status.
*/
=== modified file 'src/logic/map_objects/tribes/trainingsite.h'
--- src/logic/map_objects/tribes/trainingsite.h 2019-05-05 14:05:07 +0000
+++ src/logic/map_objects/tribes/trainingsite.h 2019-05-14 17:38:23 +0000
@@ -199,6 +199,8 @@
void training_successful(TrainingAttribute type, uint32_t level);
void training_done();
+ const BuildingSettings* create_building_settings() const override;
+
protected:
void program_end(Game&, ProgramResult) override;
=== modified file 'src/logic/map_objects/tribes/warehouse.cc'
--- src/logic/map_objects/tribes/warehouse.cc 2019-03-01 04:19:53 +0000
+++ src/logic/map_objects/tribes/warehouse.cc 2019-05-14 17:38:23 +0000
@@ -1275,17 +1275,17 @@
}
}
-Warehouse::StockPolicy Warehouse::get_ware_policy(DescriptionIndex ware) const {
+StockPolicy Warehouse::get_ware_policy(DescriptionIndex ware) const {
assert(ware < static_cast<DescriptionIndex>(ware_policy_.size()));
return ware_policy_[ware];
}
-Warehouse::StockPolicy Warehouse::get_worker_policy(DescriptionIndex ware) const {
+StockPolicy Warehouse::get_worker_policy(DescriptionIndex ware) const {
assert(ware < static_cast<DescriptionIndex>(worker_policy_.size()));
return worker_policy_[ware];
}
-Warehouse::StockPolicy Warehouse::get_stock_policy(WareWorker waretype,
+StockPolicy Warehouse::get_stock_policy(WareWorker waretype,
DescriptionIndex wareindex) const {
if (waretype == wwWORKER)
return get_worker_policy(wareindex);
@@ -1293,25 +1293,25 @@
return get_ware_policy(wareindex);
}
-void Warehouse::set_ware_policy(DescriptionIndex ware, Warehouse::StockPolicy policy) {
+void Warehouse::set_ware_policy(DescriptionIndex ware, StockPolicy policy) {
assert(ware < static_cast<DescriptionIndex>(ware_policy_.size()));
ware_policy_[ware] = policy;
}
-void Warehouse::set_worker_policy(DescriptionIndex ware, Warehouse::StockPolicy policy) {
+void Warehouse::set_worker_policy(DescriptionIndex ware, StockPolicy policy) {
assert(ware < static_cast<DescriptionIndex>(worker_policy_.size()));
worker_policy_[ware] = policy;
}
/**
- * Check if there are remaining wares with \ref Warehouse::StockPolicy::kRemove,
+ * Check if there are remaining wares with \ref StockPolicy::kRemove,
* and remove one of them if appropriate.
*/
void Warehouse::check_remove_stock(Game& game) {
if (base_flag().current_wares() < base_flag().total_capacity() / 2) {
for (DescriptionIndex ware = 0; ware < static_cast<DescriptionIndex>(ware_policy_.size());
++ware) {
- if (get_ware_policy(ware) != Warehouse::StockPolicy::kRemove || !get_wares().stock(ware))
+ if (get_ware_policy(ware) != StockPolicy::kRemove || !get_wares().stock(ware))
continue;
launch_ware(game, ware);
@@ -1321,7 +1321,7 @@
for (DescriptionIndex widx = 0; widx < static_cast<DescriptionIndex>(worker_policy_.size());
++widx) {
- if (get_worker_policy(widx) != Warehouse::StockPolicy::kRemove || !get_workers().stock(widx))
+ if (get_worker_policy(widx) != StockPolicy::kRemove || !get_workers().stock(widx))
continue;
Worker& worker = launch_worker(game, widx, Requirements());
@@ -1337,6 +1337,18 @@
return portdock_->expedition_bootstrap()->inputqueue(index, type);
}
+const BuildingSettings* Warehouse::create_building_settings() const {
+ WarehouseSettings* settings = new WarehouseSettings(descr(), owner().tribe());
+ for (auto& pair : settings->ware_preferences) {
+ pair.second = get_ware_policy(pair.first);
+ }
+ for (auto& pair : settings->worker_preferences) {
+ pair.second = get_worker_policy(pair.first);
+ }
+ settings->launch_expedition = portdock_ && portdock_->expedition_started();
+ return settings;
+}
+
void Warehouse::log_general_info(const EditorGameBase& egbase) const {
Building::log_general_info(egbase);
=== modified file 'src/logic/map_objects/tribes/warehouse.h'
--- src/logic/map_objects/tribes/warehouse.h 2019-05-05 14:05:07 +0000
+++ src/logic/map_objects/tribes/warehouse.h 2019-05-14 17:38:23 +0000
@@ -68,6 +68,40 @@
DISALLOW_COPY_AND_ASSIGN(WarehouseDescr);
};
+/**
+ * Each ware and worker type has an associated per-warehouse
+ * stock policy that defines whether it will be stocked by this
+ * warehouse.
+ *
+ * \note The values of this enum are written directly into savegames,
+ * so be careful when changing them.
+ */
+enum class StockPolicy {
+ /**
+ * The default policy allows stocking wares without any special priority.
+ */
+ kNormal = 0,
+
+ /**
+ * As long as there are warehouses with this policy for a ware, all
+ * available unstocked supplies will be transferred to warehouses
+ * with this policy.
+ */
+ kPrefer = 1,
+
+ /**
+ * If a ware has this stock policy, no more of this ware will enter
+ * the warehouse.
+ */
+ kDontStock = 2,
+
+ /**
+ * Like \ref kDontStock, but in addition, existing stock of this ware
+ * will be transported out of the warehouse over time.
+ */
+ kRemove = 3,
+};
+
class Warehouse : public Building {
friend class PortDock;
friend class MapBuildingdataPacket;
@@ -75,39 +109,6 @@
MO_DESCR(WarehouseDescr)
public:
- /**
- * Each ware and worker type has an associated per-warehouse
- * stock policy that defines whether it will be stocked by this
- * warehouse.
- *
- * \note The values of this enum are written directly into savegames,
- * so be careful when changing them.
- */
- enum class StockPolicy {
- /**
- * The default policy allows stocking wares without any special priority.
- */
- kNormal = 0,
-
- /**
- * As long as there are warehouses with this policy for a ware, all
- * available unstocked supplies will be transferred to warehouses
- * with this policy.
- */
- kPrefer = 1,
-
- /**
- * If a ware has this stock policy, no more of this ware will enter
- * the warehouse.
- */
- kDontStock = 2,
-
- /**
- * Like \ref kDontStock, but in addition, existing stock of this ware
- * will be transported out of the warehouse over time.
- */
- kRemove = 3,
- };
/**
* Whether worker indices in count_workers() have to match exactly.
@@ -208,6 +209,8 @@
return portdock_;
}
+ const BuildingSettings* create_building_settings() const override;
+
// Returns the waresqueue of the expedition if this is a port.
// Will throw an exception otherwise.
InputQueue& inputqueue(DescriptionIndex, WareWorker) override;
=== modified file 'src/logic/player.cc'
--- src/logic/player.cc 2019-05-11 18:19:20 +0000
+++ src/logic/player.cc 2019-05-14 17:38:23 +0000
@@ -760,6 +760,7 @@
} else {
workers = building->get_workers();
}
+ const BuildingSettings* settings = building->create_building_settings();
if (index_of_new_building != INVALID_INDEX) {
// For enhancing, register whether the window was open
@@ -770,7 +771,7 @@
// pointer.
if (index_of_new_building != INVALID_INDEX)
building = &egbase().warp_constructionsite(
- position, player_number_, index_of_new_building, false, former_buildings);
+ position, player_number_, index_of_new_building, false, former_buildings, settings);
else
building = &egbase().warp_dismantlesite(position, player_number_, false, former_buildings);
=== modified file 'src/logic/playercommand.cc'
--- src/logic/playercommand.cc 2019-05-07 12:26:11 +0000
+++ src/logic/playercommand.cc 2019-05-14 17:38:23 +0000
@@ -108,6 +108,14 @@
PLCMD_SHIP_SINK = 29,
PLCMD_SHIP_CANCELEXPEDITION = 30,
PLCMD_PROPOSE_TRADE = 31,
+ PLCMD_CONSTRUCTIONSITE_SOLDIERCAPACITY = 32,
+ PLCMD_CONSTRUCTIONSITE_PREFERHEROES = 33,
+ PLCMD_CONSTRUCTIONSITE_INPUTQUEUE_PRIORITY = 34,
+ PLCMD_CONSTRUCTIONSITE_INPUTQUEUE_MAXFILL = 35,
+ PLCMD_CONSTRUCTIONSITE_STOCKPOLICY = 36,
+ PLCMD_CONSTRUCTIONSITE_LAUNCHEXPEDITION = 37,
+ PLCMD_CONSTRUCTIONSITE_ENHANCE = 38,
+ PLCMD_CONSTRUCTIONSITE_STARTSTOP = 39,
};
/*** class PlayerCommand ***/
@@ -176,6 +184,22 @@
return new CmdEvictWorker(des);
case PLCMD_MILITARYSITESETSOLDIERPREFERENCE:
return new CmdMilitarySiteSetSoldierPreference(des);
+ case PLCMD_CONSTRUCTIONSITE_SOLDIERCAPACITY:
+ return new CmdConstructionsiteSoldierCapacity(des);
+ case PLCMD_CONSTRUCTIONSITE_PREFERHEROES:
+ return new CmdConstructionsitePreferHeroes(des);
+ case PLCMD_CONSTRUCTIONSITE_INPUTQUEUE_PRIORITY:
+ return new CmdConstructionsiteInputQueuePriority(des);
+ case PLCMD_CONSTRUCTIONSITE_INPUTQUEUE_MAXFILL:
+ return new CmdConstructionsiteInputQueueMaxFill(des);
+ case PLCMD_CONSTRUCTIONSITE_STOCKPOLICY:
+ return new CmdConstructionsiteStockPolicy(des);
+ case PLCMD_CONSTRUCTIONSITE_LAUNCHEXPEDITION:
+ return new CmdConstructionsiteLaunchExpedition(des);
+ case PLCMD_CONSTRUCTIONSITE_ENHANCE:
+ return new CmdConstructionsiteEnhance(des);
+ case PLCMD_CONSTRUCTIONSITE_STARTSTOP:
+ return new CmdConstructionsiteStartStop(des);
default:
throw wexception("PlayerCommand::deserialize(): Invalid command id encountered");
}
@@ -1751,7 +1775,7 @@
Warehouse& wh,
bool isworker,
DescriptionIndex ware,
- Warehouse::StockPolicy policy)
+ StockPolicy policy)
: PlayerCommand(time, p) {
warehouse_ = wh.serial();
isworker_ = isworker;
@@ -1794,7 +1818,7 @@
warehouse_ = des.unsigned_32();
isworker_ = des.unsigned_8();
ware_ = DescriptionIndex(des.unsigned_8());
- policy_ = static_cast<Warehouse::StockPolicy>(des.unsigned_8());
+ policy_ = static_cast<StockPolicy>(des.unsigned_8());
}
void CmdSetStockPolicy::serialize(StreamWrite& ser) {
@@ -1816,7 +1840,7 @@
warehouse_ = fr.unsigned_32();
isworker_ = fr.unsigned_8();
ware_ = DescriptionIndex(fr.unsigned_8());
- policy_ = static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
+ policy_ = static_cast<StockPolicy>(fr.unsigned_8());
} else {
throw UnhandledVersionError(
"CmdSetStockPolicy", packet_version, kCurrentPacketVersionCmdSetStockPolicy);
@@ -1904,4 +1928,601 @@
// TODO(sirver,trading): Implement this.
NEVER_HERE();
}
+
+
+/*** struct CmdConstructionsiteSoldierCapacity ***/
+CmdConstructionsiteSoldierCapacity::CmdConstructionsiteSoldierCapacity(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs,
+ uint32_t cap)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()), capacity_(cap) {
+}
+
+CmdConstructionsiteSoldierCapacity::CmdConstructionsiteSoldierCapacity()
+ : PlayerCommand(), constructionsite_(0), capacity_(0) {
+}
+
+void CmdConstructionsiteSoldierCapacity::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsiteSoldierCapacity: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ if (upcast(MilitarysiteSettings, ms, cs->get_settings())) {
+ assert(ms->max_capacity >= capacity_);
+ ms->desired_capacity = capacity_;
+ } else if (upcast(TrainingsiteSettings, ts, cs->get_settings())) {
+ assert(ts->max_capacity >= capacity_);
+ ts->desired_capacity = capacity_;
+ }
+ }
+ }
+}
+
+CmdConstructionsiteSoldierCapacity::CmdConstructionsiteSoldierCapacity(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+ capacity_ = des.unsigned_32();
+}
+
+void CmdConstructionsiteSoldierCapacity::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_SOLDIERCAPACITY);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+ ser.unsigned_32(capacity_);
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsiteSoldierCapacity = 1;
+
+void CmdConstructionsiteSoldierCapacity::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsiteSoldierCapacity) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ capacity_ = fr.unsigned_32();
+ } else {
+ throw UnhandledVersionError("CmdConstructionsiteSoldierCapacity", packet_version,
+ kCurrentPacketVersionCmdConstructionsiteSoldierCapacity);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsiteSoldierCapacity: %s", e.what());
+ }
+}
+
+void CmdConstructionsiteSoldierCapacity::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsiteSoldierCapacity);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+ fw.unsigned_32(capacity_);
+}
+
+/*** struct CmdConstructionsitePreferHeroes ***/
+CmdConstructionsitePreferHeroes::CmdConstructionsitePreferHeroes(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs,
+ bool h)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()), heroes_(h) {
+}
+
+CmdConstructionsitePreferHeroes::CmdConstructionsitePreferHeroes()
+ : PlayerCommand(), constructionsite_(0), heroes_(false) {
+}
+
+void CmdConstructionsitePreferHeroes::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsitePreferHeroes: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ if (upcast(MilitarysiteSettings, s, cs->get_settings())) {
+ s->prefer_heroes = heroes_;
+ }
+ }
+ }
+}
+
+CmdConstructionsitePreferHeroes::CmdConstructionsitePreferHeroes(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+ heroes_ = des.unsigned_8();
+}
+
+void CmdConstructionsitePreferHeroes::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_PREFERHEROES);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+ ser.unsigned_8(heroes_ ? 1 : 0);
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsitePreferHeroes = 1;
+
+void CmdConstructionsitePreferHeroes::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsitePreferHeroes) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ heroes_ = fr.unsigned_8();
+ } else {
+ throw UnhandledVersionError("CmdConstructionsitePreferHeroes", packet_version,
+ kCurrentPacketVersionCmdConstructionsitePreferHeroes);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsitePreferHeroes: %s", e.what());
+ }
+}
+
+void CmdConstructionsitePreferHeroes::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsitePreferHeroes);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+ fw.unsigned_8(heroes_ ? 1 : 0);
+}
+
+/*** struct CmdConstructionsiteLaunchExpedition ***/
+CmdConstructionsiteLaunchExpedition::CmdConstructionsiteLaunchExpedition(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs,
+ bool l)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()), launch_(l) {
+}
+
+CmdConstructionsiteLaunchExpedition::CmdConstructionsiteLaunchExpedition()
+ : PlayerCommand(), constructionsite_(0), launch_(false) {
+}
+
+void CmdConstructionsiteLaunchExpedition::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsiteLaunchExpedition: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ if (upcast(WarehouseSettings, s, cs->get_settings())) {
+ s->launch_expedition = launch_;
+ }
+ }
+ }
+}
+
+CmdConstructionsiteLaunchExpedition::CmdConstructionsiteLaunchExpedition(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+ launch_ = des.unsigned_8();
+}
+
+void CmdConstructionsiteLaunchExpedition::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_LAUNCHEXPEDITION);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+ ser.unsigned_8(launch_ ? 1 : 0);
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsiteLaunchExpedition = 1;
+
+void CmdConstructionsiteLaunchExpedition::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsiteLaunchExpedition) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ launch_ = fr.unsigned_8();
+ } else {
+ throw UnhandledVersionError("CmdConstructionsiteLaunchExpedition", packet_version,
+ kCurrentPacketVersionCmdConstructionsiteLaunchExpedition);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsiteLaunchExpedition: %s", e.what());
+ }
+}
+
+void CmdConstructionsiteLaunchExpedition::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsiteLaunchExpedition);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+ fw.unsigned_8(launch_ ? 1 : 0);
+}
+
+/*** struct CmdConstructionsiteStartStop ***/
+CmdConstructionsiteStartStop::CmdConstructionsiteStartStop(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs,
+ bool stop)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()), stopped_(stop) {
+}
+
+CmdConstructionsiteStartStop::CmdConstructionsiteStartStop()
+ : PlayerCommand(), constructionsite_(0), stopped_(false) {
+}
+
+void CmdConstructionsiteStartStop::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsiteStartStop: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ if (upcast(ProductionsiteSettings, s, cs->get_settings())) {
+ s->stopped = stopped_;
+ }
+ }
+ }
+}
+
+CmdConstructionsiteStartStop::CmdConstructionsiteStartStop(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+ stopped_ = des.unsigned_8();
+}
+
+void CmdConstructionsiteStartStop::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_STARTSTOP);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+ ser.unsigned_8(stopped_ ? 1 : 0);
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsiteStartStop = 1;
+
+void CmdConstructionsiteStartStop::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsiteStartStop) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ stopped_ = fr.unsigned_8();
+ } else {
+ throw UnhandledVersionError("CmdConstructionsiteStartStop", packet_version,
+ kCurrentPacketVersionCmdConstructionsiteStartStop);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsiteStartStop: %s", e.what());
+ }
+}
+
+void CmdConstructionsiteStartStop::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsiteStartStop);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+ fw.unsigned_8(stopped_ ? 1 : 0);
+}
+
+/*** struct CmdConstructionsiteStockPolicy ***/
+CmdConstructionsiteStockPolicy::CmdConstructionsiteStockPolicy(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs,
+ WareWorker ww,
+ DescriptionIndex di,
+ StockPolicy pol)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()), wwtype_(ww), index_(di), policy_(pol) {
+}
+
+CmdConstructionsiteStockPolicy::CmdConstructionsiteStockPolicy()
+ : PlayerCommand(), constructionsite_(0), wwtype_(wwWARE), index_(INVALID_INDEX), policy_() {
+}
+
+void CmdConstructionsiteStockPolicy::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsiteStockPolicy: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ if (upcast(WarehouseSettings, s, cs->get_settings())) {
+ switch (wwtype_) {
+ case wwWARE:
+ s->ware_preferences[index_] = policy_;
+ break;
+ case wwWORKER:
+ s->worker_preferences[index_] = policy_;
+ break;
+ NEVER_HERE();
+ }
+ }
+ }
+ }
+}
+
+CmdConstructionsiteStockPolicy::CmdConstructionsiteStockPolicy(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+ wwtype_ = des.unsigned_8() == 0 ? wwWARE : wwWORKER;
+ index_ = des.unsigned_32();
+ policy_ = static_cast<StockPolicy>(des.unsigned_8());
+}
+
+void CmdConstructionsiteStockPolicy::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_STOCKPOLICY);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+ ser.unsigned_8(wwtype_ == wwWARE ? 0 : 1);
+ ser.unsigned_32(index_);
+ ser.unsigned_8(static_cast<uint8_t>(policy_));
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsiteStockPolicy = 1;
+
+void CmdConstructionsiteStockPolicy::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsiteStockPolicy) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ wwtype_ = fr.unsigned_8() == 0 ? wwWARE : wwWORKER;
+ index_ = fr.unsigned_32();
+ policy_ = static_cast<StockPolicy>(fr.unsigned_8());
+ } else {
+ throw UnhandledVersionError("CmdConstructionsiteStockPolicy", packet_version,
+ kCurrentPacketVersionCmdConstructionsiteStockPolicy);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsiteStockPolicy: %s", e.what());
+ }
+}
+
+void CmdConstructionsiteStockPolicy::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsiteStockPolicy);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+ fw.unsigned_8(wwtype_ == wwWARE ? 0 : 1);
+ fw.unsigned_32(index_);
+ fw.unsigned_8(static_cast<uint8_t>(policy_));
+}
+
+/*** struct CmdConstructionsiteInputQueuePriority ***/
+CmdConstructionsiteInputQueuePriority::CmdConstructionsiteInputQueuePriority(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs,
+ WareWorker ww,
+ DescriptionIndex di,
+ int32_t prio)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()), wwtype_(ww), index_(di), priority_(prio) {
+}
+
+CmdConstructionsiteInputQueuePriority::CmdConstructionsiteInputQueuePriority()
+ : PlayerCommand(), constructionsite_(0), wwtype_(wwWARE), index_(INVALID_INDEX), priority_(0) {
+}
+
+void CmdConstructionsiteInputQueuePriority::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsiteInputQueuePriority: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ if (upcast(ProductionsiteSettings, s, cs->get_settings())) {
+ switch (wwtype_) {
+ case wwWARE:
+ for (auto& pair : s->ware_queues) {
+ if (pair.first == index_) {
+ pair.second.priority = priority_;
+ return;
+ }
+ }
+ NEVER_HERE();
+ case wwWORKER:
+ for (auto& pair : s->worker_queues) {
+ if (pair.first == index_) {
+ pair.second.priority = priority_;
+ return;
+ }
+ }
+ NEVER_HERE();
+ default:
+ NEVER_HERE();
+ }
+ }
+ }
+ }
+}
+
+CmdConstructionsiteInputQueuePriority::CmdConstructionsiteInputQueuePriority(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+ wwtype_ = des.unsigned_8() == 0 ? wwWARE : wwWORKER;
+ index_ = des.unsigned_32();
+ priority_ = des.signed_32();
+}
+
+void CmdConstructionsiteInputQueuePriority::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_INPUTQUEUE_PRIORITY);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+ ser.unsigned_8(wwtype_ == wwWARE ? 0 : 1);
+ ser.unsigned_32(index_);
+ ser.signed_32(priority_);
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsiteInputQueuePriority = 1;
+
+void CmdConstructionsiteInputQueuePriority::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsiteInputQueuePriority) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ wwtype_ = fr.unsigned_8() == 0 ? wwWARE : wwWORKER;
+ index_ = fr.unsigned_32();
+ priority_ = fr.signed_32();
+ } else {
+ throw UnhandledVersionError("CmdConstructionsiteInputQueuePriority", packet_version,
+ kCurrentPacketVersionCmdConstructionsiteInputQueuePriority);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsiteInputQueuePriority: %s", e.what());
+ }
+}
+
+void CmdConstructionsiteInputQueuePriority::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsiteInputQueuePriority);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+ fw.unsigned_8(wwtype_ == wwWARE ? 0 : 1);
+ fw.unsigned_32(index_);
+ fw.signed_32(priority_);
+}
+
+/*** struct CmdConstructionsiteInputQueueMaxFill ***/
+CmdConstructionsiteInputQueueMaxFill::CmdConstructionsiteInputQueueMaxFill(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs,
+ WareWorker ww,
+ DescriptionIndex di,
+ uint32_t max)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()), wwtype_(ww), index_(di), max_fill_(max) {
+}
+
+CmdConstructionsiteInputQueueMaxFill::CmdConstructionsiteInputQueueMaxFill()
+ : PlayerCommand(), constructionsite_(0), wwtype_(wwWARE), index_(INVALID_INDEX), max_fill_(0) {
+}
+
+void CmdConstructionsiteInputQueueMaxFill::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsiteInputQueueMaxFill: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ if (upcast(ProductionsiteSettings, s, cs->get_settings())) {
+ switch (wwtype_) {
+ case wwWARE:
+ for (auto& pair : s->ware_queues) {
+ if (pair.first == index_) {
+ assert(pair.second.max_fill >= max_fill_);
+ pair.second.desired_fill = max_fill_;
+ return;
+ }
+ }
+ NEVER_HERE();
+ case wwWORKER:
+ for (auto& pair : s->worker_queues) {
+ if (pair.first == index_) {
+ assert(pair.second.max_fill >= max_fill_);
+ pair.second.desired_fill = max_fill_;
+ return;
+ }
+ }
+ NEVER_HERE();
+ default:
+ NEVER_HERE();
+ }
+ }
+ }
+ }
+}
+
+CmdConstructionsiteInputQueueMaxFill::CmdConstructionsiteInputQueueMaxFill(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+ wwtype_ = des.unsigned_8() == 0 ? wwWARE : wwWORKER;
+ index_ = des.unsigned_32();
+ max_fill_ = des.unsigned_32();
+}
+
+void CmdConstructionsiteInputQueueMaxFill::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_INPUTQUEUE_MAXFILL);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+ ser.unsigned_8(wwtype_ == wwWARE ? 0 : 1);
+ ser.unsigned_32(index_);
+ ser.unsigned_32(max_fill_);
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsiteInputQueueMaxFill = 1;
+
+void CmdConstructionsiteInputQueueMaxFill::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsiteInputQueueMaxFill) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ wwtype_ = fr.unsigned_8() == 0 ? wwWARE : wwWORKER;
+ index_ = fr.unsigned_32();
+ max_fill_ = fr.unsigned_32();
+ } else {
+ throw UnhandledVersionError("CmdConstructionsiteInputQueueMaxFill", packet_version,
+ kCurrentPacketVersionCmdConstructionsiteInputQueueMaxFill);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsiteInputQueueMaxFill: %s", e.what());
+ }
+}
+
+void CmdConstructionsiteInputQueueMaxFill::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsiteInputQueueMaxFill);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+ fw.unsigned_8(wwtype_ == wwWARE ? 0 : 1);
+ fw.unsigned_32(index_);
+ fw.unsigned_32(max_fill_);
+}
+
+/*** struct CmdConstructionsiteEnhance ***/
+CmdConstructionsiteEnhance::CmdConstructionsiteEnhance(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite& cs)
+ : PlayerCommand(time, p), constructionsite_(cs.serial()) {
+}
+
+CmdConstructionsiteEnhance::CmdConstructionsiteEnhance()
+ : PlayerCommand(), constructionsite_(0) {
+}
+
+void CmdConstructionsiteEnhance::execute(Game& game) {
+ if (Player* plr = game.get_player(sender())) {
+ if (upcast(ConstructionSite, cs, game.objects().get_object(constructionsite_))) {
+ if (cs->get_owner() != plr) {
+ log("CmdConstructionsiteEnhance: sender %u, but site owner %u\n", sender(),
+ cs->owner().player_number());
+ return;
+ }
+ cs->enhance(game);
+ }
+ }
+}
+
+CmdConstructionsiteEnhance::CmdConstructionsiteEnhance(StreamRead& des)
+ : PlayerCommand(0, des.unsigned_8()) {
+ constructionsite_ = des.unsigned_32();
+}
+
+void CmdConstructionsiteEnhance::serialize(StreamWrite& ser) {
+ ser.unsigned_8(PLCMD_CONSTRUCTIONSITE_ENHANCE);
+ ser.unsigned_8(sender());
+ ser.unsigned_32(constructionsite_);
+}
+
+constexpr uint8_t kCurrentPacketVersionCmdConstructionsiteEnhance = 1;
+
+void CmdConstructionsiteEnhance::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
+ try {
+ uint8_t packet_version = fr.unsigned_8();
+ if (packet_version == kCurrentPacketVersionCmdConstructionsiteEnhance) {
+ PlayerCommand::read(fr, egbase, mol);
+ constructionsite_ = fr.unsigned_32();
+ } else {
+ throw UnhandledVersionError("CmdConstructionsiteEnhance", packet_version,
+ kCurrentPacketVersionCmdConstructionsiteEnhance);
+ }
+ } catch (const std::exception& e) {
+ throw GameDataError("CmdConstructionsiteEnhance: %s", e.what());
+ }
+}
+
+void CmdConstructionsiteEnhance::write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
+ fw.unsigned_8(kCurrentPacketVersionCmdConstructionsiteEnhance);
+ PlayerCommand::write(fw, egbase, mos);
+ fw.unsigned_32(constructionsite_);
+}
+
} // namespace Widelands
=== modified file 'src/logic/playercommand.h'
--- src/logic/playercommand.h 2019-05-07 12:14:02 +0000
+++ src/logic/playercommand.h 2019-05-14 17:38:23 +0000
@@ -24,6 +24,7 @@
#include "economy/flag.h"
#include "logic/cmd_queue.h"
+#include "logic/map_objects/tribes/constructionsite.h"
#include "logic/map_objects/tribes/militarysite.h"
#include "logic/map_objects/tribes/ship.h"
#include "logic/map_objects/tribes/trainingsite.h"
@@ -823,7 +824,7 @@
Warehouse& wh,
bool isworker,
DescriptionIndex ware,
- Warehouse::StockPolicy policy);
+ StockPolicy policy);
QueueCommandTypes id() const override {
return QueueCommandTypes::kSetStockPolicy;
@@ -844,7 +845,7 @@
Serial warehouse_;
bool isworker_;
DescriptionIndex ware_;
- Warehouse::StockPolicy policy_;
+ StockPolicy policy_;
};
struct CmdProposeTrade : PlayerCommand {
@@ -868,6 +869,225 @@
private:
Trade trade_;
};
+
+struct CmdConstructionsiteSoldierCapacity : PlayerCommand {
+ CmdConstructionsiteSoldierCapacity(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&,
+ uint32_t);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSiteSoldierCapacity;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsiteSoldierCapacity(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsiteSoldierCapacity();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+ uint32_t capacity_;
+};
+
+struct CmdConstructionsitePreferHeroes : PlayerCommand {
+ CmdConstructionsitePreferHeroes(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&,
+ bool);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSitePreferHeroes;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsitePreferHeroes(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsitePreferHeroes();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+ bool heroes_;
+};
+
+struct CmdConstructionsiteLaunchExpedition : PlayerCommand {
+ CmdConstructionsiteLaunchExpedition(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&,
+ bool);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSiteLaunchExpedition;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsiteLaunchExpedition(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsiteLaunchExpedition();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+ bool launch_;
+};
+
+struct CmdConstructionsiteStartStop : PlayerCommand {
+ CmdConstructionsiteStartStop(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&,
+ bool stop);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSiteStartStop;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsiteStartStop(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsiteStartStop();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+ bool stopped_;
+};
+
+struct CmdConstructionsiteStockPolicy : PlayerCommand {
+ CmdConstructionsiteStockPolicy(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&,
+ WareWorker,
+ DescriptionIndex,
+ StockPolicy);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSiteStockPolicy;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsiteStockPolicy(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsiteStockPolicy();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+ WareWorker wwtype_;
+ DescriptionIndex index_;
+ StockPolicy policy_;
+};
+
+struct CmdConstructionsiteInputQueuePriority : PlayerCommand {
+ CmdConstructionsiteInputQueuePriority(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&,
+ WareWorker,
+ DescriptionIndex,
+ int32_t);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSiteInputQueuePriority;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsiteInputQueuePriority(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsiteInputQueuePriority();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+ WareWorker wwtype_;
+ DescriptionIndex index_;
+ int32_t priority_;
+};
+
+struct CmdConstructionsiteInputQueueMaxFill : PlayerCommand {
+ CmdConstructionsiteInputQueueMaxFill(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&,
+ WareWorker,
+ DescriptionIndex,
+ uint32_t);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSiteInputQueueMaxFill;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsiteInputQueueMaxFill(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsiteInputQueueMaxFill();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+ WareWorker wwtype_;
+ DescriptionIndex index_;
+ uint32_t max_fill_;
+};
+
+struct CmdConstructionsiteEnhance : PlayerCommand {
+ CmdConstructionsiteEnhance(uint32_t time,
+ PlayerNumber p,
+ ConstructionSite&);
+
+ QueueCommandTypes id() const override {
+ return QueueCommandTypes::kConstructionSiteEnhance;
+ }
+
+ void execute(Game& game) override;
+
+ // Network (de-)serialization
+ explicit CmdConstructionsiteEnhance(StreamRead& des);
+ void serialize(StreamWrite& ser) override;
+
+ // Savegame functions
+ CmdConstructionsiteEnhance();
+ void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
+ void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
+
+private:
+ Serial constructionsite_;
+};
+
} // namespace Widelands
#endif // end of include guard: WL_LOGIC_PLAYERCOMMAND_H
=== modified file 'src/logic/queue_cmd_factory.cc'
--- src/logic/queue_cmd_factory.cc 2019-02-23 11:00:49 +0000
+++ src/logic/queue_cmd_factory.cc 2019-05-14 17:38:23 +0000
@@ -80,6 +80,22 @@
return *new CmdMilitarySiteSetSoldierPreference();
case QueueCommandTypes::kProposeTrade:
return *new CmdProposeTrade();
+ case QueueCommandTypes::kConstructionSiteSoldierCapacity:
+ return *new CmdConstructionsiteSoldierCapacity();
+ case QueueCommandTypes::kConstructionSitePreferHeroes:
+ return *new CmdConstructionsitePreferHeroes();
+ case QueueCommandTypes::kConstructionSiteLaunchExpedition:
+ return *new CmdConstructionsiteLaunchExpedition();
+ case QueueCommandTypes::kConstructionSiteStockPolicy:
+ return *new CmdConstructionsiteStockPolicy();
+ case QueueCommandTypes::kConstructionSiteInputQueuePriority:
+ return *new CmdConstructionsiteInputQueuePriority();
+ case QueueCommandTypes::kConstructionSiteInputQueueMaxFill:
+ return *new CmdConstructionsiteInputQueueMaxFill();
+ case QueueCommandTypes::kConstructionSiteEnhance:
+ return *new CmdConstructionsiteEnhance();
+ case QueueCommandTypes::kConstructionSiteStartStop:
+ return *new CmdConstructionsiteStartStop();
case QueueCommandTypes::kSinkShip:
return *new CmdShipSink();
case QueueCommandTypes::kShipCancelExpedition:
=== modified file 'src/logic/queue_cmd_ids.h'
--- src/logic/queue_cmd_ids.h 2019-02-23 11:00:49 +0000
+++ src/logic/queue_cmd_ids.h 2019-05-14 17:38:23 +0000
@@ -73,6 +73,15 @@
kMilitarysiteSetSoldierPreference,
kProposeTrade, // 27
+ kConstructionSiteStockPolicy,
+ kConstructionSiteSoldierCapacity,
+ kConstructionSitePreferHeroes,
+ kConstructionSiteLaunchExpedition,
+ kConstructionSiteInputQueuePriority,
+ kConstructionSiteInputQueueMaxFill,
+ kConstructionSiteEnhance,
+ kConstructionSiteStartStop, // 35
+
kSinkShip = 121,
kShipCancelExpedition,
kPortStartExpedition,
=== modified file 'src/map_io/map_buildingdata_packet.cc'
--- src/map_io/map_buildingdata_packet.cc 2019-05-12 10:53:08 +0000
+++ src/map_io/map_buildingdata_packet.cc 2019-05-14 17:38:23 +0000
@@ -60,7 +60,7 @@
// Building type package versions
constexpr uint16_t kCurrentPacketVersionDismantlesite = 1;
-constexpr uint16_t kCurrentPacketVersionConstructionsite = 3;
+constexpr uint16_t kCurrentPacketVersionConstructionsite = 4;
constexpr uint16_t kCurrentPacketPFBuilding = 1;
// Responsible for warehouses and expedition bootstraps
constexpr uint16_t kCurrentPacketVersionWarehouse = 7;
@@ -269,7 +269,7 @@
MapObjectLoader& mol) {
try {
uint16_t const packet_version = fr.unsigned_16();
- if (packet_version >= kCurrentPacketVersionConstructionsite) {
+ if (packet_version >= 3 && packet_version <= kCurrentPacketVersionConstructionsite) {
read_partially_finished_building(constructionsite, fr, game, mol);
for (ConstructionSite::Wares::iterator wares_iter = constructionsite.wares_.begin();
@@ -279,6 +279,18 @@
}
constructionsite.fetchfromflag_ = fr.signed_32();
+
+ if (packet_version >= 4) {
+ const uint32_t intermediates = fr.unsigned_32();
+ for (uint32_t i = 0; i < intermediates; ++i) {
+ constructionsite.info_.intermediates.push_back(game.tribes().get_building_descr(
+ game.tribes().building_index(fr.c_string())));
+ }
+ constructionsite.settings_.reset(BuildingSettings::load(game,
+ constructionsite.owner().tribe(), fr));
+ } else {
+ constructionsite.settings_.reset(nullptr);
+ }
} else {
throw UnhandledVersionError("MapBuildingdataPacket - Constructionsite", packet_version,
kCurrentPacketVersionConstructionsite);
@@ -321,7 +333,7 @@
while (fr.unsigned_8()) {
const DescriptionIndex& id = tribe.ware_index(fr.c_string());
Quantity amount = fr.unsigned_32();
- Warehouse::StockPolicy policy = static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
+ StockPolicy policy = static_cast<StockPolicy>(fr.unsigned_8());
if (game.tribes().ware_exists(id)) {
warehouse.insert_wares(id, amount);
@@ -331,7 +343,7 @@
while (fr.unsigned_8()) {
const DescriptionIndex& id = tribe.worker_index(fr.c_string());
uint32_t amount = fr.unsigned_32();
- Warehouse::StockPolicy policy = static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
+ StockPolicy policy = static_cast<StockPolicy>(fr.unsigned_8());
if (game.tribes().worker_exists(id)) {
warehouse.insert_workers(id, amount);
@@ -961,6 +973,14 @@
write_partially_finished_building(constructionsite, fw, game, mos);
fw.signed_32(constructionsite.fetchfromflag_);
+
+ fw.unsigned_32(constructionsite.info_.intermediates.size());
+ for (const BuildingDescr* d : constructionsite.info_.intermediates) {
+ fw.c_string(d->name().c_str());
+ }
+
+ assert(constructionsite.settings_);
+ constructionsite.settings_->save(game, fw);
}
void MapBuildingdataPacket::write_dismantlesite(const DismantleSite& dms,
=== modified file 'src/notifications/note_ids.h'
--- src/notifications/note_ids.h 2019-02-23 11:00:49 +0000
+++ src/notifications/note_ids.h 2019-05-14 17:38:23 +0000
@@ -29,6 +29,7 @@
ChatMessage,
LogMessage,
Immovable,
+ ConstructionsiteEnhanced,
FieldPossession,
FieldTerrainChanged,
ProductionSiteOutOfResources,
=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc 2019-05-04 10:47:44 +0000
+++ src/scripting/lua_map.cc 2019-05-14 17:38:23 +0000
@@ -4871,39 +4871,39 @@
}
// Transforms the given warehouse policy to a string which is used by the lua code
-inline void wh_policy_to_string(lua_State* L, Warehouse::StockPolicy p) {
+inline void wh_policy_to_string(lua_State* L, StockPolicy p) {
switch (p) {
- case Warehouse::StockPolicy::kNormal:
+ case StockPolicy::kNormal:
lua_pushstring(L, "normal");
break;
- case Warehouse::StockPolicy::kPrefer:
+ case StockPolicy::kPrefer:
lua_pushstring(L, "prefer");
break;
- case Warehouse::StockPolicy::kDontStock:
+ case StockPolicy::kDontStock:
lua_pushstring(L, "dontstock");
break;
- case Warehouse::StockPolicy::kRemove:
+ case StockPolicy::kRemove:
lua_pushstring(L, "remove");
break;
}
}
// Transforms the given string from the lua code to a warehouse policy
-inline Warehouse::StockPolicy string_to_wh_policy(lua_State* L, uint32_t index) {
+inline StockPolicy string_to_wh_policy(lua_State* L, uint32_t index) {
std::string str = luaL_checkstring(L, index);
if (str == "normal")
- return Warehouse::StockPolicy::kNormal;
+ return StockPolicy::kNormal;
else if (str == "prefer")
- return Warehouse::StockPolicy::kPrefer;
+ return StockPolicy::kPrefer;
else if (str == "dontstock")
- return Warehouse::StockPolicy::kDontStock;
+ return StockPolicy::kDontStock;
else if (str == "remove")
- return Warehouse::StockPolicy::kRemove;
+ return StockPolicy::kRemove;
else
report_error(L, "<%s> is no valid warehouse policy!", str.c_str());
}
inline bool
-do_set_ware_policy(Warehouse* wh, const DescriptionIndex idx, const Warehouse::StockPolicy p) {
+do_set_ware_policy(Warehouse* wh, const DescriptionIndex idx, const StockPolicy p) {
wh->set_ware_policy(idx, p);
return true;
}
@@ -4913,7 +4913,7 @@
* If the no ware with the given name exists for the tribe of the warehouse, return false.
*/
inline bool
-do_set_ware_policy(Warehouse* wh, const std::string& name, const Warehouse::StockPolicy p) {
+do_set_ware_policy(Warehouse* wh, const std::string& name, const StockPolicy p) {
const TribeDescr& tribe = wh->owner().tribe();
DescriptionIndex idx = tribe.ware_index(name);
if (!tribe.has_ware(idx)) {
@@ -4923,7 +4923,7 @@
}
inline bool
-do_set_worker_policy(Warehouse* wh, const DescriptionIndex idx, const Warehouse::StockPolicy p) {
+do_set_worker_policy(Warehouse* wh, const DescriptionIndex idx, const StockPolicy p) {
const TribeDescr& tribe = wh->owner().tribe();
// If the worker does not cost anything, ignore it
// Otherwise, an unlimited stream of carriers might leave the warehouse
@@ -4942,7 +4942,7 @@
* If no worker with the given name exists for the tribe of the warehouse, return false.
*/
inline bool
-do_set_worker_policy(Warehouse* wh, const std::string& name, const Warehouse::StockPolicy p) {
+do_set_worker_policy(Warehouse* wh, const std::string& name, const StockPolicy p) {
const TribeDescr& tribe = wh->owner().tribe();
DescriptionIndex idx = tribe.worker_index(name);
if (!tribe.has_worker(idx)) {
@@ -4972,7 +4972,7 @@
report_error(L, "Wrong number of arguments to set_warehouse_policies!");
Warehouse* wh = get(L, get_egbase(L));
- Warehouse::StockPolicy p = string_to_wh_policy(L, -1);
+ StockPolicy p = string_to_wh_policy(L, -1);
lua_pop(L, 1);
const TribeDescr& tribe = wh->owner().tribe();
=== modified file 'src/wui/actionconfirm.cc'
--- src/wui/actionconfirm.cc 2019-02-23 11:00:49 +0000
+++ src/wui/actionconfirm.cc 2019-05-14 17:38:23 +0000
@@ -92,7 +92,8 @@
struct EnhanceConfirm : public ActionConfirm {
EnhanceConfirm(InteractivePlayer& parent,
Widelands::Building& building,
- const Widelands::DescriptionIndex& id);
+ const Widelands::DescriptionIndex& id,
+ bool still_under_construction);
void think() override;
void ok() override;
@@ -100,6 +101,7 @@
private:
// Do not make this a reference - it is a stack variable in the caller
const Widelands::DescriptionIndex id_;
+ bool still_under_construction_;
};
/**
@@ -259,7 +261,8 @@
*/
EnhanceConfirm::EnhanceConfirm(InteractivePlayer& parent,
Widelands::Building& building,
- const Widelands::DescriptionIndex& id)
+ const Widelands::DescriptionIndex& id,
+ bool still_under_construction)
: ActionConfirm(
parent,
_("Enhance building?"),
@@ -270,7 +273,8 @@
.str() :
_("Do you really want to enhance this building?"),
building),
- id_(id) {
+ id_(id),
+ still_under_construction_(still_under_construction) {
// Nothing special to do
}
@@ -284,7 +288,7 @@
upcast(Widelands::Building, building, object_.get(egbase));
if (!building || !iaplayer().can_act(building->owner().player_number()) ||
- !(building->get_playercaps() & Widelands::Building::PCap_Enhancable))
+ !(still_under_construction_ || (building->get_playercaps() & Widelands::Building::PCap_Enhancable)))
die();
}
@@ -293,11 +297,18 @@
*/
void EnhanceConfirm::ok() {
Widelands::Game& game = iaplayer().game();
- upcast(Widelands::Building, building, object_.get(game));
- if (building && iaplayer().can_act(building->owner().player_number()) &&
- (building->get_playercaps() & Widelands::Building::PCap_Enhancable)) {
- game.send_player_enhance_building(*building, id_);
+ if (still_under_construction_) {
+ upcast(Widelands::ConstructionSite, cs, object_.get(game));
+ if (cs && iaplayer().can_act(cs->owner().player_number())) {
+ game.send_player_constructionsite_enhance(*cs);
+ }
+ } else {
+ upcast(Widelands::Building, building, object_.get(game));
+ if (building && iaplayer().can_act(building->owner().player_number()) &&
+ (building->get_playercaps() & Widelands::Building::PCap_Enhancable)) {
+ game.send_player_enhance_building(*building, id_);
+ }
}
die();
@@ -419,8 +430,9 @@
*/
void show_enhance_confirm(InteractivePlayer& player,
Widelands::Building& building,
- const Widelands::DescriptionIndex& id) {
- new EnhanceConfirm(player, building, id);
+ const Widelands::DescriptionIndex& id,
+ bool constructionsite) {
+ new EnhanceConfirm(player, building, id, constructionsite);
}
/**
=== modified file 'src/wui/actionconfirm.h'
--- src/wui/actionconfirm.h 2019-02-23 11:00:49 +0000
+++ src/wui/actionconfirm.h 2019-05-14 17:38:23 +0000
@@ -39,7 +39,8 @@
void show_enhance_confirm(InteractivePlayer& player,
Widelands::Building& building,
- const Widelands::DescriptionIndex& id);
+ const Widelands::DescriptionIndex& id,
+ bool still_under_construction = false);
// Ship confirm windows
void show_ship_sink_confirm(InteractivePlayer& player, Widelands::Ship& ship);
=== modified file 'src/wui/constructionsitewindow.cc'
--- src/wui/constructionsitewindow.cc 2019-02-23 11:00:49 +0000
+++ src/wui/constructionsitewindow.cc 2019-05-14 17:38:23 +0000
@@ -22,9 +22,256 @@
#include <boost/format.hpp>
#include "graphic/graphic.h"
+#include "wui/actionconfirm.h"
#include "wui/inputqueuedisplay.h"
+#include "wui/interactive_player.h"
static const char pic_tab_wares[] = "images/wui/buildings/menu_tab_wares.png";
+static const char pic_tab_workers[] = "images/wui/buildings/menu_tab_workers.png";
+static const char pic_tab_settings[] = "images/wui/menus/menu_stock.png";
+static const char pic_max_fill_indicator[] = "images/wui/buildings/max_fill_indicator.png";
+static const char pic_priority_low[] = "images/wui/buildings/low_priority_button.png";
+static const char pic_priority_normal[] = "images/wui/buildings/normal_priority_button.png";
+static const char pic_priority_high[] = "images/wui/buildings/high_priority_button.png";
+static const char pic_stock_policy_prefer[] = "images/wui/buildings/stock_policy_prefer.png";
+static const char pic_stock_policy_dontstock[] = "images/wui/buildings/stock_policy_dontstock.png";
+static const char pic_stock_policy_remove[] = "images/wui/buildings/stock_policy_remove.png";
+static const char pic_stock_policy_button_normal[] = "images/wui/buildings/stock_policy_button_normal.png";
+static const char pic_stock_policy_button_prefer[] = "images/wui/buildings/stock_policy_button_prefer.png";
+static const char pic_stock_policy_button_dontstock[] = "images/wui/buildings/stock_policy_button_dontstock.png";
+static const char pic_stock_policy_button_remove[] = "images/wui/buildings/stock_policy_button_remove.png";
+
+constexpr uint32_t kFakeInputQueueWareWidth = WARE_MENU_PIC_WIDTH + 2;
+constexpr uint32_t kFakeInputQueueWareHeight = WARE_MENU_PIC_HEIGHT + 4;
+
+ConstructionSiteWindow::FakeInputQueue::FakeInputQueue(Panel* parent,
+ int32_t x,
+ int32_t y,
+ bool can_act,
+ Widelands::ConstructionSite& cs,
+ Widelands::WareWorker ww,
+ Widelands::DescriptionIndex di)
+ : UI::Box(parent, x, y, UI::Box::Horizontal),
+ constructionsite_(cs),
+ settings_(*dynamic_cast<Widelands::ProductionsiteSettings*>(cs.get_settings())),
+ type_(ww),
+ index_(di),
+ max_fill_indicator_(g_gr->images().get(pic_max_fill_indicator)) {
+ max_fill_ = get_settings().max_fill;
+
+ const Widelands::Tribes& tribes = cs.owner().egbase().tribes();
+ const Widelands::MapObjectDescr* w_descr = nullptr;
+ if (type_ == Widelands::wwWARE) {
+ w_descr = tribes.get_ware_descr(index_);
+ } else {
+ w_descr = tribes.get_worker_descr(index_);
+ }
+ assert(w_descr);
+ set_tooltip(w_descr->descname());
+ icon_ = w_descr->icon();
+
+ UI::Button& decrease = *new UI::Button(
+ this, "decrease_max_fill", 0, 0, kFakeInputQueueWareWidth, kFakeInputQueueWareHeight,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_left.png"),
+ _("Decrease the number of items to initially store here"));
+ UI::Button& increase = *new UI::Button(
+ this, "increase_max_fill", 0, 0, kFakeInputQueueWareWidth, kFakeInputQueueWareHeight,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_right.png"),
+ _("Increase the number of items to initially store here"));
+ decrease.sigclicked.connect(boost::bind(&ConstructionSiteWindow::FakeInputQueue::change_fill, this, true));
+ increase.sigclicked.connect(boost::bind(&ConstructionSiteWindow::FakeInputQueue::change_fill, this, false));
+ decrease.set_repeating(true);
+ increase.set_repeating(true);
+ add(&decrease);
+ add_space(kFakeInputQueueWareWidth * max_fill_ + 8);
+ add(&increase);
+ if (type_ == Widelands::wwWARE) {
+ priority_low_ = new UI::Button(this, "priority_low", 0, 0,
+ kFakeInputQueueWareWidth, kFakeInputQueueWareHeight,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_priority_low),
+ _("Lowest priority"));
+ priority_normal_ = new UI::Button(this, "priority_normal", 0, 0,
+ kFakeInputQueueWareWidth, kFakeInputQueueWareHeight,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_priority_normal),
+ _("Normal priority"));
+ priority_high_ = new UI::Button(this, "priority_high", 0, 0,
+ kFakeInputQueueWareWidth, kFakeInputQueueWareHeight,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_priority_high),
+ _("Highest priority"));
+ add_space(8);
+ add(priority_low_, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+ add(priority_normal_, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+ add(priority_high_, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+ if (can_act) {
+ priority_low_->sigclicked.connect(boost::bind(&ConstructionSiteWindow::FakeInputQueue::change_priority,
+ this, Widelands::kPriorityLow));
+ priority_normal_->sigclicked.connect(boost::bind(&ConstructionSiteWindow::FakeInputQueue::change_priority,
+ this, Widelands::kPriorityNormal));
+ priority_high_->sigclicked.connect(boost::bind(&ConstructionSiteWindow::FakeInputQueue::change_priority,
+ this, Widelands::kPriorityHigh));
+ }
+ }
+ decrease.set_enabled(can_act);
+ increase.set_enabled(can_act);
+}
+
+void ConstructionSiteWindow::FakeInputQueue::change_priority(int32_t p) {
+ Widelands::Game& game = dynamic_cast<Widelands::Game&>(constructionsite_.get_owner()->egbase());
+ if (SDL_GetModState() & KMOD_CTRL) {
+ for (const auto& pair : settings_.ware_queues) {
+ game.send_player_constructionsite_input_queue_priority(constructionsite_,
+ Widelands::wwWARE, pair.first, p);
+ }
+ for (const auto& pair : settings_.worker_queues) {
+ game.send_player_constructionsite_input_queue_priority(constructionsite_,
+ Widelands::wwWORKER, pair.first, p);
+ }
+ } else {
+ game.send_player_constructionsite_input_queue_priority(constructionsite_, type_, index_, p);
+ }
+}
+
+void ConstructionSiteWindow::FakeInputQueue::change_fill(bool lower) {
+ Widelands::Game& game = dynamic_cast<Widelands::Game&>(constructionsite_.get_owner()->egbase());
+ if (SDL_GetModState() & KMOD_SHIFT) {
+ for (const auto& pair : settings_.ware_queues) {
+ if (SDL_GetModState() & KMOD_CTRL) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_,
+ Widelands::wwWARE, pair.first, lower ? 0 : pair.second.max_fill);
+ } else if (lower && pair.second.desired_fill > 0) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_,
+ Widelands::wwWARE, pair.first, pair.second.desired_fill - 1);
+ } else if (!lower && pair.second.desired_fill < pair.second.max_fill) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_,
+ Widelands::wwWARE, pair.first, pair.second.desired_fill + 1);
+ }
+ }
+ for (const auto& pair : settings_.worker_queues) {
+ if (SDL_GetModState() & KMOD_CTRL) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_,
+ Widelands::wwWORKER, pair.first, lower ? 0 : pair.second.max_fill);
+ } else if (lower && pair.second.desired_fill > 0) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_,
+ Widelands::wwWORKER, pair.first, pair.second.desired_fill - 1);
+ } else if (!lower && pair.second.desired_fill < pair.second.max_fill) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_,
+ Widelands::wwWORKER, pair.first, pair.second.desired_fill + 1);
+ }
+ }
+ } else {
+ const uint32_t fill = get_settings().desired_fill;
+ if (SDL_GetModState() & KMOD_CTRL) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_, type_, index_,
+ lower ? 0 : max_fill_);
+ } else if (lower && fill > 0) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_, type_, index_, fill - 1);
+ } else if (!lower && fill < max_fill_) {
+ game.send_player_constructionsite_input_queue_max_fill(constructionsite_, type_, index_, fill + 1);
+ }
+ }
+}
+
+const Widelands::ProductionsiteSettings::InputQueueSetting& ConstructionSiteWindow::FakeInputQueue::get_settings() const {
+ switch (type_) {
+ case Widelands::wwWARE:
+ for (const auto& pair : settings_.ware_queues) {
+ if (pair.first == index_) {
+ return pair.second;
+ }
+ }
+ NEVER_HERE();
+ case Widelands::wwWORKER:
+ for (const auto& pair : settings_.worker_queues) {
+ if (pair.first == index_) {
+ return pair.second;
+ }
+ }
+ NEVER_HERE();
+ default:
+ NEVER_HERE();
+ }
+}
+
+void ConstructionSiteWindow::FakeInputQueue::think() {
+ UI::Box::think();
+ if (priority_normal_) {
+ assert(priority_high_);
+ assert(priority_low_);
+ const int32_t priority = get_settings().priority;
+ priority_high_->set_enabled(priority != Widelands::kPriorityHigh);
+ priority_normal_->set_enabled(priority != Widelands::kPriorityNormal);
+ priority_low_->set_enabled(priority != Widelands::kPriorityLow);
+ }
+#ifndef NDEBUG
+ else {
+ assert(!priority_high_);
+ assert(!priority_low_);
+ }
+#endif
+}
+
+void ConstructionSiteWindow::FakeInputQueue::draw(RenderTarget& dst) {
+ UI::Box::draw(dst);
+
+ Vector2i point = Vector2i::zero();
+ point.x = kFakeInputQueueWareWidth + 4;
+ point.y = (kFakeInputQueueWareHeight - icon_->height()) / 2;
+
+ const uint32_t fill = get_settings().desired_fill;
+ uint32_t draw_yes = fill;
+ uint32_t draw_no = max_fill_ - draw_yes;
+ for (; draw_yes; --draw_yes, point.x += kFakeInputQueueWareWidth) {
+ dst.blitrect(Vector2i(point.x, point.y), icon_, Recti(0, 0, icon_->width(), icon_->height()),
+ BlendMode::UseAlpha);
+ }
+ for (; draw_no; --draw_no, point.x += kFakeInputQueueWareWidth) {
+ dst.blitrect_scale_monochrome(Rectf(point.x, point.y, icon_->width(), icon_->height()), icon_,
+ Recti(0, 0, icon_->width(), icon_->height()),
+ RGBAColor(191, 191, 191, 127));
+ }
+
+ point.x = 4 + kFakeInputQueueWareWidth + (fill * kFakeInputQueueWareWidth) - max_fill_indicator_->width() / 2;
+ // Unsigned arithmetic...
+ point.y = kFakeInputQueueWareHeight;
+ point.y -= max_fill_indicator_->height();
+ point.y /= 2;
+ dst.blit(point, max_fill_indicator_);
+}
+
+ConstructionSiteWindow::FakeWaresDisplay::FakeWaresDisplay(UI::Panel* parent,
+ bool can_act,
+ Widelands::ConstructionSite& cs,
+ Widelands::WareWorker type)
+ : WaresDisplay(parent, 0, 0, cs.owner().tribe(), type, can_act),
+ settings_(*dynamic_cast<Widelands::WarehouseSettings*>(cs.get_settings())) {
+}
+
+void ConstructionSiteWindow::FakeWaresDisplay::draw_ware(RenderTarget& dst, Widelands::DescriptionIndex ware) {
+ WaresDisplay::draw_ware(dst, ware);
+
+ const auto& map = get_type() == Widelands::wwWARE ? settings_.ware_preferences : settings_.worker_preferences;
+ const auto it = map.find(ware);
+ if (it == map.end()) {
+ return;
+ }
+ const Image* pic = nullptr;
+ switch (it->second) {
+ case Widelands::StockPolicy::kPrefer:
+ pic = g_gr->images().get(pic_stock_policy_prefer);
+ break;
+ case Widelands::StockPolicy::kDontStock:
+ pic = g_gr->images().get(pic_stock_policy_dontstock);
+ break;
+ case Widelands::StockPolicy::kRemove:
+ pic = g_gr->images().get(pic_stock_policy_remove);
+ break;
+ case Widelands::StockPolicy::kNormal:
+ // No icon for the normal policy
+ return;
+ }
+ assert(pic);
+ dst.blit(ware_position(ware), pic);
+}
ConstructionSiteWindow::ConstructionSiteWindow(InteractiveGameBase& parent,
UI::UniqueWindow::Registry& reg,
@@ -33,7 +280,19 @@
bool workarea_preview_wanted)
: BuildingWindow(parent, reg, cs, cs.building(), avoid_fastclick),
construction_site_(&cs),
- progress_(nullptr) {
+ progress_(nullptr),
+ cs_enhance_(nullptr),
+ cs_launch_expedition_(nullptr),
+ cs_prefer_heroes_(nullptr),
+ cs_soldier_capacity_(nullptr),
+ cs_stopped_(nullptr),
+ cs_warehouse_wares_(nullptr),
+ cs_warehouse_workers_(nullptr),
+ cs_warehouse_stock_policy_normal_(nullptr),
+ cs_warehouse_stock_policy_prefer_(nullptr),
+ cs_warehouse_stock_policy_dontstock_(nullptr),
+ cs_warehouse_stock_policy_remove_(nullptr),
+ cs_warehouse_tabs_(nullptr) {
init(avoid_fastclick, workarea_preview_wanted);
}
@@ -59,10 +318,182 @@
get_tabs()->add("wares", g_gr->images().get(pic_tab_wares), &box, _("Building materials"));
+ if (construction_site->get_settings()) {
+ const bool can_act = igbase()->can_act(construction_site->owner().player_number());
+ // Create the settings. Since we don't access an actual building, we create
+ // a simplified faksimile of the later building window that contains only
+ // the relevant options.
+ UI::Box& settings_box = *new UI::Box(get_tabs(), 0, 0, UI::Box::Vertical);
+ if (upcast(Widelands::ProductionsiteSettings, ps, construction_site->get_settings())) {
+ for (const auto& pair : ps->ware_queues) {
+ FakeInputQueue* queue = new FakeInputQueue(&settings_box, 0, 0, can_act,
+ *construction_site, Widelands::wwWARE, pair.first);
+ settings_box.add(queue);
+ settings_box.add_space(8);
+ cs_ware_queues_.push_back(queue);
+ }
+ for (const auto& pair : ps->worker_queues) {
+ FakeInputQueue* queue = new FakeInputQueue(&settings_box, 0, 0, can_act,
+ *construction_site, Widelands::wwWORKER, pair.first);
+ settings_box.add(queue);
+ settings_box.add_space(8);
+ cs_ware_queues_.push_back(queue);
+ }
+ if (upcast(Widelands::TrainingsiteSettings, ts, ps)) {
+ cs_soldier_capacity_ = new UI::SpinBox(&settings_box, 0, 0, 300, 100,
+ ts->desired_capacity, 0, ts->max_capacity, UI::PanelStyle::kWui, _("Soldier capacity:"));
+ settings_box.add(cs_soldier_capacity_);
+ settings_box.add_space(8);
+ cs_soldier_capacity_->changed.connect([this]() {
+ igbase()->game().send_player_constructionsite_soldier_capacity(
+ *construction_site_.get(igbase()->egbase()), cs_soldier_capacity_->get_value());
+ });
+ for (UI::Button* b : cs_soldier_capacity_->get_buttons()) {
+ b->set_enabled(can_act);
+ }
+ }
+ cs_stopped_ = new UI::Checkbox(&settings_box, Vector2i::zero(),
+ _("Stopped"),
+ _("Stop this building’s work after completion"));
+ cs_stopped_->changed.connect([this]() {
+ igbase()->game().send_player_constructionsite_startstop(
+ *construction_site_.get(igbase()->egbase()), cs_stopped_->get_state());
+ });
+ settings_box.add(cs_stopped_, UI::Box::Resizing::kFullSize);
+ settings_box.add_space(8);
+ cs_stopped_->set_enabled(can_act);
+ } else if (upcast(Widelands::MilitarysiteSettings, ms, construction_site->get_settings())) {
+ cs_soldier_capacity_ = new UI::SpinBox(&settings_box, 0, 0, 300, 100,
+ ms->desired_capacity, 1, ms->max_capacity, UI::PanelStyle::kWui, _("Soldier capacity:"));
+ settings_box.add(cs_soldier_capacity_);
+ settings_box.add_space(8);
+ cs_soldier_capacity_->changed.connect([this]() {
+ igbase()->game().send_player_constructionsite_soldier_capacity(*construction_site_.get(igbase()->egbase()),
+ cs_soldier_capacity_->get_value());
+ });
+ for (UI::Button* b : cs_soldier_capacity_->get_buttons()) {
+ b->set_enabled(can_act);
+ }
+ cs_prefer_heroes_ = new UI::Checkbox(&settings_box, Vector2i::zero(),
+ _("Prefer heroes"),
+ _("Prefer heroes over rookies"));
+ cs_prefer_heroes_->changed.connect([this]() {
+ igbase()->game().send_player_constructionsite_prefer_heroes(*construction_site_.get(igbase()->egbase()),
+ cs_prefer_heroes_->get_state());
+ });
+ cs_prefer_heroes_->set_enabled(can_act);
+ settings_box.add(cs_prefer_heroes_, UI::Box::Resizing::kFullSize);
+ settings_box.add_space(8);
+ } else if (upcast(Widelands::WarehouseSettings, ws, construction_site->get_settings())) {
+ cs_warehouse_tabs_ = new UI::TabPanel(&settings_box, UI::TabPanelStyle::kWuiLight);
+ cs_warehouse_wares_ = new FakeWaresDisplay(
+ cs_warehouse_tabs_, can_act, *construction_site, Widelands::wwWARE);
+ cs_warehouse_workers_ = new FakeWaresDisplay(
+ cs_warehouse_tabs_, can_act, *construction_site, Widelands::wwWORKER);
+ cs_warehouse_tabs_->add("tab_wares", g_gr->images().get(pic_tab_wares),
+ cs_warehouse_wares_, _("Wares"));
+ cs_warehouse_tabs_->add("tab_workers", g_gr->images().get(pic_tab_workers),
+ cs_warehouse_workers_, _("Workers"));
+ settings_box.add(cs_warehouse_tabs_, UI::Box::Resizing::kFullSize);
+ settings_box.add_space(8);
+ UI::Box& buttonsbox = *new UI::Box(&settings_box, 0, 0, UI::Box::Horizontal);
+ settings_box.add(&buttonsbox, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+ settings_box.add_space(8);
+ cs_warehouse_stock_policy_normal_ = new UI::Button(&buttonsbox, "stock_policy_normal", 0, 0, 34, 34,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_normal),
+ _("Normal policy"));
+ cs_warehouse_stock_policy_prefer_ = new UI::Button(&buttonsbox, "stock_policy_prefer", 0, 0, 34, 34,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_prefer),
+ _("Preferably store selected wares here"));
+ cs_warehouse_stock_policy_dontstock_ = new UI::Button(&buttonsbox, "stock_policy_dontstock", 0, 0, 34, 34,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_dontstock),
+ _("Do not store selected wares here"));
+ cs_warehouse_stock_policy_remove_ = new UI::Button(&buttonsbox, "stock_policy_remove", 0, 0, 34, 34,
+ UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_remove),
+ _("Remove selected wares from here"));
+ cs_warehouse_stock_policy_remove_->sigclicked.connect(
+ boost::bind(&ConstructionSiteWindow::change_policy, this, Widelands::StockPolicy::kRemove));
+ cs_warehouse_stock_policy_dontstock_->sigclicked.connect(
+ boost::bind(&ConstructionSiteWindow::change_policy, this, Widelands::StockPolicy::kDontStock));
+ cs_warehouse_stock_policy_prefer_->sigclicked.connect(
+ boost::bind(&ConstructionSiteWindow::change_policy, this, Widelands::StockPolicy::kPrefer));
+ cs_warehouse_stock_policy_normal_->sigclicked.connect(
+ boost::bind(&ConstructionSiteWindow::change_policy, this, Widelands::StockPolicy::kNormal));
+ buttonsbox.add(cs_warehouse_stock_policy_normal_);
+ buttonsbox.add_space(8);
+ buttonsbox.add(cs_warehouse_stock_policy_prefer_);
+ buttonsbox.add_space(8);
+ buttonsbox.add(cs_warehouse_stock_policy_dontstock_);
+ buttonsbox.add_space(8);
+ buttonsbox.add(cs_warehouse_stock_policy_remove_);
+ if (construction_site->get_info().becomes->get_isport()) {
+ cs_launch_expedition_ = new UI::Checkbox(&settings_box, Vector2i::zero(),
+ _("Launch expedition"),
+ _("Start an expedition from this port after completion"));
+ cs_launch_expedition_->changed.connect([this]() {
+ igbase()->game().send_player_constructionsite_launch_expedition(
+ *construction_site_.get(igbase()->egbase()), cs_launch_expedition_->get_state());
+ });
+ settings_box.add(cs_launch_expedition_, UI::Box::Resizing::kFullSize);
+ settings_box.add_space(8);
+ cs_launch_expedition_->set_enabled(can_act);
+ }
+ } else {
+ NEVER_HERE();
+ }
+
+ if (can_act && construction_site->get_info().becomes->enhancement() != Widelands::INVALID_INDEX) {
+ const Widelands::BuildingDescr& building_descr = *igbase()->egbase().tribes().get_building_descr(
+ construction_site->get_info().becomes->enhancement());
+ std::string enhance_tooltip =
+ (boost::format(_("Enhance to %s")) % building_descr.descname().c_str()).str() +
+ "<br><font size=11>" + _("Construction costs:") + "</font><br>" +
+ waremap_to_richtext(construction_site->owner().tribe(), building_descr.enhancement_cost());
+ cs_enhance_ = new UI::Button(&settings_box, "enhance", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu,
+ building_descr.icon(), enhance_tooltip);
+ cs_enhance_->sigclicked.connect([this, construction_site] {
+ if (SDL_GetModState() & KMOD_CTRL) {
+ igbase()->game().send_player_constructionsite_enhance(*construction_site);
+ } else {
+ show_enhance_confirm(dynamic_cast<InteractivePlayer&>(*igbase()),
+ *construction_site, construction_site->get_info().becomes->enhancement(), true);
+ }
+ });
+ settings_box.add(cs_enhance_, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+ settings_box.add_space(8);
+ }
+ if (settings_box.get_nritems()) {
+ get_tabs()->add("settings", g_gr->images().get(pic_tab_settings),
+ &settings_box, _("Settings to apply after construction"));
+ }
+ }
+
set_title((boost::format("(%s)") % construction_site->building().descname()).str());
think();
}
+void ConstructionSiteWindow::change_policy(Widelands::StockPolicy p) {
+ Widelands::ConstructionSite* construction_site = construction_site_.get(igbase()->egbase());
+ assert(construction_site);
+ upcast(Widelands::WarehouseSettings, ws, construction_site->get_settings());
+ assert(ws);
+ if (cs_warehouse_tabs_->active() == 0) {
+ for (const auto& pair : ws->ware_preferences) {
+ if (cs_warehouse_wares_->ware_selected(pair.first)) {
+ igbase()->game().send_player_constructionsite_stock_policy(*construction_site,
+ Widelands::wwWARE, pair.first, p);
+ }
+ }
+ } else {
+ for (const auto& pair : ws->worker_preferences) {
+ if (cs_warehouse_workers_->ware_selected(pair.first)) {
+ igbase()->game().send_player_constructionsite_stock_policy(*construction_site,
+ Widelands::wwWORKER, pair.first, p);
+ }
+ }
+ }
+}
+
/*
===============
Make sure the window is redrawn when necessary.
@@ -77,5 +508,30 @@
if (construction_site == nullptr) {
return;
}
+
progress_->set_state(construction_site->get_built_per64k());
+
+ // FakeInputQueue and FakeWaresDisplay update themselves – we need to refresh the other settings
+ if (upcast(Widelands::ProductionsiteSettings, ps, construction_site->get_settings())) {
+ assert(cs_stopped_);
+ cs_stopped_->set_state(ps->stopped);
+ }
+ if (upcast(Widelands::TrainingsiteSettings, ts, construction_site->get_settings())) {
+ assert(cs_soldier_capacity_);
+ cs_soldier_capacity_->set_value(ts->desired_capacity);
+ } else if (upcast(Widelands::MilitarysiteSettings, ms, construction_site->get_settings())) {
+ assert(cs_soldier_capacity_);
+ assert(cs_prefer_heroes_);
+ cs_soldier_capacity_->set_value(ms->desired_capacity);
+ cs_prefer_heroes_->set_state(ms->prefer_heroes);
+ } else if (upcast(Widelands::WarehouseSettings, ws, construction_site->get_settings())) {
+ if (cs_launch_expedition_) {
+ cs_launch_expedition_->set_state(ws->launch_expedition);
+ }
+#ifndef NDEBUG
+ else {
+ assert(!ws->launch_expedition);
+ }
+#endif
+ }
}
=== modified file 'src/wui/constructionsitewindow.h'
--- src/wui/constructionsitewindow.h 2019-02-23 11:00:49 +0000
+++ src/wui/constructionsitewindow.h 2019-05-14 17:38:23 +0000
@@ -20,8 +20,14 @@
#ifndef WL_WUI_CONSTRUCTIONSITEWINDOW_H
#define WL_WUI_CONSTRUCTIONSITEWINDOW_H
+#include <vector>
+
#include "logic/map_objects/tribes/constructionsite.h"
+#include "ui_basic/button.h"
+#include "ui_basic/checkbox.h"
#include "ui_basic/progressbar.h"
+#include "ui_basic/spinbox.h"
+#include "ui_basic/tabpanel.h"
#include "wui/buildingwindow.h"
/**
@@ -40,8 +46,72 @@
void init(bool avoid_fastclick, bool workarea_preview_wanted) override;
private:
+ struct FakeInputQueue : UI::Box {
+ FakeInputQueue(Panel* parent,
+ int32_t x,
+ int32_t y,
+ bool can_act,
+ Widelands::ConstructionSite& cs,
+ Widelands::WareWorker ww,
+ Widelands::DescriptionIndex di);
+
+ void draw(RenderTarget& dst) override;
+ void think() override;
+
+ const Widelands::ProductionsiteSettings::InputQueueSetting& get_settings() const;
+
+ private:
+ Widelands::ConstructionSite& constructionsite_;
+ Widelands::ProductionsiteSettings& settings_;
+ Widelands::WareWorker type_;
+ Widelands::DescriptionIndex index_;
+
+ void change_fill(bool);
+ void change_priority(int32_t);
+
+ uint32_t max_fill_;
+ const Image* icon_;
+ const Image* max_fill_indicator_;
+
+ UI::Button* priority_high_;
+ UI::Button* priority_normal_;
+ UI::Button* priority_low_;
+ };
+
+ class FakeWaresDisplay : public WaresDisplay {
+ public:
+ FakeWaresDisplay(UI::Panel* parent,
+ bool can_act,
+ Widelands::ConstructionSite& cs,
+ Widelands::WareWorker type);
+
+ protected:
+ void draw_ware(RenderTarget& dst, Widelands::DescriptionIndex ware) override;
+
+ private:
+ Widelands::WarehouseSettings& settings_;
+ };
+
Widelands::OPtr<Widelands::ConstructionSite> construction_site_;
UI::ProgressBar* progress_;
+
+ // BuildingSettings-related UI elements
+ UI::Button* cs_enhance_;
+ UI::Checkbox* cs_launch_expedition_;
+ UI::Checkbox* cs_prefer_heroes_;
+ UI::SpinBox* cs_soldier_capacity_;
+ std::vector<FakeInputQueue*> cs_ware_queues_;
+ std::vector<FakeInputQueue*> cs_worker_queues_;
+ UI::Checkbox* cs_stopped_;
+ FakeWaresDisplay* cs_warehouse_wares_;
+ FakeWaresDisplay* cs_warehouse_workers_;
+ UI::Button* cs_warehouse_stock_policy_normal_;
+ UI::Button* cs_warehouse_stock_policy_prefer_;
+ UI::Button* cs_warehouse_stock_policy_dontstock_;
+ UI::Button* cs_warehouse_stock_policy_remove_;
+ UI::TabPanel* cs_warehouse_tabs_;
+ void change_policy(Widelands::StockPolicy);
+
DISALLOW_COPY_AND_ASSIGN(ConstructionSiteWindow);
};
=== modified file 'src/wui/inputqueuedisplay.cc'
--- src/wui/inputqueuedisplay.cc 2019-04-25 06:40:24 +0000
+++ src/wui/inputqueuedisplay.cc 2019-05-14 17:38:23 +0000
@@ -205,13 +205,13 @@
int32_t priority = building_.get_priority(type_, index_, false);
switch (priority) {
- case HIGH_PRIORITY:
+ case Widelands::kPriorityHigh:
priority_radiogroup_->set_state(0);
break;
- case DEFAULT_PRIORITY:
+ case Widelands::kPriorityNormal:
priority_radiogroup_->set_state(1);
break;
- case LOW_PRIORITY:
+ case Widelands::kPriorityLow:
priority_radiogroup_->set_state(2);
break;
default:
@@ -294,13 +294,13 @@
switch (state) {
case 0:
- priority = HIGH_PRIORITY;
+ priority = Widelands::kPriorityHigh;
break;
case 1:
- priority = DEFAULT_PRIORITY;
+ priority = Widelands::kPriorityNormal;
break;
case 2:
- priority = LOW_PRIORITY;
+ priority = Widelands::kPriorityLow;
break;
default:
return;
=== modified file 'src/wui/warehousewindow.cc'
--- src/wui/warehousewindow.cc 2019-02-23 11:00:49 +0000
+++ src/wui/warehousewindow.cc 2019-05-14 17:38:23 +0000
@@ -75,19 +75,19 @@
void WarehouseWaresDisplay::draw_ware(RenderTarget& dst, Widelands::DescriptionIndex ware) {
WaresDisplay::draw_ware(dst, ware);
- Widelands::Warehouse::StockPolicy policy = warehouse_.get_stock_policy(get_type(), ware);
+ Widelands::StockPolicy policy = warehouse_.get_stock_policy(get_type(), ware);
const Image* pic = nullptr;
switch (policy) {
- case Widelands::Warehouse::StockPolicy::kPrefer:
+ case Widelands::StockPolicy::kPrefer:
pic = g_gr->images().get(pic_policy_prefer);
break;
- case Widelands::Warehouse::StockPolicy::kDontStock:
+ case Widelands::StockPolicy::kDontStock:
pic = g_gr->images().get(pic_policy_dontstock);
break;
- case Widelands::Warehouse::StockPolicy::kRemove:
+ case Widelands::StockPolicy::kRemove:
pic = g_gr->images().get(pic_policy_remove);
break;
- case Widelands::Warehouse::StockPolicy::kNormal:
+ case Widelands::StockPolicy::kNormal:
// don't draw anything for the normal policy
return;
}
@@ -106,7 +106,7 @@
Widelands::Warehouse&,
Widelands::WareWorker type);
- void set_policy(Widelands::Warehouse::StockPolicy);
+ void set_policy(Widelands::StockPolicy);
private:
InteractiveGameBase& gb_;
@@ -139,7 +139,7 @@
buttons, #policy, 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, \
g_gr->images().get("images/wui/buildings/stock_policy_button_" #policy ".png"), tooltip), \
b->sigclicked.connect(boost::bind( \
- &WarehouseWaresPanel::set_policy, this, Widelands::Warehouse::StockPolicy::k##policyname)), \
+ &WarehouseWaresPanel::set_policy, this, Widelands::StockPolicy::k##policyname)), \
buttons->add(b);
ADD_POLICY_BUTTON(normal, Normal, _("Normal policy"))
@@ -152,7 +152,7 @@
/**
* Add Buttons policy buttons
*/
-void WarehouseWaresPanel::set_policy(Widelands::Warehouse::StockPolicy newpolicy) {
+void WarehouseWaresPanel::set_policy(Widelands::StockPolicy newpolicy) {
if (gb_.can_act(wh_.owner().player_number())) {
bool is_workers = type_ == Widelands::wwWORKER;
const std::set<Widelands::DescriptionIndex> indices =
Follow ups
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: noreply, 2019-06-23
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-06-23
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-06-22
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-06-22
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-06-22
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-06-22
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-06-22
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-06-19
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-06-19
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-06-19
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-06-13
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-06-09
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-06-08
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-05-28
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-05-28
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-24
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-24
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-05-17
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: GunChleoc, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: kaputtnik, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: kaputtnik, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Benedikt Straub, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: Toni Förster, 2019-05-15
-
[Merge] lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
From: bunnybot, 2019-05-15