From 73ac86d49396d627971f643feec98460ffaadc09 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Tue, 28 May 2024 21:44:33 +0800 Subject: [PATCH] Updated healing skills example mod (fix inaccurate behavior and refactoring) --- .../gl_healing_skill_mod.int | Bin 6306 -> 6768 bytes .../gl_healing_skill_mod.ssl | 88 ++++++++++++------ 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/artifacts/example_mods/FirstAidDoctorRepairMod/gl_healing_skill_mod.int b/artifacts/example_mods/FirstAidDoctorRepairMod/gl_healing_skill_mod.int index 2065c1c9627c2a0a4fcb325817f71d7674c9eaa0..b571d91734472e230ebaa76a564364b14ffc3af6 100644 GIT binary patch literal 6768 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 diff --git a/artifacts/example_mods/FirstAidDoctorRepairMod/gl_healing_skill_mod.ssl b/artifacts/example_mods/FirstAidDoctorRepairMod/gl_healing_skill_mod.ssl index e2e065df..9745342f 100644 --- a/artifacts/example_mods/FirstAidDoctorRepairMod/gl_healing_skill_mod.ssl +++ b/artifacts/example_mods/FirstAidDoctorRepairMod/gl_healing_skill_mod.ssl @@ -20,32 +20,33 @@ #define critter_max_hp(cr) get_critter_stat(cr, STAT_max_hit_points) #define critter_cur_hp(cr) get_critter_stat(cr, STAT_current_hp) -#define critter_body_type(cr) proto_data(obj_pid(cr), cr_body_type) #define critter_has_dmg_flag(cr, flag) ((get_object_data(cr, OBJ_DATA_DAMAGE_FLAGS) bwand flag) != 0) #define clear_critter_flag(cr, offset, flag) set_object_data(cr, offset, get_object_data(cr, offset) bwand bwnot(flag)) #define clear_critter_dmg_flag(cr, flag) clear_critter_flag(cr, OBJ_DATA_DAMAGE_FLAGS, flag) #define clear_critter_combat_flag(cr, flag) clear_critter_flag(cr, OBJ_DATA_COMBAT_STATE, flag) -#define SKILL_COUNT (18) #define SKILLS_MAX_USES_PER_DAY (3) variable times_skill_used, healable_damage_flags; procedure skill_use_slot_available(variable skill) begin - variable slot, time, hoursSinceLastUsage, - skillOffset := skill * SKILLS_MAX_USES_PER_DAY; + variable slot, time, hoursSinceLastUsage, timesUsed; // Lazy init array if (not times_skill_used) then - times_skill_used := create_array_list(SKILL_COUNT * SKILLS_MAX_USES_PER_DAY); + times_skill_used := create_array_map; + if (not times_skill_used[skill]) then + times_skill_used[skill] := create_array_list(SKILLS_MAX_USES_PER_DAY); + + timesUsed := times_skill_used[skill]; for (slot := 0; slot < SKILLS_MAX_USES_PER_DAY; slot++) begin - if (times_skill_used[skillOffset + slot] == 0) then + if (timesUsed[slot] == 0) then return slot; end time := game_time; - hoursSinceLastUsage = (time - times_skill_used[skillOffset + 0]) / ONE_GAME_HOUR; + hoursSinceLastUsage = (time - timesUsed[0]) / ONE_GAME_HOUR; if (hoursSinceLastUsage <= 24) then begin return -1; end @@ -53,19 +54,21 @@ procedure skill_use_slot_available(variable skill) begin end procedure skill_use_slot_add(variable skill) begin - variable i, - slot := skill_use_slot_available(skill), - skillOffset := skill * SKILLS_MAX_USES_PER_DAY; + variable i, timesUsed, + slot := skill_use_slot_available(skill); + if (slot == -1) then return -1; - if (times_skill_used[skillOffset + slot] != 0) then begin + timesUsed := times_skill_used[skill]; + if (timesUsed[slot] != 0) then begin + // Shift all earlier use times to make use for the new time. for (i := 0; i < slot; i++) begin - times_skill_used[skillOffset + i] := times_skill_used[skillOffset + i + 1]; + timesUsed[i] := timesUsed[i + 1]; end end - times_skill_used[skillOffset + slot] = game_time; + timesUsed[slot] = game_time; return 0; end @@ -85,6 +88,18 @@ procedure critter_is_dead(variable critter) begin return false; end +procedure critter_body_type(variable critter) begin + if (not critter) then begin + debug_msg("\nError: critter_body_type: pobj was NULL!"); + return CR_BODY_BIPED; + end + + if (obj_type(critter) != OBJ_TYPE_CRITTER) then + return CR_BODY_BIPED; + + return proto_data(obj_pid(critter), cr_body_type); +end + procedure critter_is_crippled(variable critter) begin if (not critter) then return false; @@ -121,23 +136,43 @@ procedure show_skill_use_messages(variable skill, variable successCount := 1) be display_msg(sprintf(mstr_skill(505), after - before)); end +variable sfall_ini_RemoveCriticalTimelimits := -2; + /** - * Exactly like FO2 roll_check functions, but without returning "how_much" and disabling criticals in the first day. + * Exactly like FO2 roll_check function, but without returning "how_much". + * @arg {int} rollMod + * @arg {int} critSuccessMod */ -procedure roll_check(variable rollMod, variable critChance) begin +procedure roll_check(variable rollMod, variable critSuccessMod) begin variable delta := rollMod - random(1, 100), - roll; + roll, criticalsAllowed; + + if (sfall_ini_RemoveCriticalTimelimits == -2) then + sfall_ini_RemoveCriticalTimelimits := get_ini_setting("ddraw.ini|Misc|RemoveCriticalTimelimits"); + + criticalsAllowed := (sfall_ini_RemoveCriticalTimelimits > 0) or (game_time >= ONE_GAME_DAY); if (delta < 0) then begin - return ROLL_CRITICAL_FAILURE if (random(1, 100) <= -delta / 10) else ROLL_FAILURE; + return ROLL_CRITICAL_FAILURE + if (criticalsAllowed and random(1, 100) <= -delta / 10) + else ROLL_FAILURE; end - return ROLL_CRITICAL_SUCCESS if (random(1, 100) <= delta / 10 + critChance) else ROLL_SUCCESS; + return ROLL_CRITICAL_SUCCESS + if (criticalsAllowed and random(1, 100) <= delta / 10 + critSuccessMod) + else ROLL_SUCCESS; end +// 530: damaged eye +// 531: crippled left arm +// 532: crippled right arm +// 533: crippled right leg +// 534: crippled left leg +#define display_uncrippled_msg(dmgFlagIdx, prefixMsgId) display_msg(sprintf(mstr_skill(prefixMsgId), mstr_skill(530 + dmgFlagIdx))) + /** - * A refactored version of skill_use function from the engine, for use with healing skills only. Returns true if skill use was successful. + * A refactored version of skill_use function from the engine, for use with healing skills only. Returns true if skill use was actually attempted. * @arg {ObjectPtr} user * @arg {ObjectPtr} target * @arg {int} skill - First Aid, Doctor or Repair @@ -204,22 +239,16 @@ procedure use_healing_skill(variable user, variable target, variable skill, vari clear_critter_combat_flag(target, COMBAT_STATE_FLEEING); // 520: You heal your %s. // 521: You heal the %s. - prefixMsg := 520 if (target == dude_obj) else 521; + display_uncrippled_msg(i, 520 if (target == dude_obj) else 521); call skill_use_slot_add(skill); skillUseSlotAdded := true; + if (user == dude_obj) then + call show_skill_use_messages(skill); end else begin // 525: You fail to heal your %s. // 526: You fail to heal the %s. - prefixMsg := 525 if (target == dude_obj) else 526; + display_uncrippled_msg(i, 525 if (target == dude_obj) else 526); end - // 530: damaged eye - // 531: crippled left arm - // 532: crippled right arm - // 533: crippled right leg - // 534: crippled left leg - display_msg(sprintf(mstr_skill(prefixMsg), mstr_skill(530 + i))); - if (user == dude_obj) then - call show_skill_use_messages(skill); end end @@ -270,6 +299,7 @@ procedure use_healing_skill(variable user, variable target, variable skill, vari end // TODO: not sure if this is needed //exec_map_update_scripts + return true; end