diff --git a/src/building/building.c b/src/building/building.c index 630bb0d67f..4cd10dfa33 100644 --- a/src/building/building.c +++ b/src/building/building.c @@ -172,21 +172,6 @@ static void remove_adjacent_types(building *b) b->next_of_type = 0; } -void initialize_sentiment_cooldown(building *b) { - if (b->house_adv_sentiment.cooldown_initialized) { - return; - } - - b->house_adv_sentiment.cooldown_initialized = 1; - - if (b->type <= BUILDING_HOUSE_GRAND_INSULA) { - b->house_adv_sentiment.cooldown = ADVANCED_SENTIMENT_COOLDOWN_MAX_TICKS; - } else { - // Do not apply cooldown to villas - b->house_adv_sentiment.cooldown = 0; - } -} - building *building_create(building_type type, int x, int y) { building *b; @@ -220,7 +205,7 @@ building *building_create(building_type type, int x, int y) // subtype if (building_is_house(type)) { - initialize_sentiment_cooldown(b); + b->cooldown_advanced_sentiment = type < BUILDING_HOUSE_SMALL_VILLA ? ADVANCED_SENTIMENT_COOLDOWN_TICKS : 0; b->subtype.house_level = type - BUILDING_HOUSE_VACANT_LOT; } diff --git a/src/building/building.h b/src/building/building.h index 6f742575ac..f8345d4cf3 100644 --- a/src/building/building.h +++ b/src/building/building.h @@ -8,12 +8,8 @@ #include "translation/translation.h" // Ticks of cooldown before new advanced sentiment logic will be applied -// for the house building. Each tick is equal to 3 months. That value -// shouldn't ever exceed 7, since it takes 3 bits of data. -// To extend or reduce the cooldown duration edit the -// ADVANCED_SENTIMENT_COOLDOWN_TICK_MONTHS preprocessor definition. -#define ADVANCED_SENTIMENT_COOLDOWN_MAX_TICKS 7 -#define ADVANCED_SENTIMENT_COOLDOWN_TICK_MONTHS 3 +// for the house building. Each tick is equal to 8 days (half of month). +#define ADVANCED_SENTIMENT_COOLDOWN_TICKS 36 typedef enum order_condition_type { ORDER_CONDITION_NEVER = 0, @@ -22,12 +18,6 @@ typedef enum order_condition_type { ORDER_CONDITION_DESTINATION_HAS_LESS_THAN } order_condition_type; -typedef struct advanced_sentiment { - uint8_t cooldown_initialized: 1; - uint8_t cooldown: 3; - uint8_t reserved: 4; -} advanced_sentiment; - typedef struct order { resource_type resource_type; int src_storage_id; @@ -194,11 +184,7 @@ typedef struct building { signed char house_happiness; signed char native_anger; } sentiment; - // New advanced sentiment contribution logic requires cooldown for newly built houses. - // The new happiness gain/drop logic will not be applied until cooldown expires. - // Cooldown ticks get decreased every Jan/Apr/Jul/Oct, which gives 18-20 months in total. - // That should be enough to build new housing block and evolve it. - struct advanced_sentiment house_adv_sentiment; + uint8_t cooldown_advanced_sentiment; unsigned char show_on_problem_overlay; unsigned char house_tavern_wine_access; unsigned char house_tavern_food_access; @@ -239,8 +225,6 @@ building *building_main(building *b); building *building_next(building *b); -void initialize_sentiment_cooldown(building *b); - building *building_create(building_type type, int x, int y); void building_clear_related_data(building *b); diff --git a/src/building/state.c b/src/building/state.c index 0663c13d70..0e1dad05af 100644 --- a/src/building/state.c +++ b/src/building/state.c @@ -167,11 +167,10 @@ void building_state_save_to_buffer(buffer *buf, const building *b) buffer_write_u8(buf, b->storage_id); buffer_write_i8(buf, b->sentiment.house_happiness); // which union field we use does not matter - assert (sizeof(b->house_adv_sentiment) == sizeof(uint8_t)); if (building_is_house(b->type)) { - buffer_write_raw(buf, &b->house_adv_sentiment, sizeof(b->house_adv_sentiment)); + buffer_write_u8(buf, b->cooldown_advanced_sentiment); } else { - buffer_skip(buf, sizeof(b->house_adv_sentiment)); + buffer_skip(buf, sizeof(b->cooldown_advanced_sentiment)); } buffer_write_u8(buf, b->show_on_problem_overlay); @@ -505,9 +504,9 @@ void building_state_load_from_buffer(buffer *buf, building *b, int building_buf_ b->sentiment.house_happiness = buffer_read_i8(buf); // which union field we use does not matter if (save_version >= SAVE_GAME_LAST_ADVANCED_SENTIMENT) { if (building_is_house(b->type)) { - buffer_read_raw(buf, &b->house_adv_sentiment, sizeof(b->house_adv_sentiment)); + b->cooldown_advanced_sentiment = buffer_read_u8(buf); } else { - buffer_skip(buf, sizeof(b->house_adv_sentiment)); + buffer_skip(buf, sizeof(b->cooldown_advanced_sentiment)); } } b->show_on_problem_overlay = buffer_read_u8(buf); @@ -709,8 +708,4 @@ void building_state_load_from_buffer(buffer *buf, building *b, int building_buf_ if (building_buf_size > BUILDING_STATE_CURRENT_BUFFER_SIZE) { buffer_skip(buf, building_buf_size - BUILDING_STATE_CURRENT_BUFFER_SIZE); } - - if (building_is_house(b->type)) { - initialize_sentiment_cooldown(b); - } } diff --git a/src/building/state.h b/src/building/state.h index a5bf163d51..f8b7ac5934 100644 --- a/src/building/state.h +++ b/src/building/state.h @@ -11,11 +11,11 @@ #define BUILDING_STATE_TOURISM_BUFFER_SIZE (BUILDING_STATE_ORIGINAL_BUFFER_SIZE + 6) // 134 #define BUILDING_STATE_VARIANTS_AND_UPGRADES (BUILDING_STATE_TOURISM_BUFFER_SIZE + 2) // 136 #define BUILDING_STATE_STRIKES (BUILDING_STATE_VARIANTS_AND_UPGRADES + 1) // 137 -#define BUILDING_STATE_ADV_SENTIMENT (BUILDING_STATE_STRIKES + sizeof(advanced_sentiment)) // 138 -#define BUILDING_STATE_SICKNESS (BUILDING_STATE_ADV_SENTIMENT + 5) // 143 -#define BUILDING_STATE_WITHOUT_RESOURCES (BUILDING_STATE_SICKNESS - RESOURCE_MAX_LEGACY) // 127 (plus variable resource size) +#define BUILDING_STATE_SICKNESS (BUILDING_STATE_ADV_SENTIMENT + 5) // 142 +#define BUILDING_STATE_WITHOUT_RESOURCES (BUILDING_STATE_SICKNESS - RESOURCE_MAX_LEGACY) // 126 (plus variable resource size) #define BUILDING_STATE_DYNAMIC_RESOURCES (BUILDING_STATE_WITHOUT_RESOURCES + BUILDING_STATE_NONSTATIC_RESOURCE_SIZE) #define BUILDING_STATE_CURRENT_BUFFER_SIZE (BUILDING_STATE_DYNAMIC_RESOURCES + 8) +#define BUILDING_STATE_ADV_SENTIMENT (BUILDING_STATE_STRIKES + sizeof(uint8_t)) void building_state_save_to_buffer(buffer *buf, const building *b); diff --git a/src/city/sentiment.c b/src/city/sentiment.c index eb42ab3c6b..fac4ec657e 100644 --- a/src/city/sentiment.c +++ b/src/city/sentiment.c @@ -37,6 +37,13 @@ #define IMPERIAL_GAMES_SENTIMENT_BONUS 15 #define POP_STEP_FOR_BASE_AVERAGE_HOUSE_LEVEL 625 +#define min(a,b) \ +({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; \ +}) + // New advanced sentiment change calculation applies only after configured months // of gameplay has passed. This is required to prevent very fast sentiment drop // by high unemployment at very early game @@ -341,36 +348,34 @@ const int advanced_sentiment_drop_modifier[5] = { 50 // Very Hard }; -// Checks if house building still has a cooldown before apply advanced sentiment change logic -int check_house_advanced_sentiment_change_cooldown(building *b, int update_sentiment_cooldown) { - if (!building_is_house(b->type) || !b->house_adv_sentiment.cooldown_initialized) { +// Updates house building sentiment cooldown by delta value. +// Returns 1 if advanced sentiment logic should be applied to house and 0 if not +int update_house_advanced_sentiment_cooldown(building *b, int sentiment_cooldown_delta) { + if (!building_is_house(b->type)) { return 0; } - if (b->type > BUILDING_HOUSE_GRAND_INSULA) { + if (b->type >= BUILDING_HOUSE_SMALL_VILLA) { // Reset cooldown for villas - b->house_adv_sentiment.cooldown = 0; - } else if (b->type == BUILDING_HOUSE_VACANT_LOT && b->house_adv_sentiment.cooldown == ADVANCED_SENTIMENT_COOLDOWN_MAX_TICKS) { + b->cooldown_advanced_sentiment = 0; + } else if (b->type == BUILDING_HOUSE_VACANT_LOT) { // Wait for new citizens to arrive - return 1; + return 0; } - if (update_sentiment_cooldown && - b->house_adv_sentiment.cooldown && - game_time_month() % ADVANCED_SENTIMENT_COOLDOWN_TICK_MONTHS == 0) { - // Decrease tick once configured amount of game months has passed. - b->house_adv_sentiment.cooldown--; + if (sentiment_cooldown_delta > 0 && b->cooldown_advanced_sentiment > 0) { + b->cooldown_advanced_sentiment -= min(sentiment_cooldown_delta, b->cooldown_advanced_sentiment); } - if (!b->house_adv_sentiment.cooldown) { + if (!b->cooldown_advanced_sentiment) { // Cooldown has ended - return 0; + return 1; } - return 1; + return 0; } -void city_sentiment_update(int update_sentiment_cooldown) +void city_sentiment_update(int sentiment_cooldown_delta) { city_population_check_consistency(); @@ -448,13 +453,14 @@ void city_sentiment_update(int update_sentiment_cooldown) // Change sentiment gradually to the new value int sentiment_delta = sentiment - b->sentiment.house_happiness; if (sentiment_delta != 0 && - apply_advanced_sentiment_change && - !check_house_advanced_sentiment_change_cooldown(b, update_sentiment_cooldown)) { + update_house_advanced_sentiment_cooldown(b, sentiment_cooldown_delta) && + apply_advanced_sentiment_change + ) { // With new advanced logic we introduce faster sentiment change when the target value is // far away from current happiness level. The final change value depends on difficulty settings. // Example #1: // Current house happiness level is 82, the new sentiment value is 10 and the delta is -72. - // The final happiness change for VeryHard mode will be -28 (40% of -72). + // The final happiness change for VeryHard mode will be -36 (50% of -72). // Example #2: // Current house happiness level is 20, the new sentiment value is 77 and the delta is 57. // The final happiness change for Hard mode will be 9 (17% of 57). diff --git a/src/city/sentiment.h b/src/city/sentiment.h index 02db1c9ba6..a159280f58 100644 --- a/src/city/sentiment.h +++ b/src/city/sentiment.h @@ -25,6 +25,6 @@ void city_sentiment_reduce_crime_cooldown(void); int city_sentiment_get_blessing_festival_boost(void); void city_sentiment_decrement_blessing_boost(void); -void city_sentiment_update(int update_sentiment_cooldown); +void city_sentiment_update(int sentiment_cooldown_delta); #endif // CITY_SENTIMENT_H diff --git a/src/game/tick.c b/src/game/tick.c index 60eda1186d..48e5ea3b1d 100644 --- a/src/game/tick.c +++ b/src/game/tick.c @@ -130,9 +130,8 @@ static void advance_day(void) if (game_time_advance_day()) { advance_month(); } - int update_sentiment_cooldown = game_time_day() == 0; - if (update_sentiment_cooldown || game_time_day() == 8) { - city_sentiment_update(update_sentiment_cooldown); + if (game_time_day() == 0 || game_time_day() == 8) { + city_sentiment_update(1); } if (game_time_day() == 0 || game_time_day() == 7) { building_lighthouse_consume_timber();