Merge remote-tracking branch 'upstream/master'

This commit is contained in:
dP
2020-07-09 10:55:24 +03:00
10 changed files with 259 additions and 131 deletions

View File

@@ -613,23 +613,6 @@ water_cmd.cpp
waypoint_cmd.cpp
zoning_cmd.cpp
# CityMania files
citymania/base64.h
citymania/base64.cpp
citymania/cm_bitstream.hpp
citymania/cm_bitstream.cpp
citymania/highlight.hpp
citymania/highlight.cpp
citymania/locations.hpp
citymania/locations.cpp
citymania/minimap.hpp
citymania/minimap.cpp
citymania/cm_saveload.hpp
citymania/cm_saveload.cpp
citymania/station_ui.hpp
citymania/station_ui.cpp
newgrf_revisions.hpp
# Save/Load handlers
saveload/afterload.cpp
saveload/ai_sl.cpp
@@ -1220,6 +1203,8 @@ sound/null_s.cpp
thread.h
# CityMania
citymania/cm_bitstream.hpp
citymania/cm_bitstream.cpp
citymania/cm_console_cmds.hpp
citymania/cm_console_cmds.cpp
citymania/cm_event.hpp
@@ -1232,5 +1217,21 @@ citymania/cm_main.cpp
citymania/cm_tooltips.hpp
citymania/cm_tooltips.cpp
citymania/cm_type.hpp
citymania/cm_saveload.hpp
citymania/cm_saveload.cpp
citymania/cm_settings.hpp
citymania/extensions/cmext_town.hpp
citymania/extensions/cmext_company.hpp
# CityMania client
citymania/base64.h
citymania/base64.cpp
citymania/highlight.hpp
citymania/highlight.cpp
citymania/locations.hpp
citymania/locations.cpp
citymania/minimap.hpp
citymania/minimap.cpp
citymania/station_ui.hpp
citymania/station_ui.cpp
newgrf_revisions.hpp

View File

