Skip to content

Commit

Permalink
Add dynamic demand changes
Browse files Browse the repository at this point in the history
Also some code refactoring
  • Loading branch information
crudelios committed Oct 9, 2024
1 parent 640fbd3 commit de4f89d
Show file tree
Hide file tree
Showing 26 changed files with 586 additions and 397 deletions.
12 changes: 6 additions & 6 deletions src/editor/tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "map/routing_terrain.h"
#include "map/tiles.h"
#include "map/terrain.h"
#include "scenario/editor.h"
#include "scenario/editor_events.h"
#include "scenario/editor_map.h"
#include "city/warning.h"
Expand Down Expand Up @@ -294,7 +295,7 @@ void editor_tool_update_use(const map_tile *tile)
break;
}

scenario_editor_updated_terrain();
scenario_editor_set_as_unsaved();
widget_minimap_invalidate();
}

Expand Down Expand Up @@ -360,7 +361,7 @@ static void place_building(const map_tile *tile)
if (editor_tool_can_place_building(tile, size * size, 0)) {
building *b = building_create(type, tile->x, tile->y);
map_building_tiles_add(b->id, tile->x, tile->y, size, image_id, TERRAIN_BUILDING);
scenario_editor_updated_terrain();
scenario_editor_set_as_unsaved();
} else {
city_warning_show(WARNING_EDITOR_CANNOT_PLACE, NEW_WARNING_SLOT);
}
Expand All @@ -377,8 +378,7 @@ static void update_terrain_after_elevation_changes(void)
map_tiles_update_all_meadow();
map_tiles_update_all_water();


scenario_editor_updated_terrain();
scenario_editor_set_as_unsaved();
}

static void place_access_ramp(const map_tile *tile)
Expand All @@ -396,7 +396,7 @@ static void place_access_ramp(const map_tile *tile)
image_group(GROUP_TERRAIN_ACCESS_RAMP) + orientation, TERRAIN_ACCESS_RAMP);

