Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handgold and payday rules #3847

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 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
16 changes: 15 additions & 1 deletion config/fxdata/rules.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ PayDayGap = 10000
; How fast pay day comes percentage.
PayDaySpeed = 100
; How many game turns between the heart recovering health.
MaxPaydaysAdvanced = 5
; Amount of paydays the creatures can be paid in advance.
; 0 = Creatures goes always to the treasure room.
MaxPaydaysOwed = 5
; Amount of paydays the creatures can be in debt. 0/255
; 0 = Creatures ignores all paydays
AcceptPartialPayday = 1
; (Orginal Behaviour) Creatures will accept any amount of gold given from hand (or pocket if enabled) 0/255
; to skip current and any payday in advance. 0/1
PocketGold = 0
; Creatures will carry gold in their pockets when manually given by the player. 0/1
TakePayFromPocket = 0
; Creatures will first use any gold in their pockets for their payday before going to the treasury. 0/1

DungeonHeartHealTime = 8
; How much health the heart recovers. Or loses when negative.
DungeonHeartHealHealth = 4
Expand Down Expand Up @@ -72,7 +86,7 @@ EasterEggSpeechInterval = 20000
; STUN_FRIENDLY_UNITS - Infighting with imprisonment on will not kill your creatures.
; PASSIVE_NEUTRALS - Neutral creatures placed in prison or torture room wander out.
; NEUTRAL_TORTURE_CONVERTS - Neutral torture rooms convert creatures into neutral creatures.
PreserveClassicBugs =
PreserveClassicBugs =

[computer]
; Maximum health percentage when creatures are considered to be put to temple to cure of disease.
Expand Down
13 changes: 11 additions & 2 deletions src/config_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,13 @@ const struct NamedField rules_game_named_fields[] = {
{"GLOBALAMBIENTLIGHT", &game.conf.rules.game.global_ambient_light, var_type(game.conf.rules.game.global_ambient_light ), LONG_MIN, LONG_MAX},
{"LIGHTENABLED", &game.conf.rules.game.light_enabled, var_type(game.conf.rules.game.light_enabled ), 0, 1},
{"MAPCREATURELIMIT", &game.conf.rules.game.creatures_count, var_type(game.conf.rules.game.creatures_count ), 0, CREATURES_COUNT-2},
{"PAYDAYADVANCED", &game.conf.rules.game.max_paydays_advanced, var_type(game.conf.rules.game.max_paydays_advanced ), 0, UCHAR_MAX},
{"PAYDAYOWED", &game.conf.rules.game.max_paydays_owed, var_type(game.conf.rules.game.max_paydays_owed ), 0, UCHAR_MAX},
{"ACCEPTPARTIALPAYDAY", &game.conf.rules.game.accept_partial_payday, var_type(game.conf.rules.game.accept_partial_payday ), 0, 1},
{"POCKETGOLD", &game.conf.rules.game.pocket_gold, var_type(game.conf.rules.game.pocket_gold ), 0, 1},
{"TAKEPAYFROMPOCKET", &game.conf.rules.game.take_pay_from_pocket, var_type(game.conf.rules.game.take_pay_from_pocket ), 0, 1},
{NULL, NULL, 0, 0, 0},
};