@@ -2,6 +2,8 @@
#define CM_EVENT_HPP
#include "cm_type.hpp"
#include "../console_func.h"
#include "../cargo_type.h"
#include "../company_type.h"
#include "../economy_type.h"
@@ -42,12 +44,15 @@ struct HouseRebuilt {
struct HouseBuilt {
Town *town;
TileIndex tile;
HouseID house_id;
const HouseSpec *house_spec;
bool is_rebuilding;
};
struct HouseCleared {
Town *town;
TileIndex tile;
HouseID house_id;
const HouseSpec *house_spec;
bool was_completed; ///< whether house was completed before destruction
};
@@ -55,6 +60,7 @@ struct HouseCleared {
struct HouseCompleted {
Town *town;
TileIndex tile;
HouseID house_id;
const HouseSpec *house_spec;
};
@@ -100,6 +106,13 @@ struct CompanyBalanceChanged {
Money delta;
};
enum class Slot : uint8 {
GOAL = 10,
CONTROLLER = 20,
GAME = 30,
CONTROLLER_POST = 40,
RECORDER = 50,
};
class TypeDispatcherBase {
public:
@@ -115,14 +128,16 @@ public:
TypeDispatcher() { }
virtual ~TypeDispatcher() {}
void listen(Handler &handler) {
this->new_handlers.push_back(handler);
void listen(Slot slot, Handler &handler) {
this->handler_map.insert(std::make_pair(slot, handler));
}
void emit(const T &event) {
if (!this->new_handlers.empty()) {
this->handlers.insert(this->handlers.end(), this->new_handlers.begin(), this->new_handlers.end());
this->new_handlers.clear();
if (this->new_handlers) { // only rebuild handlers while not iterating
this->handlers.clear();
for (auto &p : this->handler_map) {
this->handlers.push_back(p.second);
}
}
for (auto &h : this->handlers) {
h(event);
@@ -131,7 +146,8 @@ public:
protected:
std::vector<Handler> handlers;
std::vector<Handler> new_handlers;
std::multimap<Slot, Handler> handler_map;
bool new_handlers = false;
};
@@ -151,8 +167,8 @@ protected:
public:
template<typename T>
void listen(std::function<void(const T &)> handler) {
this->get_dispatcher<T>().listen(handler);
void listen(Slot slot, std::function<void(const T &)> handler) {
this->get_dispatcher<T>().listen(slot, handler);
}
template<typename T>

View File

@@ -9,7 +9,7 @@
namespace citymania {
Game::Game() {
this->events.listen<event::NewMonth>([this] (const event::NewMonth &) {
this->events.listen<event::NewMonth>(event::Slot::GAME, [this] (const event::NewMonth &) {
for (Town *t : Town::Iterate()) {
t->cm.hs_last_month = t->cm.hs_total - t->cm.hs_total_prev;
t->cm.hs_total_prev = t->cm.hs_total;
@@ -28,45 +28,45 @@ Game::Game() {
this->towns_growth_tiles.clear();
});
this->events.listen<event::TownGrowthSucceeded>([this] (const event::TownGrowthSucceeded &event) {
this->events.listen<event::TownGrowthSucceeded>(event::Slot::GAME, [this] (const event::TownGrowthSucceeded &event) {
if (event.town->cache.num_houses <= event.prev_houses) {
event.town->cm.hs_total++;
this->towns_growth_tiles[event.tile] = TownGrowthTileState::HS;
this->set_town_growth_tile(event.tile, TownGrowthTileState::HS);
}
});
this->events.listen<event::TownGrowthFailed>([this] (const event::TownGrowthFailed &event) {
this->events.listen<event::TownGrowthFailed>(event::Slot::GAME, [this] (const event::TownGrowthFailed &event) {
event.town->cm.cs_total++;
this->towns_growth_tiles[event.tile] = TownGrowthTileState::CS;
this->set_town_growth_tile(event.tile, TownGrowthTileState::CS);
});
this->events.listen<event::HouseRebuilt>([this] (const event::HouseRebuilt &event) {
this->events.listen<event::HouseRebuilt>(event::Slot::GAME, [this] (const event::HouseRebuilt &event) {
if (event.was_successful) {
event.town->cm.houses_reconstructed_this_month++;
this->towns_growth_tiles[event.tile] = TownGrowthTileState::RH_REBUILT;
this->set_town_growth_tile(event.tile, TownGrowthTileState::RH_REBUILT);
} else {
event.town->cm.houses_demolished_this_month++;
this->towns_growth_tiles[event.tile] = TownGrowthTileState::RH_REMOVED;
this->set_town_growth_tile(event.tile, TownGrowthTileState::RH_REMOVED);
}
});
this->events.listen<event::HouseBuilt>([this] (const event::HouseBuilt &event) {
this->events.listen<event::HouseBuilt>(event::Slot::GAME, [this] (const event::HouseBuilt &event) {
event.town->cm.houses_constructing++;
event.town->cm.real_population += event.house_spec->population;
this->towns_growth_tiles[event.tile] = TownGrowthTileState::NEW_HOUSE;
this->set_town_growth_tile(event.tile, TownGrowthTileState::NEW_HOUSE);
});
this->events.listen<event::HouseCleared>([this] (const event::HouseCleared &event) {
this->events.listen<event::HouseCleared>(event::Slot::GAME, [this] (const event::HouseCleared &event) {
if (!event.was_completed)
event.town->cm.houses_constructing--;
event.town->cm.real_population -= event.house_spec->population;
});
this->events.listen<event::HouseCompleted>([this] (const event::HouseCompleted &event) {
this->events.listen<event::HouseCompleted>(event::Slot::GAME, [this] (const event::HouseCompleted &event) {
event.town->cm.houses_constructing--;
});
this->events.listen<event::TownCachesRebuilt>([this] (const event::TownCachesRebuilt &event) {
this->events.listen<event::TownCachesRebuilt>(event::Slot::GAME, [this] (const event::TownCachesRebuilt &event) {
for (Town *town : Town::Iterate()) {
town->cm.real_population = 0;
town->cm.houses_constructing = 0;
@@ -81,9 +81,13 @@ Game::Game() {
}
});
this->events.listen<event::CargoAccepted>([this] (const event::CargoAccepted &event) {
this->events.listen<event::CargoAccepted>(event::Slot::GAME, [this] (const event::CargoAccepted &event) {
event.company->cur_economy.cm.cargo_income[event.cargo_type] += event.profit;
});
}
void Game::set_town_growth_tile(TileIndex tile, TownGrowthTileState state) {
if (this->towns_growth_tiles[tile] < state) this->towns_growth_tiles[tile] = state;
}
} // namespace citymania

View File

@@ -1,5 +1,5 @@
#ifndef CMEXT_GAME_HPP
#define CMEXT_GAME_HPP
#ifndef CM_GAME_HPP
#define CM_GAME_HPP
#include "../town.h"
@@ -20,13 +20,14 @@ enum class TownGrowthTileState : uint8 {
class Game {
public:
event::Dispatcher events;
typedef std::map<TileIndex, TownGrowthTileState> TownsGrowthTilesIndex;
TownsGrowthTilesIndex towns_growth_tiles_last_month;
TownsGrowthTilesIndex towns_growth_tiles;
event::Dispatcher events;
Game();
void set_town_growth_tile(TileIndex tile, TownGrowthTileState state);
TownGrowthTileState get_town_growth_tile(TileIndex tile) {
auto a = this->towns_growth_tiles.find(tile);

View File

@@ -16,7 +16,7 @@ void ResetGame() {
}
void SwitchToMode(SwitchMode new_mode) {
ResetGame();
if (new_mode != SM_SAVE_GAME) ResetGame();
}
void ToggleSmallMap() {

View File

@@ -8,6 +8,7 @@
#include "cm_bitstream.hpp"
#include "cm_saveload.hpp"
#include "cm_settings.hpp"
#include "cm_game.hpp"
#include "cm_main.hpp"
@@ -116,7 +117,8 @@ void CBController_saveload_encode(BitOStream &bs) {
bs.WriteBytes(0 /* version */, 2);
// Controller::saveload_encode(bs);
bs.WriteBytes(0, 1);
bs.WriteBytes(_settings_client.gui.cb_distance_check, 1);
bs.WriteBytes(0, 1);
// bs.WriteBytes(_settings_client.gui.cb_distance_check, 1);
bs.WriteBytes(0, 1);
bs.WriteBytes(0, 1);
bs.WriteBytes(0, 1);
@@ -124,43 +126,43 @@ void CBController_saveload_encode(BitOStream &bs) {
bs.WriteBytes(0, 1);
bs.WriteBytes(0, 1);
std::vector<CargoID> cb_cargos;
for(CargoID cargo = 0; cargo < NUM_CARGO; cargo++) {
if (CB_GetReq(cargo) > 0)
cb_cargos.push_back(cargo);
}
// for(CargoID cargo = 0; cargo < NUM_CARGO; cargo++) {
// if (CB_GetReq(cargo) > 0)
// cb_cargos.push_back(cargo);
// }
for (auto cargo_id : cb_cargos) {
// bs.WriteBytes(req.cargo_id, 1);
// bs.WriteBytes(req.amount, 4);
// bs.WriteBytes(req.from, 4);
// bs.WriteBytes(req.decay, 1);
bs.WriteBytes(cargo_id, 1);
bs.WriteBytes(CB_GetReq(cargo_id), 4);
bs.WriteBytes(CB_GetFrom(cargo_id), 4);
bs.WriteBytes(CB_GetDecay(cargo_id), 1);
}
// uint16 cb_towns = 0;
// ForEachCBTown([this, &cb_towns](Town *, Company *) { cb_towns++; });
bs.WriteBytes(Town::GetNumItems(), 2);
for (Town *t : Town::Iterate()) {
auto &tcb = t->cb;
bs.WriteBytes(t->index, 2);
bs.WriteBytes(tcb.pax_delivered, 4);
bs.WriteBytes(tcb.mail_delivered, 4);
bs.WriteBytes(tcb.pax_delivered_last_month, 4);
bs.WriteBytes(tcb.mail_delivered_last_month, 4);
bs.WriteBytes((uint8)tcb.growth_state, 1);
bs.WriteBytes(tcb.shrink_effeciency, 1);
bs.WriteBytes(tcb.shrink_rate, 2);
bs.WriteBytes(tcb.shrink_counter, 2);
for (auto cargo_id : cb_cargos) {
bs.WriteBytes(tcb.stored[cargo_id], 4);
bs.WriteBytes(tcb.delivered[cargo_id], 4);
bs.WriteBytes(tcb.required[cargo_id], 4);
bs.WriteBytes(tcb.delivered_last_month[cargo_id], 4);
bs.WriteBytes(tcb.required_last_month[cargo_id], 4);
}
}
// for (auto cargo_id : cb_cargos) {
// // bs.WriteBytes(req.cargo_id, 1);
// // bs.WriteBytes(req.amount, 4);
// // bs.WriteBytes(req.from, 4);
// // bs.WriteBytes(req.decay, 1);
// bs.WriteBytes(cargo_id, 1);
// bs.WriteBytes(CB_GetReq(cargo_id), 4);
// bs.WriteBytes(CB_GetFrom(cargo_id), 4);
// bs.WriteBytes(CB_GetDecay(cargo_id), 1);
// }
// // uint16 cb_towns = 0;
// // ForEachCBTown([this, &cb_towns](Town *, Company *) { cb_towns++; });
// bs.WriteBytes(Town::GetNumItems(), 2);
// for (Town *t : Town::Iterate()) {
// auto &tcb = t->cb;
// bs.WriteBytes(t->index, 2);
// bs.WriteBytes(tcb.pax_delivered, 4);
// bs.WriteBytes(tcb.mail_delivered, 4);
// bs.WriteBytes(tcb.pax_delivered_last_month, 4);
// bs.WriteBytes(tcb.mail_delivered_last_month, 4);
// bs.WriteBytes((uint8)tcb.growth_state, 1);
// bs.WriteBytes(tcb.shrink_effeciency, 1);
// bs.WriteBytes(tcb.shrink_rate, 2);
// bs.WriteBytes(tcb.shrink_counter, 2);
// for (auto cargo_id : cb_cargos) {
// bs.WriteBytes(tcb.stored[cargo_id], 4);
// bs.WriteBytes(tcb.delivered[cargo_id], 4);
// bs.WriteBytes(tcb.required[cargo_id], 4);
// bs.WriteBytes(tcb.delivered_last_month[cargo_id], 4);
// bs.WriteBytes(tcb.required_last_month[cargo_id], 4);
// }
// }
}
bool CBController_saveload_decode(BitIStream &bs) {
@@ -171,7 +173,8 @@ bool CBController_saveload_decode(BitIStream &bs) {
// if (!Controller::saveload_decode(bs))
// return false;
bs.ReadBytes(1); /* _settings_game.citymania.cb.requirements_type */
_settings_client.gui.cb_distance_check = bs.ReadBytes(1); /* _settings_game.citymania.cb.acceptance_range */
bs.ReadBytes(1); /* _settings_game.citymania.cb.acceptance_range */
// _settings_client.gui.cb_distance_check = bs.ReadBytes(1); /* _settings_game.citymania.cb.acceptance_range */
bs.ReadBytes(1); /* _settings_game.citymania.cb.storage_size */
bs.ReadBytes(1); /* _settings_game.citymania.cb.town_protection_range */
bs.ReadBytes(2); /* _settings_game.citymania.cb.claim_max_houses */
@@ -191,7 +194,7 @@ bool CBController_saveload_decode(BitIStream &bs) {
auto required = bs.ReadBytes(4);
auto from = bs.ReadBytes(4);
auto decay = bs.ReadBytes(1);
CB_SetRequirements(cargo_id, required, from, decay);
// CB_SetRequirements(cargo_id, required, from, decay);
// _settings_game.citymania.cb.requirements.push_back(CBRequirement(cargo_id, from, required, decay, i, ""));
}
@@ -205,28 +208,54 @@ bool CBController_saveload_decode(BitIStream &bs) {
return false;
}
auto &tcb = t->cb;
tcb.pax_delivered = bs.ReadBytes(4);
tcb.mail_delivered = bs.ReadBytes(4);
tcb.pax_delivered_last_month = bs.ReadBytes(4);
tcb.mail_delivered_last_month = bs.ReadBytes(4);
tcb.growth_state = (TownGrowthState)bs.ReadBytes(1);
tcb.shrink_effeciency = bs.ReadBytes(1);
tcb.shrink_rate = bs.ReadBytes(2);
tcb.shrink_counter = bs.ReadBytes(2);
for (auto cargo_id : cb_cargos) {
tcb.stored[cargo_id] = bs.ReadBytes(4);
tcb.delivered[cargo_id] = bs.ReadBytes(4);
tcb.required[cargo_id] = bs.ReadBytes(4);
tcb.delivered_last_month[cargo_id] = bs.ReadBytes(4);
tcb.required_last_month[cargo_id] = bs.ReadBytes(4);
}
// auto &tcb = t->cb;
// tcb.pax_delivered = bs.ReadBytes(4);
// tcb.mail_delivered = bs.ReadBytes(4);
// tcb.pax_delivered_last_month = bs.ReadBytes(4);
// tcb.mail_delivered_last_month = bs.ReadBytes(4);
// tcb.growth_state = (TownGrowthState)bs.ReadBytes(1);
// tcb.shrink_effeciency = bs.ReadBytes(1);
// tcb.shrink_rate = bs.ReadBytes(2);
// tcb.shrink_counter = bs.ReadBytes(2);
// for (auto cargo_id : cb_cargos) {
// tcb.stored[cargo_id] = bs.ReadBytes(4);
// tcb.delivered[cargo_id] = bs.ReadBytes(4);
// tcb.required[cargo_id] = bs.ReadBytes(4);
// tcb.delivered_last_month[cargo_id] = bs.ReadBytes(4);
// tcb.required_last_month[cargo_id] = bs.ReadBytes(4);
// }
};
return true;
}
uint8 _controller_type = 0;
uint8 _game_type = 0;
void EncodeSettings(BitOStream &bs, Settings &settings) {
bs.WriteBytes(settings.max_players_in_company, 1);
bs.WriteBytes(settings.destroyed_houses_per_month, 2);
bs.WriteBytes(settings.game_length_years, 2);
bs.WriteBytes(settings.protect_funded_industries, 1);
bs.WriteBytes(settings.same_depot_sell_years, 2);
bs.WriteBytes(settings.economy.cashback_for_extra_land_clear, 1);
bs.WriteBytes(settings.economy.cashback_for_bridges_and_tunnels, 1);
bs.WriteBytes(settings.economy.cashback_for_foundations, 1);
bs.WriteBytes(settings.limits.max_airports, 2);
bs.WriteBytes(settings.limits.disable_canals, 1);
bs.WriteBytes(settings.limits.min_distance_between_docks, 2);
}
void DecodeSettings(BitIStream &bs, Settings &settings) {
settings.max_players_in_company = bs.ReadBytes(1);
settings.destroyed_houses_per_month = bs.ReadBytes(2);
settings.game_length_years = bs.ReadBytes(2);
settings.protect_funded_industries = bs.ReadBytes(1);
settings.same_depot_sell_years = bs.ReadBytes(2);
settings.economy.cashback_for_extra_land_clear = bs.ReadBytes(1);
settings.economy.cashback_for_bridges_and_tunnels = bs.ReadBytes(1);
settings.economy.cashback_for_foundations = bs.ReadBytes(1);
settings.limits.max_airports = bs.ReadBytes(2);
settings.limits.disable_canals = bs.ReadBytes(1);
settings.limits.min_distance_between_docks = bs.ReadBytes(2);
}
uint16 _last_client_version = 1512;
static u8vector EncodeData() {
@@ -234,37 +263,39 @@ static u8vector EncodeData() {
bs.Reserve(1000);
bs.WriteBytes(SAVEGAME_DATA_FORMAT_VERSION, 2);
bs.WriteBytes(_last_client_version, 2);
bs.WriteBytes(_controller_type, 1);
bs.WriteBytes(_settings_game.citymania.controller_type, 1);
bs.WriteBytes(_date, 4); // Just in case we'll need to detect that game
bs.WriteBytes(_date_fract, 1); // was saved by unmodified client
bs.WriteBytes(_game_type, 1);
bs.WriteBytes(_settings_game.citymania.game_type, 1);
bs.WriteBytes(0, 3); // Reserved
bs.WriteBytes(0, 4); // Reserved
EncodeSettings(bs, _settings_game.citymania);
EncodeCompanies(bs);
EncodeTowns(bs);
EncodeTownsGrowthTiles(bs, _game->towns_growth_tiles);
EncodeTownsGrowthTiles(bs, _game->towns_growth_tiles_last_month);
if (_controller_type == 4)
if (_settings_game.citymania.controller_type == 4)
CBController_saveload_encode(bs);
return bs.GetVector();
}
static void DecodeDataV2(BitIStream &bs) {
DecodeSettings(bs, _settings_game.citymania);
DecodeCompanies(bs);
DecodeTowns(bs);
DecodeTownsGrowthTiles(bs, _game->towns_growth_tiles);
DecodeTownsGrowthTiles(bs, _game->towns_growth_tiles_last_month);
if (_controller_type == 4) CBController_saveload_decode(bs);
if (_settings_game.citymania.controller_type == 4) CBController_saveload_decode(bs);
}
static void DecodeTownsCargoV1(BitIStream &bs)
{
CB_SetStorage(bs.ReadBytes(1));
_settings_client.gui.cb_distance_check = bs.ReadBytes(1);
bs.ReadBytes(1);bs.ReadBytes(1);
// CB_SetStorage(bs.ReadBytes(1));
// _settings_client.gui.cb_distance_check = bs.ReadBytes(1);
uint n_cb_cargos = bs.ReadBytes(1);
CB_ResetRequirements();
// CB_ResetRequirements();
std::vector<CargoID> cb_cargos;
for (uint i = 0; i < n_cb_cargos; i++) {
uint cargo = bs.ReadBytes(1);
@@ -276,7 +307,7 @@ static void DecodeTownsCargoV1(BitIStream &bs)
uint req = bs.ReadBytes(4);
uint from = bs.ReadBytes(4);
uint decay = bs.ReadBytes(1);
CB_SetRequirements(cargo, req, from, decay);
// CB_SetRequirements(cargo, req, from, decay);
}
Town *t;
uint n_affected_towns = bs.ReadBytes(2);
@@ -287,21 +318,21 @@ static void DecodeTownsCargoV1(BitIStream &bs)
DEBUG(sl, 0, "Invalid TownID in CB towns cargo data (%u)", town_id);
return;
}
auto &tcb = t->cb;
for (auto cargo_id : cb_cargos) {
tcb.stored[cargo_id] = bs.ReadBytes(4);
tcb.delivered_last_month[cargo_id] = bs.ReadBytes(4);
tcb.delivered[cargo_id] = bs.ReadBytes(4);
bs.ReadBytes(1); /* delivered enough */
// auto &tcb = t->cb;
// for (auto cargo_id : cb_cargos) {
// tcb.stored[cargo_id] = bs.ReadBytes(4);
// tcb.delivered_last_month[cargo_id] = bs.ReadBytes(4);
// tcb.delivered[cargo_id] = bs.ReadBytes(4);
// bs.ReadBytes(1); /* delivered enough */
tcb.required[cargo_id] = 0;
tcb.required_last_month[cargo_id] = 0;
}
// tcb.required[cargo_id] = 0;
// tcb.required_last_month[cargo_id] = 0;
// }
}
}
static void DecodeDataV1(BitIStream &bs) {
if (_controller_type != 0) DecodeTownsCargoV1(bs);
if (_settings_game.citymania.controller_type != 0) DecodeTownsCargoV1(bs);
for (Town *t : Town::Iterate()) {
t->cm.growing_by_chance = bs.ReadBytes(1);
t->cm.houses_reconstructed_this_month = bs.ReadBytes(2);
@@ -348,15 +379,15 @@ static void DecodeData(u8vector &data) {
}
DEBUG(sl, 2, "CityMania savegame data version %u", version);
_last_client_version = bs.ReadBytes(2);
_controller_type = bs.ReadBytes(1);
if (version <= 1) _controller_type = (_controller_type ? 4 : 0);
_settings_game.citymania.controller_type = bs.ReadBytes(1);
if (version <= 1) _settings_game.citymania.controller_type = (_settings_game.citymania.controller_type ? 4 : 0);
int32 date = bs.ReadBytes(4);
uint32 date_fract = bs.ReadBytes(1);
if (date != _date || date_fract != _date_fract) {
DEBUG(sl, 0, "Savegame was run in unmodified client, extra save data "
"preserved, but may not be accurate");
}
_game_type = bs.ReadBytes(1);
_settings_game.citymania.game_type = bs.ReadBytes(1);
bs.ReadBytes(3); // reserved
bs.ReadBytes(4); // reserved
if (version == 1) DecodeDataV1(bs);

View File

@@ -0,0 +1,69 @@
#ifndef CM_SETTINGS_HPP
#define CM_SETTINGS_HPP
#include <memory>
#include <vector>
// #include "types.hpp"
namespace citymania {
class CBRequirement {
public:
CargoID cargo_id;
uint32 from;
uint32 amount;
uint8 decay;
uint8 index;
std::string name;
bool has_storage;
static CBRequirement Parse(const char *name, const char *value, uint8 index);
CBRequirement(CargoID cargo_id, uint32 from, uint32 amount, uint8 decay,
uint8 index, std::string name)
:cargo_id{cargo_id}, from{from}, amount{amount}, decay{decay},
index{index}, name{name}, has_storage{decay < 100} {}
};
struct EconomySettings {
bool cashback_for_extra_land_clear;
bool cashback_for_bridges_and_tunnels;
bool cashback_for_foundations;
};
struct LimitsSettings {
uint16 max_airports; ///< maximum number of airports per company, 0=unlimited
bool disable_canals;
uint16 min_distance_between_docks; ///< docks can be build only x tiles apart another, 0=disable check
};
struct CBSettings {
uint8 requirements_type; // 0 - regular 1 - income-based requirements (new cb only)
std::vector<CBRequirement> requirements;
uint8 acceptance_range; // How far can station be to count towards requiremnts
uint8 storage_size; // cargo storage multiplier (x * monthly requirements)
uint8 town_protection_range; // Claimed town protection range (square from centre), overlaped with tz0
uint16 claim_max_houses; // Max amount of houses claimable town can have
bool smooth_growth_rate; // Calculate growth rate precisely instead of rounding to 50 houses and allow going below 70 ticks (default max)
bool allow_negative_growth; // Make town shrink (with the same speed as growth) if requirements aren't satisfied
};
struct Settings {
CBSettings cb;
EconomySettings economy;
LimitsSettings limits;
uint8 game_type; // GameType
uint8 controller_type; // ControllerType
uint8 max_players_in_company;
uint16 destroyed_houses_per_month; // max amount of houses a company can destroy per month
uint16 game_length_years; // game length in years(0 = disabled)
bool protect_funded_industries;
uint16 same_depot_sell_years; // can only sell vehicles in the same place (20 tiles radius) for first x yearss of its lifetime (0 = disabled)
};
}; // namespace citymania
#endif

View File

@@ -18,7 +18,7 @@ public:
bool is_scored; ///< whether company is eligible for scoring
};
} // namespace ext
} // namespace citymania
} // namespace citymania

View File

@@ -20,6 +20,8 @@
#include "zoom_type.h"
#include "openttd.h"
#include "citymania/cm_settings.hpp"
/** Settings profiles and highscore tables. */
enum SettingsProfile {
@@ -585,6 +587,8 @@ struct GameSettings {
LinkGraphSettings linkgraph; ///< settings for link graph calculations
StationSettings station; ///< settings related to station management
LocaleSettings locale; ///< settings related to used currency/unit system in the current game
citymania::Settings citymania;
};
/** All settings that are only important for the local client. */

View File

@@ -258,7 +258,7 @@ enum TownGrowthResult {
// GROWTH_SEARCH_RUNNING >= 1
};
static bool BuildTownHouse(Town *t, TileIndex tile);
static bool BuildTownHouse(Town *t, TileIndex tile, bool is_rebuilding = false);
static Town *CreateRandomTown(uint attempts, uint32 townnameparts, TownSize size, bool city, TownLayout layout);
static void TownDrawHouseLift(const TileInfo *ti)
@@ -537,7 +537,7 @@ static void MakeSingleHouseBigger(TileIndex tile)
ResetHouseAge(tile);
if (hs->building_flags & BUILDING_HAS_1_TILE)
citymania::Emit(citymania::event::HouseCompleted{town, tile, hs});
citymania::Emit(citymania::event::HouseCompleted{town, tile, house_id, hs});
}
MarkTileDirtyByTile(tile);
}
@@ -673,7 +673,7 @@ static void TileLoop_Town(TileIndex tile)
/* Rebuild with another house? */
bool rebuild_res = false;
if (GB(r, 24, 8) >= 12) rebuild_res = BuildTownHouse(t, tile);
if (GB(r, 24, 8) >= 12) rebuild_res = BuildTownHouse(t, tile, true);
citymania::Emit(citymania::event::HouseRebuilt{t, tile, rebuild_res});
}
@@ -2745,7 +2745,7 @@ static bool CheckTownBuild2x2House(TileIndex *tile, Town *t, int maxz, bool nosl
* @param tile where the house will be built
* @return false iff no house can be built at this tile
*/
static bool BuildTownHouse(Town *t, TileIndex tile)
static bool BuildTownHouse(Town *t, TileIndex tile, bool is_rebuilding)
{
/* forbidden building here by town layout */
if (!TownLayoutAllowsHouseHere(t, tile)) return false;
@@ -2894,8 +2894,10 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
UpdateTownGrowthRate(t);
UpdateTownCargoes(t, tile);
citymania::Emit(citymania::event::HouseBuilt{t, tile, hs});
if (completed) citymania::Emit(citymania::event::HouseCompleted{t, tile, hs});
if (!_generating_world) {
citymania::Emit(citymania::event::HouseBuilt{t, tile, house, hs, is_rebuilding});
if (completed) citymania::Emit(citymania::event::HouseCompleted{t, tile, house, hs});
}
return true;
}
@@ -2986,7 +2988,7 @@ void ClearTownHouse(Town *t, TileIndex tile)
/* Update cargo acceptance. */
UpdateTownCargoes(t, tile);
citymania::Emit(citymania::event::HouseCleared{t, tile, hs, is_completed});
citymania::Emit(citymania::event::HouseCleared{t, tile, house, hs, is_completed});
}
/**