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

Add function calculate_correct_creature_max_health to fix issue with modifier #3716

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
28 changes: 17 additions & 11 deletions src/creature_states_lair.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,42 +512,48 @@ long room_has_slab_adjacent(const struct Room *room, long slbkind)

short creature_sleep(struct Thing *thing)
{
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
if (creature_affected_by_slap(thing) || !creature_will_sleep(thing)) {
struct CreatureControl *cctrl = creature_control_get_from_thing(thing);
if (creature_affected_by_slap(thing) || !creature_will_sleep(thing))
{
set_start_state(thing);
return 0;
}
struct Room* room = get_room_thing_is_on(thing);
if (room_is_invalid(room) || (!room_role_matches(room->kind,get_room_role_for_job(Job_TAKE_SLEEP)))
|| (cctrl->lair_room_id != room->index) || (room->owner != thing->owner)) {
struct Room *room = get_room_thing_is_on(thing);
if (room_is_invalid(room)
|| (!room_role_matches(room->kind, get_room_role_for_job(Job_TAKE_SLEEP)))
|| (cctrl->lair_room_id != room->index)
|| (room->owner != thing->owner))
{
set_start_state(thing);
return 0;
}
thing->movement_flags &= ~0x0020;
struct CreatureStats* crstat = creature_stats_get_from_thing(thing);
struct CreatureStats *crstat = creature_stats_get_from_thing(thing);
// Recovery is disabled if frequency is set to 0 on rules.cfg.
if (game.conf.rules.creature.recovery_frequency > 0)
{
if (((game.play_gameturn + thing->index) % game.conf.rules.creature.recovery_frequency) == 0)
{
HitPoints recover = compute_creature_max_health(crstat->sleep_recovery, cctrl->explevel, thing->owner);
HitPoints recover = compute_creature_max_health(crstat->sleep_recovery, cctrl->explevel);
apply_health_to_thing_and_display_health(thing, recover);
}
}
anger_set_creature_anger(thing, 0, AngR_NoLair);
anger_apply_anger_to_creature(thing, crstat->annoy_sleeping, AngR_Other, 1);
if (cctrl->turns_at_job > 0) {
if (cctrl->turns_at_job > 0)
{
cctrl->turns_at_job--;
}
if (((game.play_gameturn + thing->index) & 0x3F) == 0)
{
if (CREATURE_RANDOM(thing, 100) < 5) {
struct Dungeon* dungeon = get_dungeon(thing->owner);
if (CREATURE_RANDOM(thing, 100) < 5)
{
struct Dungeon *dungeon = get_dungeon(thing->owner);
dungeon->lvstats.backs_stabbed++;
}
}
if (crstat->sleep_exp_slab != SlbT_ROCK)
{
{ // To think about: Should SlbT_ROCK be ignored? Settings the experience gain to 0 is enough to disable the feature.
if (creature_can_gain_experience(thing) && room_has_slab_adjacent(room, crstat->sleep_exp_slab))
{
cctrl->exp_points += crstat->sleep_experience;
Expand Down
12 changes: 8 additions & 4 deletions src/creature_states_spdig.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,17 +1502,21 @@ short imp_toking(struct Thing *creatng)
}
if (cctrl->instance_id == CrInst_NULL)
{
if ( CREATURE_RANDOM(creatng, 8) )
if (CREATURE_RANDOM(creatng, 8))
{
set_creature_instance(creatng, CrInst_RELAXING, 0, 0);
}
else
{
set_creature_instance(creatng, CrInst_TOKING, 0, 0);
}
}

if ((cctrl->instance_id == CrInst_TOKING) && (cctrl->inst_turn == cctrl->inst_action_turns))
{
struct CreatureStats* crstat = creature_stats_get_from_thing(creatng);
if (crstat->toking_recovery != 0) {
HitPoints recover = compute_creature_max_health(crstat->toking_recovery, cctrl->explevel, creatng->owner);
if (crstat->toking_recovery != 0)
{
HitPoints recover = compute_creature_max_health(crstat->toking_recovery, cctrl->explevel);
apply_health_to_thing_and_display_health(creatng, recover);
}
}
Expand Down
38 changes: 21 additions & 17 deletions src/creature_states_tortr.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,10 +499,10 @@ long compute_torture_broke_chance(const struct Thing *thing)
CrCheckRet process_torture_function(struct Thing *creatng)
{
long i;
struct Room* room = get_room_creature_works_in(creatng);
if ( !room_still_valid_as_type_for_thing(room,RoRoF_Torture,creatng) )
struct Room *room = get_room_creature_works_in(creatng);
if (!room_still_valid_as_type_for_thing(room, RoRoF_Torture, creatng))
{
WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->owner);
WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d", room_code_name(room->kind), (int)room->owner, thing_model_name(creatng), (int)creatng->owner);
set_start_state(creatng);
return CrCkRet_Continue;
}
Expand All @@ -513,16 +513,16 @@ CrCheckRet process_torture_function(struct Thing *creatng)
return CrCkRet_Available;
}
}
struct CreatureStats* crstat = creature_stats_get_from_thing(creatng);
struct CreatureControl* cctrl = creature_control_get_from_thing(creatng);
struct CreatureStats *crstat = creature_stats_get_from_thing(creatng);
struct CreatureControl *cctrl = creature_control_get_from_thing(creatng);
anger_apply_anger_to_creature(creatng, crstat->annoy_in_torture, AngR_Other, 1);
if ((long)game.play_gameturn >= cctrl->turns_at_job + game.conf.rules.health.turns_per_torture_health_loss)
{
i = compute_creature_max_health(game.conf.rules.health.torture_health_loss,cctrl->explevel,creatng->owner);
remove_health_from_thing_and_display_health(creatng, i);
HitPoints torture_damage = compute_creature_max_health(game.conf.rules.health.torture_health_loss, cctrl->explevel);
remove_health_from_thing_and_display_health(creatng, torture_damage);
cctrl->turns_at_job = (long)game.play_gameturn;
}
// Check if we should convert the creature into ghost
// Check if we should convert the creature into ghost.
if ((creatng->health < 0) && (game.conf.rules.rooms.ghost_convert_chance > 0))
{
if (CREATURE_RANDOM(creatng, 100) < game.conf.rules.rooms.ghost_convert_chance)
Expand All @@ -531,32 +531,36 @@ CrCheckRet process_torture_function(struct Thing *creatng)
return CrCkRet_Deleted;
}
}
// Other torture functions are available only when torturing enemies
// Other torture functions are available only when torturing enemies.
if (room->owner == creatng->owner)
{
return CrCkRet_Available;
// Torture must take some time before it has any affect
i = compute_torture_convert_time(creatng,room);
if ( (i < crstat->torture_break_time) || (cctrl->tortured.assigned_torturer == 0) )
}
// Torture must take some time before it has any affect.
i = compute_torture_convert_time(creatng, room);
if ((i < crstat->torture_break_time) || (cctrl->tortured.assigned_torturer == 0))
{
return CrCkRet_Available;
// After that, every time broke chance is hit, do something
}
// After that, every time broke chance is hit, do something.
if (CREATURE_RANDOM(creatng, 100) < compute_torture_broke_chance(creatng))
{
if (CREATURE_RANDOM(creatng, 100) >= (int)game.conf.rules.rooms.torture_death_chance)
{
SYNCDBG(4, "The %s has been broken", thing_model_name(creatng));

if (CREATURE_RANDOM(creatng, 100) < (int)game.conf.rules.rooms.torture_convert_chance)
{ // converting creature and ending the torture
{ // Converting creature and ending the torture.
convert_tortured_creature_owner(creatng, room->owner);
return CrCkRet_Continue;
}
else
{ // revealing information about enemy and continuing the torture
{ // Revealing information about enemy and continuing the torture.
cctrl->tortured.start_gameturn = (long)game.play_gameturn - (long)crstat->torture_break_time / 2;
reveal_players_map_to_player(creatng, room->owner);
return CrCkRet_Available;
}
} else
}
else
{
SYNCDBG(4, "The %s died from torture", thing_model_name(creatng));
if (CREATURE_RANDOM(creatng, 100) < game.conf.rules.rooms.ghost_convert_chance)
Expand Down
21 changes: 11 additions & 10 deletions src/magic.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,38 +594,39 @@ void slap_creature(struct PlayerInfo *player, struct Thing *thing)
long i;
crstat = creature_stats_get_from_thing(thing);
cctrl = creature_control_get_from_thing(thing);

anger_apply_anger_to_creature(thing, crstat->annoy_slapped, AngR_Other, 1);
if (crstat->slaps_to_kill > 0)
{
i = compute_creature_max_health(crstat->health,cctrl->explevel,thing->owner) / crstat->slaps_to_kill;
apply_damage_to_thing_and_display_health(thing, i, DmgT_Physical, player->id_number);
HitPoints slap_damage = calculate_correct_creature_max_health(thing) / crstat->slaps_to_kill;
apply_damage_to_thing_and_display_health(thing, slap_damage, DmgT_Physical, player->id_number);
}
pwrdynst = get_power_dynamic_stats(PwrK_SLAP);
i = cctrl->slap_turns;
cctrl->slap_turns = pwrdynst->duration;
if (i == 0)
cctrl->max_speed = calculate_correct_creature_maxspeed(thing);
{
cctrl->max_speed = calculate_correct_creature_maxspeed(thing);
}
if (thing->active_state != CrSt_CreatureSlapCowers)
{
clear_creature_instance(thing);
if (thing->active_state != CrSt_CreatureCastingPreparation)
{
// If the creature was in CreatureCastingPreparation state, its active and continue
// states have been assigned to those bkp states, so we don't need to assign them again.
// If the creature was in CreatureCastingPreparation state,
// its active and continue states have been assigned to those bkp states,
// so we don't need to assign them again.
cctrl->active_state_bkp = thing->active_state;
cctrl->continue_state_bkp = thing->continue_state;
}
creature_mark_if_woken_up(thing);
external_set_thing_state(thing, CrSt_CreatureSlapCowers);
}
cctrl->frozen_on_hit = 6;
cctrl->cowers_from_slap_turns = 18;
cctrl->frozen_on_hit = 6; // Could be configurable.
cctrl->cowers_from_slap_turns = 18; // Could be configurable.
play_creature_sound(thing, CrSnd_Slap, 3, 0);
}

TbBool can_cast_power_at_xy(PlayerNumber plyr_idx, PowerKind pwkind,
MapSubtlCoord stl_x, MapSubtlCoord stl_y, unsigned long allow_flags)
TbBool can_cast_power_at_xy(PlayerNumber plyr_idx, PowerKind pwkind, MapSubtlCoord stl_x, MapSubtlCoord stl_y, unsigned long allow_flags)
{
struct Map *mapblk;
struct SlabMap *slb;
Expand Down
81 changes: 48 additions & 33 deletions src/thing_creature.c
Original file line number Diff line number Diff line change
Expand Up @@ -891,13 +891,14 @@ void first_apply_spell_effect_to_thing(struct Thing *thing, SpellKind spell_idx,
i = get_free_spell_slot(thing);
if (spell_idx == SplK_Heal)
{
n = saturate_set_signed(thing->health + pwrdynst->strength[spell_lev], 16);
if (n < 0)
HitPoints healing_recovery = (thing->health + pwrdynst->strength[spell_lev]);
if (healing_recovery < 0)
{
thing->health = 0;
} else
}
else
{
thing->health = min(n, cctrl->max_health);
thing->health = min(healing_recovery, cctrl->max_health);
}
if (spconf->aura_effect != 0)
{
Expand Down Expand Up @@ -1096,12 +1097,14 @@ void reapply_spell_effect_to_thing(struct Thing *thing, long spell_idx, long spe
break;
case SplK_Heal:
{
HitPoints i = saturate_set_signed(thing->health + pwrdynst->strength[spell_lev], 16);
if (i < 0)
HitPoints healing_recovery = (thing->health + pwrdynst->strength[spell_lev]);
if (healing_recovery < 0)
{
thing->health = 0;
} else {
thing->health = min(i,cctrl->max_health);
thing->health = 0;
}
else
{
thing->health = min(healing_recovery, cctrl->max_health);
}
break;
}
Expand Down Expand Up @@ -3342,32 +3345,39 @@ void thing_fire_shot(struct Thing *firing, struct Thing *target, ThingModel shot

void set_creature_level(struct Thing *thing, long nlvl)
{
struct CreatureStats* crstat = creature_stats_get_from_thing(thing);
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
struct CreatureControl *cctrl = creature_control_get_from_thing(thing);
if (creature_control_invalid(cctrl))
{
ERRORLOG("Creature has no control");
return;
}
if (nlvl > CREATURE_MAX_LEVEL-1) {
ERRORLOG("Level %d too high, bounding",(int)nlvl);
nlvl = CREATURE_MAX_LEVEL-1;
if (nlvl > CREATURE_MAX_LEVEL - 1)
{
ERRORLOG("Level %d too high, bounding", (int)nlvl);
nlvl = CREATURE_MAX_LEVEL - 1;
}
if (nlvl < 0) {
ERRORLOG("Level %d too low, bounding",(int)nlvl);
if (nlvl < 0)
{
ERRORLOG("Level %d too low, bounding", (int)nlvl);
nlvl = 0;
}
HitPoints old_max_health = compute_creature_max_health(crstat->health, cctrl->explevel, thing->owner);
HitPoints old_max_health = calculate_correct_creature_max_health(thing);
if (old_max_health < 1)
{
old_max_health = 1;
}
cctrl->explevel = nlvl;
HitPoints max_health = compute_creature_max_health(crstat->health, cctrl->explevel, thing->owner);
HitPoints max_health = calculate_correct_creature_max_health(thing);
cctrl->max_health = max_health;
set_creature_size_stuff(thing);
if (old_max_health > 0)
thing->health = saturate_set_signed( (thing->health*max_health)/old_max_health, 16);
{
thing->health = ((thing->health * max_health) / old_max_health);
}
else
{
thing->health = -1;
}
creature_increase_available_instances(thing);
add_creature_score_to_owner(thing);
}
Expand Down Expand Up @@ -4248,31 +4258,32 @@ TbBool creature_count_below_map_limit(TbBool temp_creature)

struct Thing *create_creature(struct Coord3d *pos, ThingModel model, PlayerNumber owner)
{
struct CreatureStats* crstat = creature_stats_get(model);
struct CreatureStats *crstat = creature_stats_get(model);
if (game.thing_lists[TngList_Creatures].count >= CREATURES_COUNT)
{
ERRORLOG("Cannot create %s for player %d. Creature limit %d reached.", creature_code_name(model), (int)owner, CREATURES_COUNT);
return INVALID_THING;
}
if (!i_can_allocate_free_thing_structure(FTAF_FreeEffectIfNoSlots))
{
ERRORDBG(3,"Cannot create %s for player %d. There are too many things allocated.",creature_code_name(model),(int)owner);
ERRORDBG(3, "Cannot create %s for player %d. There are too many things allocated.", creature_code_name(model), (int)owner);
erstat_inc(ESE_NoFreeThings);
return INVALID_THING;
}
if (!i_can_allocate_free_control_structure())
{
ERRORDBG(3,"Cannot create %s for player %d. There are too many creatures allocated.",creature_code_name(model),(int)owner);
ERRORDBG(3, "Cannot create %s for player %d. There are too many creatures allocated.", creature_code_name(model), (int)owner);
erstat_inc(ESE_NoFreeCreatrs);
return INVALID_THING;
}
struct Thing* crtng = allocate_free_thing_structure(FTAF_FreeEffectIfNoSlots);
if (crtng->index == 0) {
ERRORDBG(3,"Should be able to allocate %s for player %d, but failed.",creature_code_name(model),(int)owner);
struct Thing *crtng = allocate_free_thing_structure(FTAF_FreeEffectIfNoSlots);
if (crtng->index == 0)
{
ERRORDBG(3, "Should be able to allocate %s for player %d, but failed.", creature_code_name(model), (int)owner);
erstat_inc(ESE_NoFreeThings);
return INVALID_THING;
}
struct CreatureControl* cctrl = allocate_free_control_structure();
struct CreatureControl *cctrl = allocate_free_control_structure();
crtng->ccontrol_idx = cctrl->index;
crtng->class_id = TCls_Creature;
crtng->model = model;
Expand All @@ -4299,8 +4310,8 @@ struct Thing *create_creature(struct Coord3d *pos, ThingModel model, PlayerNumbe
long i = get_creature_anim(crtng, CGI_Stand);
set_thing_draw(crtng, i, 256, game.conf.crtr_conf.sprite_size, 0, 0, ODC_Default);
cctrl->explevel = 1;
crtng->health = crstat->health;
cctrl->max_health = compute_creature_max_health(crstat->health,cctrl->explevel, owner);
cctrl->max_health = calculate_correct_creature_max_health(crtng);
crtng->health = cctrl->max_health;
crtng->owner = owner;
crtng->mappos.x.val = pos->x.val;
crtng->mappos.y.val = pos->y.val;
Expand All @@ -4310,27 +4321,31 @@ struct Thing *create_creature(struct Coord3d *pos, ThingModel model, PlayerNumbe
cctrl->blood_type = CREATURE_RANDOM(crtng, BLOOD_TYPES_COUNT);
if (player_is_roaming(owner))
{
cctrl->hero.sbyte_89 = -1;
cctrl->hero.byte_8C = 1;
cctrl->hero.sbyte_89 = -1;
cctrl->hero.byte_8C = 1;
}
cctrl->flee_pos.x.val = crtng->mappos.x.val;
cctrl->flee_pos.y.val = crtng->mappos.y.val;
cctrl->flee_pos.z.val = crtng->mappos.z.val;
cctrl->flee_pos.z.val = get_thing_height_at(crtng, pos);
cctrl->fighting_player_idx = -1;
if (crstat->flying) {
if (crstat->flying)
{
crtng->movement_flags |= TMvF_Flying;
}
set_creature_level(crtng, 0);
crtng->health = cctrl->max_health;
add_thing_to_its_class_list(crtng);
place_thing_in_mapwho(crtng);
if (owner <= PLAYERS_COUNT)
set_first_creature(crtng);
{
set_first_creature(crtng);
}
set_start_state(crtng);
add_creature_score_to_owner(crtng);
cctrl->active_instance_id = creature_choose_first_available_instance(crtng);
if (crstat->illuminated) {
if (crstat->illuminated)
{
illuminate_creature(crtng);
}
return crtng;
Expand Down
Loading