// Special cases rules_game.
const struct NamedCommand rules_game_commands[] = {
{"PRESERVECLASSICBUGS", 1},
Expand Down Expand Up @@ -292,6 +296,11 @@ static void set_defaults()
game.conf.rules.game.torture_training_cost = 100;
game.conf.rules.game.torture_scavenging_cost = 100;
game.conf.rules.game.creatures_count = 255;
game.conf.rules.game.max_paydays_advanced = 5;
game.conf.rules.game.max_paydays_owed = 5;
game.conf.rules.game.accept_partial_payday = true;
game.conf.rules.game.pocket_gold = false;
game.conf.rules.game.take_pay_from_pocket = false;
// Creature block.
game.conf.rules.creature.recovery_frequency = 10;
game.conf.rules.creature.fight_max_hate = 200;
Expand Down Expand Up @@ -616,7 +625,7 @@ static void mark_cheaper_diggers_sacrifice(void)
struct SacrificeRecipe* sac = &game.conf.rules.sacrifices.sacrifice_recipes[i];
if (sac->action == SacA_None)
continue;
if (((sac->action == SacA_PosUniqFunc) && (sac->param == UnqF_CheaperImp))
if (((sac->action == SacA_PosUniqFunc) && (sac->param == UnqF_CheaperImp))
|| ((sac->action == SacA_NegUniqFunc) && (sac->param == UnqF_CostlierImp)))
{
if ((sac->victims[1] == 0) && (game.conf.rules.sacrifices.cheaper_diggers_sacrifice_model == 0)) {
Expand Down
5 changes: 5 additions & 0 deletions src/config_rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ struct GameRulesConfig {
long global_ambient_light;
TbBool light_enabled;
unsigned short creatures_count;
unsigned char max_paydays_advanced;
unsigned char max_paydays_owed;
TbBool accept_partial_payday;
TbBool pocket_gold;
TbBool take_pay_from_pocket;
};

struct ComputerRulesConfig {
Expand Down
1 change: 1 addition & 0 deletions src/creature_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ struct CreatureControl {
unsigned char thought_bubble_display_timer;
unsigned char paydays_owed;
char paydays_advanced;
GoldAmount paid_wage;
long annoy_untrained_turn;
unsigned long last_roar_turn;
/** The game enumerates the elements of annoyance array periodically and looks for the highest value.
Expand Down
112 changes: 105 additions & 7 deletions src/creature_states.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ TbBool creature_is_called_to_arms(const struct Thing *thing)
TbBool creature_is_taking_salary_activity(const struct Thing *thing)
{
CrtrStateId crstate = get_creature_state_besides_move(thing);
if ((crstate == CrSt_CreatureWantsSalary) || (crstate == CrSt_CreatureTakeSalary))
if ((crstate == CrSt_CreatureWantsSalary) || (crstate == CrSt_CreatureTakeSalary) || (crstate == CrSt_CreatureWaitAtTreasureRoomDoor))
return true;
return false;
}
Expand Down Expand Up @@ -3018,6 +3018,8 @@ short creature_pick_up_spell_to_steal(struct Thing *creatng)

short creature_take_salary(struct Thing *creatng)
{
GoldAmount salary = calculate_correct_creature_pay(creatng);
struct CreatureControl* cctrl = creature_control_get_from_thing(creatng);
TRACE_THING(creatng);
SYNCDBG(18,"Starting");
if (!thing_is_on_own_room_tile(creatng))
Expand All @@ -3033,7 +3035,11 @@ short creature_take_salary(struct Thing *creatng)
internal_set_thing_state(creatng, CrSt_CreatureWantsSalary);
return 1;
}
GoldAmount salary = calculate_correct_creature_pay(creatng);
// Creature take salary first out of her own pocket
if(game.conf.rules.game.take_pay_from_pocket || !game.conf.rules.game.accept_partial_payday){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is 'not partial payday' here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If allowed with accept_partial_payday,
creatures would take the full salary even if they were already partially paid

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but by accepting partial paydays, you would always take 0 payday next payday on any cash right? So would it not need to be fully excluded before this point?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not about excluding accept_partial_payday, but rather about allowing !accept_partial_payday so that in this case the salary is calculated differently.

salary -= cctrl->paid_wage;
cctrl->paid_wage = 0;
}
GoldAmount received = take_money_from_dungeon(creatng->owner, salary, 0);
if (received < 1) {
ERRORLOG("The %s index %d has used capacity %d but no gold for %s salary",room_code_name(room->kind),
Expand All @@ -3042,15 +3048,20 @@ short creature_take_salary(struct Thing *creatng)
return 1;
} else
{
struct CreatureControl* cctrl = creature_control_get_from_thing(creatng);
if (cctrl->paydays_owed > 0)
{
cctrl->paydays_owed--;
}
if ((dungeon->total_money_owned >= salary) && (cctrl->paydays_advanced < 0)) //If the creature has missed payday, and there is money again, time to pay up.
{
cctrl->paydays_owed++;
cctrl->paydays_advanced++;
if (cctrl->paydays_owed < game.conf.rules.game.max_paydays_owed)
{
cctrl->paydays_owed++;
}
if (cctrl->paydays_advanced < game.conf.rules.game.max_paydays_advanced)
{
cctrl->paydays_advanced++;
}
}
}
set_start_state(creatng);
Expand Down Expand Up @@ -4943,6 +4954,78 @@ long creature_setup_head_for_treasure_room_door(struct Thing *creatng, struct Ro
return 0;
}

/**
* @brief
* Used if take_pay_from_pocket rule is activated
*
* Attempts to deduct the creature's salary from its carried gold.
*
* - If partial paydays are allowed, the function subtracts as much as possible
* from the creature's pocket.
*
* - Otherwise, it tries to cover the full salary
* from the pocket and, if not enough, from the dungeon.
* @param creatng
* @return TbBool Returns true if enough gold is taken from the creature to handle the entaire payday
*/
TbBool process_custom_salary(struct Thing *creatng)
{
struct CreatureControl* cctrl = creature_control_get_from_thing(creatng);
// Calculate the correct salary for the creature.
GoldAmount salary = calculate_correct_creature_pay(creatng);
// Subtract any already given gold from the salary
salary -= cctrl->paid_wage;
struct Dungeon* dungeon = get_dungeon(creatng->owner);
if(creatng->creature.gold_carried > 0)
{
//Creature has enough gold to cover the salary or partial paydays are allowed.
if((creatng->creature.gold_carried >= salary) || (game.conf.rules.game.accept_partial_payday))
{
//Reduce the number of paydays owed
cctrl->paydays_owed--;
//Reset already given gold
cctrl->paid_wage = 0;
//Visual effect
struct Thing* efftng;
if(game.conf.rules.game.accept_partial_payday && (salary > creatng->creature.gold_carried))
{
efftng = create_price_effect(&creatng->mappos, creatng->owner, creatng->creature.gold_carried);
}
else
{
efftng = create_price_effect(&creatng->mappos, creatng->owner, salary);
}
//Take the salary from the creature pocket
creatng->creature.gold_carried -= salary;
//Ensure that the creature's gold carried does not drop below zero.
if (creatng->creature.gold_carried < 0)
{
creatng->creature.gold_carried = 0;
}
set_start_state(creatng);
//Play sound effect
thing_play_sample(efftng, 32, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS);
dungeon->lvstats.salary_cost += salary;
return 1;
}
//Continue to take the remaining salary from the dungeon
else
{
//Add carried gold to already paid gold
cctrl->paid_wage += creatng->creature.gold_carried;
//Visual effect
struct Thing* efftng = create_price_effect(&creatng->mappos, creatng->owner, creatng->creature.gold_carried);
//Sound effect
thing_play_sample(efftng, 32, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS);
//Reset carried gold
creatng->creature.gold_carried = 0;
//Creature continues to try to take the salary from the dungeon
return 0;
}
}
return 0;
}

long process_creature_needs_a_wage(struct Thing *creatng, const struct CreatureStats *crstat)
{
struct CreatureControl* cctrl = creature_control_get_from_thing(creatng);
Expand All @@ -4952,6 +5035,14 @@ long process_creature_needs_a_wage(struct Thing *creatng, const struct CreatureS
if (creature_is_taking_salary_activity(creatng)) {
return 1;
}
// rule activated
if(game.conf.rules.game.take_pay_from_pocket)
{
if(process_custom_salary(creatng))
{
return 1;
}
}
if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreatureWantsSalary)) {
return 0;
}
Expand Down Expand Up @@ -5122,10 +5213,17 @@ long anger_process_creature_anger(struct Thing *creatng, const struct CreatureSt
{
if ((dungeon->total_money_owned >= dungeon->creatures_total_backpay) && !room_is_invalid(room))
{
cctrl->paydays_advanced++;
if (cctrl->paydays_advanced < game.conf.rules.game.max_paydays_advanced)
{
cctrl->paydays_advanced++;
}
if (cctrl->paydays_owed < SCHAR_MAX)
{
cctrl->paydays_owed++; // if there's enough money to pay, go to treasure room now, instead of complaining
// if there's enough money to pay, go to treasure room now, instead of complaining
if (cctrl->paydays_owed < game.conf.rules.game.max_paydays_owed)
{
cctrl->paydays_owed++;
}
}
}
else
Expand Down
1 change: 1 addition & 0 deletions src/creature_states.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ SubtlCodedCoords find_position_around_in_room(const struct Coord3d *pos, PlayerN
void remove_health_from_thing_and_display_health(struct Thing *thing, HitPoints delta);

TbBool process_creature_hunger(struct Thing *thing);
TbBool process_custom_salary(struct Thing *creatng);
void process_person_moods_and_needs(struct Thing *thing);
TbBool restore_creature_flight_flag(struct Thing *creatng);
TbBool attempt_to_destroy_enemy_room(struct Thing *thing, MapSubtlCoord stl_x, MapSubtlCoord stl_y);
Expand Down
4 changes: 4 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2335,6 +2335,10 @@ void count_players_creatures_being_paid(int *creatures_count)
} else
{
cctrl->paydays_owed++;
if (cctrl->paydays_owed > game.conf.rules.game.max_paydays_owed)
{
cctrl->paydays_owed = game.conf.rules.game.max_paydays_owed;
}
creatures_count[thing->owner]++;
}
}
Expand Down
Loading