Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions descriptor/factory_desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ class factory_desc_t : public obj_desc_t {
sint8 sound_id;
uint32 sound_interval;

// Extended pak: automatic upgrade when retiring
uint16 upgrade_probability; // 0 = never upgrade; 1-10000 = chance out of 10000
char* upgrade_to_name; // temporary during loading; freed after resolution
const factory_desc_t* upgrade_to; // resolved target, NULL = no upgrade

public:
const char *get_name() const { return get_building()->get_name(); }
const char *get_copyright() const { return get_building()->get_copyright(); }
Expand Down Expand Up @@ -300,6 +305,9 @@ class factory_desc_t : public obj_desc_t {
sint8 get_sound() const { return sound_id; }
uint32 get_sound_interval_ms() const { return sound_interval; }

uint16 get_upgrade_probability() const { return upgrade_probability; }
const factory_desc_t* get_upgrade_to() const { return upgrade_to; }

void calc_checksum(checksum_t *chk) const;
};

Expand Down
38 changes: 38 additions & 0 deletions descriptor/reader/factory_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ obj_desc_t *factory_reader_t::read_node(FILE *fp, obj_node_info_t &node)
desc->sound_id = NO_SOUND;
desc->sound_interval = 0xFFFFFFFFul;
desc->smokerotations = 0;
desc->upgrade_probability = 0;
desc->upgrade_to_name = NULL;
desc->upgrade_to = NULL;

typedef factory_desc_t::site_t site_t;
if(version == 5) {
Expand Down Expand Up @@ -460,6 +463,23 @@ obj_desc_t *factory_reader_t::read_node(FILE *fp, obj_node_info_t &node)
desc->mail_demand = 65535;
}

// Extended pak fields (appended after any standard version block)
if( extended ) {
if( extended_version > 1 ) {
dbg->fatal("factory_reader_t::read_node()", "Incompatible Extended pak version %i", extended_version);
}
if( extended_version >= 1 ) {
desc->upgrade_probability = decode_uint16(p);
const uint8 len = decode_uint8(p);
if( len > 0 ) {
char *name = new char[len + 1];
for( uint8 i = 0; i < len; i++ ) { name[i] = decode_sint8(p); }
name[len] = '\0';
desc->upgrade_to_name = name;
}
}
}

DBG_DEBUG("factory_reader_t::read_node()",
"version=%i, place=%i, productivity=%i, suppliers=%i, products=%i, fields=%i, range=%i, level=%i"
"Demands: pax=%i / mail=%i / electric=%i,"
Expand Down Expand Up @@ -509,17 +529,35 @@ DBG_MESSAGE("vehicle_reader_t::register_obj()","old sound %i to %i",old_id,desc-
}


// Factories that have an upgrade_to_name needing resolution after all descs are loaded.
static vector_tpl<factory_desc_t*> pending_upgrade_resolution;

void factory_reader_t::register_obj(obj_desc_t *&data)
{
factory_desc_t* desc = static_cast<factory_desc_t*>(data);
size_t fab_name_len = strlen( desc->get_name() );
desc->electricity_producer = ( fab_name_len>11 && (strcmp(desc->get_name()+fab_name_len-9, "kraftwerk")==0 || strcmp(desc->get_name()+fab_name_len-11, "Power Plant")==0) );
desc->correct_smoke();
factory_builder_t::register_desc(desc);
if( desc->upgrade_to_name ) {
pending_upgrade_resolution.append(desc);
}
}


bool factory_reader_t::successfully_loaded() const
{
// Resolve upgrade targets now that all factory descs are registered.
FOR(vector_tpl<factory_desc_t*>, desc, pending_upgrade_resolution) {
desc->upgrade_to = factory_builder_t::get_desc(desc->upgrade_to_name);
if( !desc->upgrade_to ) {
dbg->warning("factory_reader_t::successfully_loaded()",
"upgrade target '%s' not found for factory '%s'",
desc->upgrade_to_name, desc->get_name());
}
delete[] desc->upgrade_to_name;
desc->upgrade_to_name = NULL;
}
pending_upgrade_resolution.clear();
return factory_builder_t::successfully_loaded();
}
18 changes: 15 additions & 3 deletions simfab.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2827,14 +2827,26 @@ void fabrik_t::new_month()
const uint16 timeline_month = welt->get_timeline_year_month(); // This will be 0 if timeline is disabled.
const uint16 retire_month = desc->get_building()->get_retire_year_month();
const uint32 latest_retire_month = retire_month + (12 * welt->get_settings().get_factory_max_years_obsolete());//welt->get_settings().get_factory_max_years_obsolete());
if(welt->get_settings().is_close_old_factory() && !no_close_factory && !no_close_factory && timeline_month > retire_month)
if(welt->get_settings().is_close_old_factory() && !no_close_factory && timeline_month > retire_month)
{
if(latest_retire_month <= timeline_month || simrand(latest_retire_month - timeline_month) == 0)
{
// Check whether this factory upgrades to a successor instead of simply closing.
pending_upgrade = NULL;
const factory_desc_t* upgrade_desc = desc->get_upgrade_to();
if( upgrade_desc && desc->get_upgrade_probability() > 0
&& simrand(10000) < desc->get_upgrade_probability() ) {
pending_upgrade = upgrade_desc;
}
welt->closed_factories_this_month.append(this);
cbuffer_t buf;
buf.printf( translator::translate("Factory %s has closed."), get_name());
welt->get_message()->add_message( (const char *)buf, get_pos().get_2d(), message_t::warnings, CITY_KI, get_desc()->get_building()->get_tile(0)->get_background(0, 0, 0));
if( pending_upgrade ) {
buf.printf( translator::translate("Factory %s has been upgraded."), get_name());
welt->get_message()->add_message( (const char *)buf, get_pos().get_2d(), message_t::industry, CITY_KI, get_desc()->get_building()->get_tile(0)->get_background(0, 0, 0));
} else {
buf.printf( translator::translate("Factory %s has closed."), get_name());
welt->get_message()->add_message( (const char *)buf, get_pos().get_2d(), message_t::warnings, CITY_KI, get_desc()->get_building()->get_tile(0)->get_background(0, 0, 0));
}
} else {
cbuffer_t buf;
buf.printf( translator::translate("Factory %s is retired! Close soon!"), get_name());
Expand Down
2 changes: 2 additions & 0 deletions simfab.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ class fabrik_t
* if this flag is true, this factory cannot close even after retire year
*/
bool no_close_factory=false;
const factory_desc_t* pending_upgrade=NULL; // set when upgrading instead of closing

/**
* the shipment size
Expand Down Expand Up @@ -742,6 +743,7 @@ class fabrik_t
*/
const bool is_no_close_factory() {return no_close_factory;}
void set_no_close_factory(bool yesno) { no_close_factory = yesno;}
const factory_desc_t* get_pending_upgrade() const { return pending_upgrade; }

/**
* get and set shipment size
Expand Down
29 changes: 29 additions & 0 deletions simworld.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3935,8 +3935,37 @@ void karte_t::new_month()
{
if(fab_list.is_contained(fab))
{
const factory_desc_t* upgrade_desc = fab->get_pending_upgrade();
const koord3d old_pos = fab->get_pos();
gebaeude_t* gb = lookup_kartenboden( fab->get_pos().get_2d() )->find<gebaeude_t>();
const uint8 old_rot = gb ? gb->get_tile()->get_layout() : 0;

// Save connection lists before the factory is destroyed.
vector_tpl<koord> old_lieferziele( upgrade_desc ? fab->get_lieferziele() : vector_tpl<koord>() );
vector_tpl<koord> old_suppliers( upgrade_desc ? fab->get_suppliers() : vector_tpl<koord>() );

hausbauer_t::remove(get_public_player(), gb);
// fab pointer is invalid from here on.

if( upgrade_desc ) {
fabrik_t* new_fab = factory_builder_t::build_factory(NULL, upgrade_desc, -1, old_rot, old_pos, get_public_player());
if( new_fab ) {
// Re-link to former consumers: check if new factory produces what each consumer needs.
FOR(vector_tpl<koord>, consumer_pos, old_lieferziele) {
fabrik_t* consumer = fabrik_t::get_fab(consumer_pos);
if( consumer ) {
consumer->add_supplier(new_fab);
}
}
// Re-link to former suppliers: check if new factory needs what each supplier produces.
FOR(vector_tpl<koord>, supplier_pos, old_suppliers) {
fabrik_t* supplier = fabrik_t::get_fab(supplier_pos);
if( supplier ) {
new_fab->add_supplier(supplier);
}
}
}
}
}
}
INT_CHECK("simworld 1278");
Expand Down
Loading