diff --git a/artifacts/example_mods/ComputeDamage/gl_compute_damage.ssl b/artifacts/example_mods/ComputeDamage/gl_compute_damage.ssl new file mode 100644 index 00000000..44d32934 --- /dev/null +++ b/artifacts/example_mods/ComputeDamage/gl_compute_damage.ssl @@ -0,0 +1,206 @@ +/* + Example algorithm of how the game engine calculates combat damage +*/ + +#include "..\headers\define.h" +#include "..\headers\command.h" +#include "..\headers\sfall\sfall.h" +#include "..\headers\sfall\define_extra.h" + +procedure start; +procedure compute_damage_F2; +procedure item_w_damage_hook; +procedure item_w_subtype(variable weapon, variable hit_mode); +procedure get_ammo_value(variable weapon, variable param); + +variable item_w_damage; + +procedure start begin + if game_loaded then begin + register_hook_proc(HOOK_COMBATDAMAGE, compute_damage_F2); + register_hook_proc(HOOK_ITEMDAMAGE, item_w_damage_hook); + end +end + +procedure compute_damage_F2 begin + variable dmg_type, weapon_perk, dmg_thresh, dmg_resist, weapon_subtype, bonus_ranged, difficulty, i, dmg_mult, dmg_div, damage; + variable target, flags, knockback, amount; + + variable + ctdTarget := get_sfall_arg, + ctdSource := get_sfall_arg, + amountTarget := get_sfall_arg, + amountSource := get_sfall_arg, + flagsTarget := get_sfall_arg, + flagsSource := get_sfall_arg, + weapon := get_sfall_arg, + bodypart := get_sfall_arg, + damageMultiplier := get_sfall_arg, + rounds := get_sfall_arg, + amountKnockback := get_sfall_arg, + hit_mode := get_sfall_arg; + + if (flagsSource bwand DAM_HIT) then begin + target := ctdTarget; + flags := flagsTarget; + knockback := 1; + end else begin + target := ctdSource; + flags := flagsSource; + knockback := 0; + end + + //amount := 0; + if target and (obj_type(target) == OBJ_TYPE_CRITTER) then begin + if weapon then begin + dmg_type := weapon_dmg_type(weapon); + weapon_perk := get_proto_data(obj_pid(weapon), PROTO_WP_PERK); + end else begin + dmg_type := DMG_normal_dam; + weapon_perk := -1; + end + + dmg_thresh := get_critter_stat(target, STAT_dmg_thresh + dmg_type); + dmg_resist := get_critter_stat(target, STAT_dmg_resist + dmg_type); + + if (flags bwand DAM_BYPASS) and (dmg_type != DMG_emp) then begin + dmg_thresh := dmg_thresh * 20 / 100; + dmg_resist := dmg_resist * 20 / 100; + end else begin + if (weapon_perk == PERK_weapon_penetrate) + or (hit_mode == ATKTYPE_PALMSTRIKE or hit_mode == ATKTYPE_PIERCINGSTRIKE + or hit_mode == ATKTYPE_HOOKKICK or hit_mode == ATKTYPE_PIERCINGKICK) then + dmg_thresh := dmg_thresh * 20 / 100; + + if ctdSource == dude_obj and has_trait(TRAIT_TRAIT, ctdSource, TRAIT_finesse) then + dmg_resist += 30; + end + + weapon_subtype := item_w_subtype(weapon, hit_mode); // item_w_subtype_ + if (ctdSource != dude_obj) or (weapon_subtype != WEAPON_TYPE_GUNS) then + bonus_ranged := 0; + else + bonus_ranged := has_trait(TRAIT_PERK, ctdSource, PERK_bonus_ranged_damage) * 2; + + difficulty := 100; + if (has_trait(TRAIT_OBJECT, ctdSource, OBJECT_TEAM_NUM) != has_trait(TRAIT_OBJECT, dude_obj, OBJECT_TEAM_NUM)) then begin + if (combat_difficulty == 0) then + difficulty := 75; + else if (combat_difficulty == 2) then + difficulty := 125; + end + + // F2 default start + // Damage = (1 - (DR_armor + DR_ammo_adjust) * (((raw_damage * (dmg_mult * damageMultiplier)) / dmg_div) - dmg_thresh) + dmg_resist += get_ammo_value(weapon, PROTO_AM_DR_MOD); // item_w_dr_adjust_ (DR Adjust %) + if (dmg_resist < 100) then begin + if (dmg_resist < 0) then dmg_resist := 0; + + dmg_mult := damageMultiplier * get_ammo_value(weapon, PROTO_AM_DMG_MULT); // item_w_dam_mult_ (Dmg mod A) + dmg_div := get_ammo_value(weapon, PROTO_AM_DMG_DIV); // item_w_dam_div_ (Dmg mod B) + + for (i := 1; i <= rounds; i++) begin + damage := (item_w_damage + bonus_ranged) * dmg_mult; // item_w_damage_ (raw_damage) + if dmg_div then damage /= dmg_div; + + damage := (((damage / 2) * difficulty) / 100) - dmg_thresh; + if (damage > 0) then begin + damage := damage - ((damage * dmg_resist) / 100); // reduce damage by the percentage of DR_armor + DR_Ammo + if (damage > 0) then amount += damage; + end + end + end + // F2 default end + + if (ctdSource == dude_obj) then begin + if has_trait(TRAIT_PERK, ctdSource, PERK_living_anatomy_perk) and (critter_kill_type(ctdTarget) != KILL_TYPE_robot_kills) + and (critter_kill_type(ctdTarget) != KILL_TYPE_alien_kills) then + amount += 5; + if has_trait(TRAIT_PERK, ctdSource, PERK_pyromaniac_perk) and (dmg_type == DMG_fire) then + amount += 5; + end + + if knockback and ((get_flags(target) bwand FLAG_MULTIHEX) == 0) + and (dmg_type == DMG_explosion or weapon == 0 or weapon_subtype == WEAPON_TYPE_MELEE) + and ((get_proto_data(obj_pid(target), PROTO_CR_FLAGS) bwand CFLG_NOKNOCKDOWN) == 0) then begin // critter_flag_check_ + damage := 0; + if (target == dude_obj) and has_trait(TRAIT_PERK, target, PERK_stonewall_perk) then begin + damage := 1; + if (random(0, 100) < 50) then knockback := 0; + end + if knockback then begin + if (weapon_perk == PERK_weapon_knockback) then + amountKnockback := amount / 5; + else + amountKnockback := amount / 10; + + if damage then amountKnockback /= 2; + end + end + end + + if (flagsSource bwand DAM_HIT) then begin + display_msg("amountTarget = " + amountTarget+ ", amount = " + amount); + amountTarget := amount; + flagsTarget := flags; + end else begin + display_msg("amountSource = " + amountSource+ ", amount = " + amount); + amountSource := amount; + flagsSource := flags; + end + + set_sfall_return(amountTarget); + set_sfall_return(amountSource); + set_sfall_return(flagsTarget); + set_sfall_return(flagsSource); + set_sfall_return(amountKnockback); +end + +procedure item_w_damage_hook begin + variable + item_w_damage_min := get_sfall_arg, + item_w_damage_max := get_sfall_arg; + //weapon := get_sfall_arg, + //source := get_sfall_arg, + //hit_mode := get_sfall_arg, + //isMelee := get_sfall_arg; + + item_w_damage := (item_w_damage_min + (item_w_damage_max - item_w_damage_min) / 2); + display_msg("item_w_damage_ = " + item_w_damage); + + set_sfall_return(item_w_damage); +end + +procedure item_w_subtype(variable weapon, variable hit_mode) begin + variable attack_mode, type := WEAPON_TYPE_UNARMED; + + if weapon and (hit_mode <= ATKTYPE_RWEP2) then begin + attack_mode := (get_proto_data(obj_pid(weapon), PROTO_IT_FLAGS)); + + if (hit_mode == ATKTYPE_LWEP2) or (hit_mode == ATKTYPE_RWEP2) then + attack_mode := (attack_mode bwand 0xF0) / 16; // shift 4 bits to the right + else + attack_mode := (attack_mode bwand 0x0F); + + if (attack_mode > ATKMODE_PRI_THROW) then + type := WEAPON_TYPE_GUNS; + else if (attack_mode == ATKMODE_PRI_THROW) then + type := WEAPON_TYPE_THROWN; + else if (attack_mode > ATKMODE_PRI_KICK) then + type := WEAPON_TYPE_MELEE; + end + + return type; +end + +procedure get_ammo_value(variable weapon, variable param) begin + variable pid := -1, value := 0; // default DR value + + if weapon then begin + pid := get_weapon_ammo_pid(weapon); + if (pid > -1) then value := get_proto_data(pid, param); + end + if (pid == -1 and param != PROTO_AM_DR_MOD) then value := 1; // default value for Mult/Div + + return value; +end diff --git a/artifacts/mods/gl_highlighting.int b/artifacts/mods/gl_highlighting.int index df28f02b..3112fa38 100644 Binary files a/artifacts/mods/gl_highlighting.int and b/artifacts/mods/gl_highlighting.int differ diff --git a/artifacts/mods/gl_npcarmor.int b/artifacts/mods/gl_npcarmor.int index 54d07d49..d31041e9 100644 Binary files a/artifacts/mods/gl_npcarmor.int and b/artifacts/mods/gl_npcarmor.int differ diff --git a/artifacts/mods/gl_partycontrol.int b/artifacts/mods/gl_partycontrol.int index b853c502..3d56e1b9 100644 Binary files a/artifacts/mods/gl_partycontrol.int and b/artifacts/mods/gl_partycontrol.int differ diff --git a/artifacts/mods/main.h b/artifacts/mods/main.h index 84a4c50a..8e09b02d 100644 --- a/artifacts/mods/main.h +++ b/artifacts/mods/main.h @@ -10,21 +10,35 @@ variable ini := "sfall-mods.ini"; variable translationIni; -// Gets the integer value from ini +// Gets the integer value from the specified ini +procedure GetIniConfig(variable section, variable key, variable def, variable inifile) begin + variable val := get_ini_setting(inifile + "|" + section + "|" + key); + if val == -1 then val := def; + return val; +end + +// Gets the string value from the specified ini +procedure GetIniConfigStr(variable section, variable key, variable def, variable inifile) begin + variable val := get_ini_string(inifile + "|" + section + "|" + key); + if val == -1 or val == "" then val := def; + return val; +end + +// Gets the integer value from sfall-mods.ini procedure GetConfig(variable section, variable key, variable def) begin variable val := get_ini_setting(ini + "|" + section + "|" + key); if val == -1 then val := def; return val; end -// Gets the string value from ini +// Gets the string value from sfall-mods.ini procedure GetConfigStr(variable section, variable key, variable def) begin variable val := get_ini_string(ini + "|" + section + "|" + key); if val == -1 or val == "" then val := def; return val; end -// Gets the value from ini as a temp array of strings +// Gets the value from sfall-mods.ini as a temp array of strings procedure GetConfigList(variable section, variable key) begin variable val := get_ini_string(ini + "|" + section + "|" + key); if val == -1 or val == "" then return []; @@ -32,7 +46,7 @@ procedure GetConfigList(variable section, variable key) begin return string_split(val, ","); end -// Gets the value from ini as a temp array of ints +// Gets the value from sfall-mods.ini as a temp array of ints procedure GetConfigListInt(variable section, variable key) begin variable arr, i, item; @@ -53,5 +67,5 @@ procedure Translate(variable id, variable def) begin end procedure InitConfigs begin - translationIni := GetConfigStr("Main", "TranslationsINI", "./Translations.ini"); + translationIni := GetIniConfigStr("Main", "TranslationsINI", "Translations.ini", "ddraw.ini"); end