update_terrain_after_elevation_changes();
scenario_editor_updated_terrain();
scenario_editor_set_as_unsaved();
} else {
city_warning_show(WARNING_EDITOR_CANNOT_PLACE, NEW_WARNING_SLOT);
}
Expand All @@ -405,7 +405,7 @@ static void place_access_ramp(const map_tile *tile)
static void place_road(const map_tile *start_tile, const map_tile *end_tile)
{
if (building_construction_place_road(0, start_tile->x, start_tile->y, end_tile->x, end_tile->y)) {
scenario_editor_updated_terrain();
scenario_editor_set_as_unsaved();
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/game/file_editor.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ static void prepare_map_for_editing(void)
map_natives_init_editor();
map_routing_update_all();

scenario_editor_set_as_saved();

city_view_init();
game_state_unpause();
}
Expand Down Expand Up @@ -170,5 +172,9 @@ int game_file_editor_write_scenario(const char *scenario_file)
scenario_distant_battle_set_roman_travel_months();
scenario_distant_battle_set_enemy_travel_months();

return game_file_io_write_scenario(scenario_file);
if (game_file_io_write_scenario(scenario_file)) {
scenario_editor_set_as_saved();
return 1;
}
return 0;
}
7 changes: 4 additions & 3 deletions src/game/file_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "scenario/criteria.h"
#include "scenario/custom_media.h"
#include "scenario/custom_messages.h"
#include "scenario/demand_change.h"
#include "scenario/earthquake.h"
#include "scenario/emperor_change.h"
#include "scenario/empire.h"
Expand Down Expand Up @@ -679,7 +680,7 @@ static void scenario_load_from_state(scenario_state *file, scenario_version_t ve
}
if (version > SCENARIO_LAST_STATIC_ORIGINAL_DATA) {
scenario_invasion_load_state(file->invasions);
// scenario_demand_change_load_state(file->demand_changes);
scenario_demand_change_load_state(file->demand_changes);
// scenario_price_change_load_state(file->price_changes);
// scenario_building_load_state(file->allowed_buildings);
// scenario_custom_variable_load_state(file->custom_variables);
Expand Down Expand Up @@ -714,7 +715,7 @@ static void scenario_save_to_state(scenario_state *file)
scenario_save_state(file->scenario);
scenario_request_save_state(file->requests);
scenario_invasion_save_state(file->invasions);
// scenario_demand_change_save_state(file->demand_changes);
scenario_demand_change_save_state(file->demand_changes);
// scenario_price_change_save_state(file->price_changes);
// scenario_building_save_state(file->allowed_buildings);
// scenario_custom_variable_save_state(file->custom_variables);
Expand Down Expand Up @@ -764,7 +765,7 @@ static void savegame_load_from_state(savegame_state *state, savegame_version_t v

if (scenario_version > SCENARIO_LAST_STATIC_ORIGINAL_DATA) {
scenario_invasion_load_state(state->invasions);
// scenario_demand_change_load_state(state->demand_changes);
scenario_demand_change_load_state(state->demand_changes);
// scenario_price_change_load_state(state->price_changes);
// scenario_building_load_state(state->allowed_buildings);
// scenario_custom_variable_load_state(state->custom_variables);
Expand Down
18 changes: 1 addition & 17 deletions src/scenario/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

#include <stdint.h>

#define MAX_DEMAND_CHANGES 20
#define MAX_PRICE_CHANGES 20
#define MAX_CUSTOM_VARIABLES 100

Expand Down Expand Up @@ -95,17 +94,6 @@ typedef struct {
int is_rise;
} price_change_t;

typedef struct {
int year;
int month;
int resource;
int route_id;
int amount;
} demand_change_t;

#define DEMAND_CHANGE_LEGACY_IS_RISE 9999
#define DEMAND_CHANGE_LEGACY_IS_FALL -9999

typedef struct {
struct win_criteria_t population;
struct win_criteria_t culture;
Expand Down Expand Up @@ -166,9 +154,7 @@ extern struct scenario_t {

custom_variable_t custom_variables[MAX_CUSTOM_VARIABLES];

demand_change_t demand_changes[MAX_DEMAND_CHANGES];

price_change_t price_changes[MAX_DEMAND_CHANGES];
price_change_t price_changes[MAX_PRICE_CHANGES];

struct {
int severity;
Expand Down Expand Up @@ -234,8 +220,6 @@ extern struct scenario_t {
/** Temp storage for carrying over player name to next campaign mission */
uint8_t player_name[MAX_PLAYER_NAME];
} campaign;

int is_saved;
} scenario;

#endif // SCENARIO_DATA_H
212 changes: 177 additions & 35 deletions src/scenario/demand_change.c
Original file line number Diff line number Diff line change
@@ -1,57 +1,199 @@
#include "demand_change.h"

#include "city/message.h"
#include "core/array.h"
#include "core/log.h"
#include "core/random.h"
#include "empire/city.h"
#include "empire/trade_route.h"
#include "game/time.h"
#include "scenario/data.h"
#include "scenario/property.h"

#define DEMAND_CHANGES_ARRAY_SIZE_STEP 16

#define DEMAND_CHANGES_STRUCT_SIZE_CURRENT (1 * sizeof(int32_t) + 1 * sizeof(int16_t) + 3 * sizeof(uint8_t))


static array(demand_change_t) demand_changes;

static void new_demand_change(demand_change_t *demand_change, int index)
{
demand_change->id = index;
}

static int demand_change_in_use(const demand_change_t *demand_change)
{
return demand_change->year != 0;
}

void scenario_demand_change_clear_all(void)
{
if (!array_init(demand_changes, DEMAND_CHANGES_ARRAY_SIZE_STEP, new_demand_change, demand_change_in_use)) {
log_error("Problem creating demand changes array - memory full. The gane will now crash.", 0, 0);
}
}

void scenario_demand_change_init(void)
{
for (int i = 0; i < MAX_DEMAND_CHANGES; i++) {
demand_change_t *demand_change;
array_foreach(demand_changes, demand_change) {
random_generate_next();
if (scenario.demand_changes[i].year) {
scenario.demand_changes[i].month = (random_byte() & 7) + 2;
if (demand_change->year) {
demand_change->month = (random_byte() & 7) + 2;
}
}
}

void scenario_demand_change_process(void)
int scenario_demand_change_new(void)
{
for (int i = 0; i < MAX_DEMAND_CHANGES; i++) {
if (!scenario.demand_changes[i].year) {
continue;
}
if (game_time_year() != scenario.demand_changes[i].year + scenario.start_year ||
game_time_month() != scenario.demand_changes[i].month) {
continue;
}
int route = scenario.demand_changes[i].route_id;
int resource = scenario.demand_changes[i].resource;
int city_id = empire_city_get_for_trade_route(route);
if (city_id < 0) {
city_id = 0;
demand_change_t *demand_change;
array_new_item(demand_changes, 0, demand_change);
return demand_change ? demand_change->id : -1;
}

static void process_demand_change(demand_change_t *demand_change)
{
if (!demand_change->year) {
return;
}
if (game_time_year() != demand_change->year + scenario_property_start_year() ||
game_time_month() != demand_change->month) {
return;
}
int route = demand_change->route_id;
int resource = demand_change->resource;
int city_id = empire_city_get_for_trade_route(route);
if (city_id < 0) {
city_id = 0;
}

int last_amount = trade_route_limit(route, resource);
int amount = demand_change->amount;
if (amount == DEMAND_CHANGE_LEGACY_IS_RISE) {
amount = trade_route_legacy_increase_limit(route, resource);
} else if (amount == DEMAND_CHANGE_LEGACY_IS_FALL) {
amount = trade_route_legacy_decrease_limit(route, resource);
} else {
trade_route_set_limit(route, resource, amount);
}
if (empire_city_is_trade_route_open(route)) {
int change = amount - last_amount;
if (amount > 0 && change > 0) {
city_message_post(1, MESSAGE_INCREASED_TRADING, city_id, resource);
} else if (amount > 0 && change < 0) {
city_message_post(1, MESSAGE_DECREASED_TRADING, city_id, resource);
} else if (amount <= 0) {
city_message_post(1, MESSAGE_TRADE_STOPPED, city_id, resource);
}
}
}

void scenario_demand_change_process(void)
{
array_foreach_callback(demand_changes, process_demand_change);
}

const demand_change_t *scenario_demand_change_get(int id)
{
return array_item(demand_changes, id);
}

int last_amount = trade_route_limit(route, resource);
int amount = scenario.demand_changes[i].amount;
if (amount == DEMAND_CHANGE_LEGACY_IS_RISE) {
amount = trade_route_legacy_increase_limit(route, resource);
} else if (amount == DEMAND_CHANGE_LEGACY_IS_FALL) {
amount = trade_route_legacy_decrease_limit(route, resource);
} else {
trade_route_set_limit(route, resource, amount);
void scenario_demand_change_update(int id, const demand_change_t *demand_change)
{
demand_change_t *base_demand_change = array_item(demand_changes, id);
*base_demand_change = *demand_change;
base_demand_change->id = id;
array_trim(demand_changes);
}

void scenario_demand_change_delete(int id)
{
demand_change_t *demand_change = array_item(demand_changes, id);
memset(demand_change, 0, sizeof(demand_change_t));
array_trim(demand_changes);
}

void scenario_demand_change_remap_resource(void)
{
demand_change_t *demand_change;
array_foreach(demand_changes, demand_change) {
demand_change->resource = resource_remap(demand_change->resource);
}
}

int scenario_demand_change_count_total(void)
{
return demand_changes.size;
}

void scenario_demand_change_save_state(buffer *buf)
{
buffer_init_dynamic_piece(buf, 0, demand_changes.size, DEMAND_CHANGES_STRUCT_SIZE_CURRENT);

const demand_change_t *demand_change;
array_foreach(demand_changes, demand_change) {
buffer_write_i16(buf, demand_change->year);
buffer_write_u8(buf, demand_change->month);
buffer_write_u8(buf, demand_change->resource);
buffer_write_u8(buf, demand_change->route_id);
buffer_write_i32(buf, demand_change->amount);
}
}

void scenario_demand_change_load_state(buffer *buf)
{
int size;

buffer_load_dynamic_piece_header_data(buf, 0, 0, &size, 0);

if (!array_init(demand_changes, DEMAND_CHANGES_ARRAY_SIZE_STEP, new_demand_change, demand_change_in_use) ||
!array_expand(demand_changes, size)) {
log_error("Problem creating demand changes array - memory full. The gane will now crash.", 0, 0);
}

for (int i = 0; i < size; i++) {
demand_change_t *demand_change = array_next(demand_changes);
demand_change->year = buffer_read_i16(buf);
demand_change->month = buffer_read_u8(buf);
demand_change->resource = buffer_read_u8(buf);
demand_change->route_id = buffer_read_u8(buf);
demand_change->amount = buffer_read_i32(buf);
}

array_trim(demand_changes);
}

void scenario_demand_change_load_state_old_version(buffer *buf, int is_legacy_change)
{
if (!array_init(demand_changes, DEMAND_CHANGES_ARRAY_SIZE_STEP, new_demand_change, demand_change_in_use) ||
!array_expand(demand_changes, MAX_ORIGINAL_DEMAND_CHANGES)) {
log_error("Problem creating demand changes array - memory full. The gane will now crash.", 0, 0);
}
for (size_t i = 0; i < MAX_ORIGINAL_DEMAND_CHANGES; i++) {
array_advance(demand_changes);
}
demand_change_t *demand_change;
array_foreach(demand_changes, demand_change) {
demand_change->year = buffer_read_i16(buf);
}
array_foreach(demand_changes, demand_change) {
demand_change->month = buffer_read_u8(buf);
}
array_foreach(demand_changes, demand_change) {
demand_change->resource = buffer_read_u8(buf);
}
array_foreach(demand_changes, demand_change) {
demand_change->route_id = buffer_read_u8(buf);
}
if (is_legacy_change) {
array_foreach(demand_changes, demand_change) {
int is_rise = buffer_read_u8(buf);
int amount = is_rise ? DEMAND_CHANGE_LEGACY_IS_RISE : DEMAND_CHANGE_LEGACY_IS_FALL;
demand_change->amount = amount;
}
if (empire_city_is_trade_route_open(route)) {
int change = amount - last_amount;
if (amount > 0 && change > 0) {
city_message_post(1, MESSAGE_INCREASED_TRADING, city_id, resource);
} else if (amount > 0 && change < 0) {
city_message_post(1, MESSAGE_DECREASED_TRADING, city_id, resource);
} else if (amount <= 0) {
city_message_post(1, MESSAGE_TRADE_STOPPED, city_id, resource);
}
} else {
array_foreach(demand_changes, demand_change) {
demand_change->amount = buffer_read_i32(buf);
}
}
}
Loading

0 comments on commit de4f89d

Please sign in to comment.