Bath House Bribes Blunders
Summary
The bath house bribes are affected by three different bugs:
- If a merchant's offer is lower than the councillor's expectations and the councillor hasn't been bribed by anyone else, the councillor is bribed by the merchant with the index
1
. - Annoying a councillor in one town affects councillors in all towns.
- Limits on the bribability don't have any effect.
Details
Attribution to Merchant 1
The handle_operation_bath_house_bribe_failure
function at 0x0053AD10
sets the councillor's briber to 1
, if the councillor was not already bribed by anyone.
This also prevents you from getting the "Are you there again?! Let me have my bath in peace, please." line you are supposed to get with annoyed councillors.
Instead you'll get the "Ah! You're here as well, John Doe? I have only very recently spoken to one of your competitors." line, since the councillor is now bribed by merchant 1
.
Unforgiving Bath Houses
The bath house remembers only the index of annoyed local councillors (0-3), and not to which town they belong. If you annoy the first councillor in one town, the first councillor in every town will stop talking to you, and so forth.
While the annoyed "Are you there again?! Let me have my bath in peace, please." line is unreachable in the correct town due to the attribution bug, you do get it if you encounter a councillor with the same index in a different town.
Limitless Corruption
The handle_operation_bath_house_bribe_success
function at 0x0053AC50
applies the briber only if a particular value is smaller than 2:
bribed_councillors = 0;
previous_bribing_merchant = static_game_world.field_68_towns[town_index].field_6DC_councillor_bribes[this->args.unknown.arg1];
v6 = 4;
do
{
if (previous_bribing_merchant == merchant_index)
++bribed_councillors;
--v6;
}
while (v6);
merchant = get_merchant(&static_game_world, merchant_index);
old_recent_donations = merchant->field_4BC_recent_donations;
merchant->field_0_money -= this->args.unknown.arg3;
merchant->field_4BC_recent_donations = this->args.unknown.arg3 + old_recent_donations;
merchant_bribe_success_increase_social_reputation(merchant, this->args.unknown.arg4, this->args.unknown.arg3);
if (bribed_councillors < 2) {
static_game_world.field_68_towns[this->args.unknown.arg4].field_6DC_councillor_bribes[this->args.unknown.arg1] = this->args.unknown.arg2;
}
Since neither previous_bribing_merchant
nor merchant_index
change during the loop, the final value of bribed_councillors
is always either 0 or 4.
This doesn't make any sense as it is, so it is assumed that bribed_councillors
was intended to be the amount of already bribed councillors in that town, and that the comparison with 2 was intended to prevent a player from bribing the majority of councillors in one town.
Fix
All bugs are fixed by the fix-bath-house-bribe-blunders mod.
Attribution to Merchant 1
The councillor's briber must be set to -1
instead of 1
if the bribe fails and the councillor is not bribed by anyone else.
The original instruction:
.text:0053AD85 mov byte ptr [ecx], 1
must be replaced with:
.text:0053AD85 mov byte ptr [ecx], -1
Unforgiving Bath Houses
This cannot be properly fixed easily. However, resetting the annoyance when opening the bath house is just a small change. Since the annoyances are reset if the bath house is not opened for 256 ticks, one can replace the conditional jump around the reset code with nops:
.text:005B17B7 jbe short loc_5B17CC
Limitless Corruption
This issue is fixed by moving the previous_bribing_merchant
assignment into the loop and using the loop counter instead of the argument to index the bribes array.
Footnotes
Since the probability of each councillor appearing is just 7%, you can use the debug bath house IDC script to change it to 100%.