Added New Mods and Profiles Folders

This is a complete rebuild of the modpack, with all new mods and updates for 1.5.3 of Anomaly.
This commit is contained in:
2025-01-14 05:07:53 -05:00
parent 85c665b107
commit 376b4b9689
21217 changed files with 546254 additions and 0 deletions
@@ -0,0 +1,124 @@
;___________________________________________________________________________________________________________________
;___________________________________________________________________________________________________________________
;Анимации - свежевание
;Ножи - базовые параметры ah yes, of course
[item_ea_harv_useknife_animset]
anim_length = 2868
anim_sound = interface\item_usage\harvest_use
[item_ea_harv_useknife_animset_hud]
hands_position = -0.0055,-0.07, 0.36
hands_position_16x9 = -0.0055,-0.07, 0.36
anm_ea_show = skinning_knife, idle
;____Ножи
[item_ea_harv_wpn_knife]:item_ea_harv_useknife_animset
[item_ea_harv_wpn_knife_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_knife\wpn_knife_hud.ogf
[item_ea_harv_wpn_knife2_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_knife\wpn_knife_nr40_hud.ogf
[item_ea_harv_wpn_knife3_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_knife\wpn_knife_hunting_hud.ogf
[item_ea_harv_wpn_knife4_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_knife\wpn_knife_swat_hud.ogf
[item_ea_harv_wpn_knife5_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_knife\wpn_knife_combat_hud.ogf
[item_ea_harv_wpn_knife6_hud]:item_ea_harv_useknife_animset_hud
item_visual = dynamics\weapons\wpn_knife\wpn_knifebf4_hud.ogf
[item_ea_harv_wpn_knife7_hud]:item_ea_harv_useknife_animset_hud
item_visual = dynamics\weapons\wpn_knife\wpn_tactical_knife_hud.ogf
[item_ea_harv_wpn_knife8_hud]:item_ea_harv_useknife_animset_hud
item_visual = dynamics\weapons\wpn_knife\wpn_kukri_hud.ogf
[item_ea_harv_wpn_knife9_hud]:item_ea_harv_useknife_animset_hud
item_visual = dynamics\weapons\wpn_knife\wpn_tomahawk_hud.ogf
[item_ea_harv_wpn_axe3_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_sledge_hammer\wpn_sledge_hud.ogf
[item_ea_harv_wpn_axe2_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_shovel\wpn_shovel_sharp_hud.ogf
[item_ea_harv_wpn_axe_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_axe\wpn_axe_hud.ogf
[item_ea_harv_mmf_shovel_old_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_shovel\wpn_shovel_hud.ogf
[item_ea_harv_mmf_shovel_mili_hud]:item_ea_harv_useknife_animset_hud
item_visual = anomaly_weapons\wpn_shovel\wpn_shovel_mili_hud.ogf
;___________________________________________________________________________________________________________________
;___________________________________________________________________________________________________________________
;Анимации - сбор мяса в мешок
;Мясо_базовые параметры
[item_ea_harv_meat_animset_hud]
hands_position = -0.0055,-0.085, 0.32
hands_position_16x9 = -0.0055,-0.085, 0.32
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_1_hud.ogf
anm_ea_show = harv_loot_hands, harvest_success_wpn_eat
;____Мясо
[item_ea_harv_meat_1_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_1_hud.ogf
test_motion_names = harv_loot_hands, harvest_success_wpn_eat
[item_ea_harv_meat_4_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_boar_hud.ogf
[item_ea_harv_meat_6_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_dog_hud.ogf
[item_ea_harv_meat_8_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_eye_hud.ogf
[item_ea_harv_meat_3_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_flesh_hud.ogf
[item_ea_harv_meat_9_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_himera_hud.ogf
[item_ea_harv_meat_2_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_hud.ogf
[item_ea_harv_meat_10_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_krovosos_hud.ogf
[item_ea_harv_meat_12_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_nose_hud.ogf
[item_ea_harv_meat_14_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_polter_hud.ogf
[item_ea_harv_meat_13_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_pseudodog_hud.ogf
[item_ea_harv_meat_5_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_snork_hud.ogf
[item_ea_harv_meat_7_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_tushkan_tail_hud.ogf
[item_ea_harv_meat_11_hud]:item_ea_harv_meat_animset_hud
item_visual = dynamics\weapons\wpn_eat\harvest\meat_1\wpn_harvest_meat_zombie_hud.ogf
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,11 @@
[common_supplies] ; gets used if trader has no supply_level
[supplies_1]:common_supplies
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,11 @@
[common_supplies] ; gets used if trader has no supply_level
[supplies_1]:common_supplies
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,11 @@
[common_supplies] ; gets used if trader has no supply_level
[supplies_1]:common_supplies
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,15 @@
[common_supplies] ; gets used if trader has no supply_level
wpn_axe = 1, 1
[supplies_1]:common_supplies
wpn_axe = 1, 1
[supplies_2]:supplies_1
[supplies_3]:supplies_2
[supplies_4]:supplies_3
[supplies_5]:supplies_4
@@ -0,0 +1,280 @@
;--------------------------------------------------------------------------------------------AXE---------------------
![wpn_axe]:!wpn_axe_sounds
visual = dynamics\weapons\heavy_melee\wpn_axe.ogf
hud_fov = 0.5
icons_texture = ui\heavy_melee_icons
description = st_axe2_descr
inv_grid_width = 4
inv_grid_height = 2
inv_grid_x = 4
inv_grid_y = 0
position = 0.07, 0.05, 0
orientation = 0, 90, -90
hit_power = 3.4
hit_power_2 = 3.1
hit_impulse = 13.5
hit_impulse_2 = 1.5
snd_draw = weapons\new_axe\heavy_draw
snd_holster = weapons\new_axe\heavy_holster
snd_shoot = $no_sound
snd_shoot1 = $no_sound
snd_shoot2 = $no_sound
;Sounds Handled In Scripts
scripted_snd_attack = weapons\new_axe\axe_swing, true
scripted_snd_attack_variant1 = weapons\new_axe\axe_swing_var1, true
scripted_snd_attack_variant2 = weapons\new_axe\axe_swing_var2, true
scripted_snd_attack2 = weapons\new_axe\heavy_overhead_swing, true
![wpn_axe_hud]
item_visual = anomaly_weapons\wpn_axe\wpn_axe_hud
item_position = 0, 0, 0
item_orientation = 0, 0, 0
hands_orientation = -0.5, 1, 10
hands_orientation_16x9 = -0.5, 1, 10
hands_position = -0.001529, -0.168825, 0.198185
hands_position_16x9 = -0.001529, -0.168825, 0.198185
lowered_hud_offset_pos = 0.150546, -0.440668, 0.134398
lowered_hud_offset_pos_16x9 = 0.150546, -0.440668, 0.134398
lowered_hud_offset_rot = -0.603039, -1.149442, -0.738433
lowered_hud_offset_rot_16x9 = -0.603039, -1.149442, -0.738433
anm_attack = barry_axe_light_hands
anm_attack2 = barry_axe_heavy_hands
anm_hide = barry_axe_holster_hands
anm_idle = barry_axe_idle_hands
anm_idle_aim = barry_axe_idle_hands
anm_idle_moving = barry_axe_walk_hands
anm_idle_sprint = barry_axe_sprint_hands
anm_show = barry_axe_draw_hands
anm_show_empty = barry_axe_draw_hands
anm_bore = barry_axe_inspect_hands
; Custom Animation Types Handled In Scripts
anm_attack_variant1 = barry_axe_light_hands_alt1
anm_attack_variant2 = barry_axe_light_hands_alt2
anm_1h_show = barry_axe_1h_draw_hands
; Transition/Intermediate Animations
anm_walk2sprint = barry_axe_transition_hands
anm_sprint2walk = barry_axe_transition_hands_alt
; Transition Definitions
ts_pattern_walk2sprint = .+, anm_idle_sprint, anm_walk2sprint, 1
ts_pattern_sprint2walk = anm_idle_sprint, ^anm_idle.*, anm_sprint2walk, 1
;------------------------------------------------------------------------------------------SHARP-SHOVEL-----------------------
![wpn_axe2]:!wpn_axe_sounds
visual = dynamics\weapons\heavy_melee\sharp_shovel.ogf
description = st_shovel_sharp_descr
inv_name = st_shovel_sharp
inv_name_short = st_shovel_sharp
icons_texture = ui\heavy_melee_icons
inv_grid_width = 4
inv_grid_height = 2
inv_grid_x = 0
inv_grid_y = 4
cost = 260
inv_weight = 1.54
position = -0.01, 0.6, 0.024
orientation = 0, 180, 0
hit_power = 6.4
hit_power_2 = 48
condition_queue_shot_dec = 15
condition_shot_dec = 15
repair_type = none
hud = wpn_axe2_hud
snd_draw = weapons\new_axe\heavy_draw
snd_holster = weapons\new_axe\heavy_holster
snd_shoot = $no_sound
snd_shoot1 = $no_sound
snd_shoot2 = $no_sound
;Sounds Handled In Scripts
scripted_snd_attack = weapons\new_axe\axe_swing, true
scripted_snd_attack_variant1 = weapons\new_axe\axe_swing_var1, true
scripted_snd_attack_variant2 = weapons\new_axe\axe_swing_var2, true
scripted_snd_attack2 = weapons\new_axe\heavy_overhead_swing, true
![wpn_axe2_hud]
item_visual = anomaly_weapons\wpn_shovel\wpn_shovel_sharp_hud
item_position = 0, 0, 0
item_orientation = 0, 0, 0
hands_orientation = -0.5, 1, 10
hands_orientation_16x9 = -0.5, 1, 10
hands_position = -0.001529, -0.168825, 0.198185
hands_position_16x9 = -0.001529, -0.168825, 0.198185
lowered_hud_offset_pos = 0.019067, -0.358889, 0.069541
lowered_hud_offset_pos_16x9 = 0.019067, -0.358889, 0.069541
lowered_hud_offset_rot = -0.892271, -0.538412, -0.263826
lowered_hud_offset_rot_16x9 = -0.892271, -0.538412, -0.263826
anm_attack = barry_shovel_light_hands
anm_attack2 = barry_shovel_heavy_hands
anm_hide = barry_shovel_holster_hands
anm_idle = barry_shovel_idle_hands
anm_idle_aim = barry_shovel_idle_hands
anm_idle_moving = barry_shovel_walk_hands
anm_idle_sprint = barry_shovel_sprint_hands
anm_show = barry_shovel_draw_hands
anm_show_empty = barry_shovel_draw_hands
anm_bore = barry_shovel_inspect_hands
; Custom Animation Types Handled In Scripts
anm_attack_variant1 = barry_shovel_light_hands_alt1
anm_attack_variant2 = barry_shovel_light_hands_alt2
anm_1h_show = barry_shovel_draw_1h_hands
; Transition/Intermediate Animations
anm_walk2sprint = none
anm_sprint2walk = none
; Transition Definitions
ts_pattern_walk2sprint = none
ts_pattern_sprint2walk = none
shell_bone = wpn_body
shell_point = 0, 0, 0
fire_bone = knife
fire_point = 0.004500, 0.062500, -0.178499
freelook_z_offset_mul = 0.9
;-------------------------------------------------------------------------------------SLEDGE-HAMMER----------------------------
![wpn_axe3]:!wpn_axe_sounds
visual = dynamics\weapons\heavy_melee\wpn_sledge.ogf
hud_fov = 0.5
description = st_sledge_hammer_descr
inv_name = st_sledge_hammer
inv_name_short = st_sledge_hammer
icons_texture = ui\heavy_melee_icons
inv_grid_width = 4
inv_grid_height = 2
inv_grid_x = 4
inv_grid_y = 2
hit_power = 3.4
hit_power_2 = 4.8
hit_impulse = 25.5
hit_impulse_2 = 1.5
position = -0.05, 0.1, 0.05
orientation = 0, 90, 0
snd_draw = weapons\new_axe\heavy_draw
snd_holster = weapons\new_axe\heavy_holster
snd_shoot = $no_sound
snd_shoot1 = $no_sound
snd_shoot2 = $no_sound
;Sounds Handled In Scripts
scripted_snd_attack = weapons\new_axe\axe_swing, true
scripted_snd_attack_variant1 = weapons\new_axe\axe_swing_var1, true
scripted_snd_attack_variant2 = weapons\new_axe\axe_swing_var2, true
scripted_snd_attack2 = weapons\new_axe\heavy_overhead_swing_sledge, true
![wpn_axe3_hud]
item_visual = anomaly_weapons\wpn_sledge_hammer\wpn_sledge_hud
item_position = 0, 0, 0
item_orientation = 0, 0, 0
hands_orientation = 6.3614, -4.82933, 9.645867
hands_orientation_16x9 = 6.3614, -4.82933, 9.645867
hands_position = 0.001152, -0.127219, 0.102892
hands_position_16x9 = 0.001152, -0.127219, 0.102892
lowered_hud_offset_pos = 0.155134, -0.378376, 0.095714
lowered_hud_offset_pos_16x9 = 0.155134, -0.378376, 0.095714
lowered_hud_offset_rot = -0.603039, -1.149442, -0.738433
lowered_hud_offset_rot_16x9 = -0.603039, -1.149442, -0.738433
anm_attack = barry_axe_light_hands
anm_attack2 = barry_axe_heavy_hands
anm_hide = barry_axe_holster_hands
anm_idle = barry_axe_idle_hands
anm_idle_aim = barry_axe_idle_hands
anm_idle_moving = barry_axe_walk_hands
anm_idle_sprint = barry_axe_sprint_hands
anm_show = barry_axe_draw_hands
anm_show_empty = barry_axe_draw_hands
anm_bore = barry_sledge_inspect_hands
; Custom Animation Types Handled In Scripts
anm_attack_variant1 = barry_axe_light_hands_alt1
anm_attack_variant2 = barry_axe_light_hands
anm_1h_show = barry_axe_1h_draw_hands
; Transition/Intermediate Animations
anm_walk2sprint = barry_axe_transition_hands
anm_sprint2walk = barry_axe_transition_hands_alt
; Transition Definitions
ts_pattern_walk2sprint = .+, anm_idle_sprint, anm_walk2sprint, 1
ts_pattern_sprint2walk = anm_idle_sprint, ^anm_idle.*, anm_sprint2walk, 1
;-----------------------------------------------------------------------------------OLD-SHOVEL---------------------------
![shovel_old]
icons_texture = ui\heavy_melee_icons
inv_grid_width = 4
inv_grid_height = 2
inv_grid_x = 0
inv_grid_y = 2
;-----------------------------------------------------------------------------------MILI-SHOVEL--------------------------
![shovel_mili]
visual = dynamics\equipments\trade\mili_shovel.ogf
icons_texture = ui\heavy_melee_icons
inv_grid_width = 4
inv_grid_height = 2
inv_grid_x = 0
inv_grid_y = 0
;---------------------------------------------------------------------------------MMF-OLD-SHOVEL---------------------------
[mmf_shovel_old]:wpn_axe2
visual = dynamics\equipments\trade\shovel.ogf
description = st_shovel_old_descr
inv_name = st_shovel_old
inv_name_short = st_shovel_old
icons_texture = ui\heavy_melee_icons
inv_grid_width = 4
inv_grid_height = 2
inv_grid_x = 0
inv_grid_y = 2
hit_power = 1.6
hit_power_2 = 0.525, 0.525, 0.525, 0.525
hit_power_critical_2 = 0.75, 0.75, 0.75, 0.75
hud = mmf_shovel_old_hud
[mmf_shovel_old_hud]:wpn_axe2_hud
item_visual = anomaly_weapons\wpn_shovel\wpn_shovel_hud
;---------------------------------------------------------------------------------MMF-MILI-SHOVEL--------------------------
[mmf_shovel_mili]:wpn_axe2
visual = dynamics\equipments\trade\mili_shovel.ogf
description = st_shovel_mili_descr
inv_name = st_shovel_mili
inv_name_short = st_shovel_mili
icons_texture = ui\heavy_melee_icons
inv_grid_width = 4
inv_grid_height = 2
inv_grid_x = 0
inv_grid_y = 0
hit_power = 1.6
hit_power_2 = 0.525, 0.525, 0.525, 0.525
hit_power_critical_2 = 0.75, 0.75, 0.75, 0.75
hud = mmf_shovel_mili_hud
[mmf_shovel_mili_hud]:wpn_axe2_hud
item_visual = anomaly_weapons\wpn_shovel\wpn_shovel_mili_hud
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<string id="ui_mcm_menu_aoldri_axe_sounds">
<text>Melee Hit Stop</text>
</string>
<string id="ui_mcm_aoldri_axe_sounds_title">
<text>Melee Slowmo on Death</text>
</string>
<string id="ui_mcm_aoldri_axe_sounds_resume_time">
<text>Slowdown Length</text>
</string>
<string id="ui_mcm_aoldri_axe_sounds_time_factor">
<text>Slowdown Time Factor (Affects Slowdown Length)</text>
</string>
</string_table>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<string id="st_demonized_crafter">
<text>craft</text>
</string>
<string id="st_demonized_crafter_craft_success">
<text>Crafted</text>
</string>
<string id="st_demonized_crafter_craft_spent_items">
<text>Used items</text>
</string>
<string id="st_demonized_crafter_craft_fail">
<text>Failed to craft</text>
</string>
<string id="st_demonized_crafter_craft_possible_combinations">
<text>Possible combinations</text>
</string>
<string id="st_demonized_crafter_craft_or">
<text>OR</text>
</string>
<string id="st_demonized_crafter_craft_all">
<text>all</text>
</string>
<string id="st_demonized_crafter_craft_check_pda_news">
<text>Check recipes in PDA in "News" tab</text>
</string>
</string_table>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<string id="st_shovel_sharp">
<text>Sharpened Shovel</text>
</string>
<string id="st_shovel_sharp_descr">
<text>A sharpened black metal shovel. Doesnt seem very durable but its certainly sharp. \n \n
%c[ui_gray_3]PROPERTIES:\n
%c[d_blue] • %c[ui_gray_2] Heavy Melee item\n</text>
</string>
<string id="st_sledge_hammer">
<text>Sledge Hammer</text>
</string>
<string id="st_sledge_hammer_descr">
<text>A blunt, heavy industrial sledge hammer. Once a tool used to contruct the buildings around us, now used to crush the heads of those squatting inside. \n \n
%c[ui_gray_3]PROPERTIES:\n
%c[d_blue] • %c[ui_gray_2] Heavy Melee item\n</text>
</string>
<string id="st_sharpen_shovel">
<text>Sharpen Shovel</text>
</string>
</string_table>
@@ -0,0 +1,29 @@
<string_table>
<string id="ui_mcm_melee_degrade_onhit_title">
<text>Melee Degrade Configuration</text>
</string>
<string id="ui_mcm_menu_melee_degrade_onhit">
<text>Melee Degrade On Hit</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_axe_loss_mult">
<text>Axe Degrade Multiplier</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_knife_loss_mult">
<text>Knife Degrade Multiplier</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_geometry_loss_mult">
<text>Hard Surface Degrade Multiplier</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_phys_loss_mult">
<text>Object Degrade Multiplier</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_enemy_loss_mult">
<text>Enemy Degrade Multiplier</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_light_loss_mult">
<text>Light Attack Degrade Multiplier</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_heavy_loss_mult">
<text>Heavy Attack Degrade Multiplier</text>
</string>
</string_table>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<string id="ui_mcm_menu_aoldri_axe_sounds">
<text>Óäàð â áëèæíåì áîþ Îñòàíîâèòü</text>
</string>
<string id="ui_mcm_aoldri_axe_sounds_title">
<text>Áëèæíèé áîé Çàìåäëåííîå äâèæåíèå íà ñìåðòü</text>
</string>
<string id="ui_mcm_aoldri_axe_sounds_resume_time">
<text>Ïðîäîëæèòåëüíîñòü çàìåäëåíèÿ</text>
</string>
<string id="ui_mcm_aoldri_axe_sounds_time_factor">
<text>Êîýôôèöèåíò âðåìåíè çàìåäëåíèÿ (âëèÿåò íà ïðîäîëæèòåëüíîñòü çàìåäëåíèÿ)</text>
</string>
</string_table>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<string id="st_demonized_crafter">
<text>ñêðàôòèòü</text>
</string>
<string id="st_demonized_crafter_craft_success">
<text>Ñîçäàíî:</text>
</string>
<string id="st_demonized_crafter_craft_spent_items">
<text>Èñïîëüçîâàííûå ïðåäìåòû</text>
</string>
<string id="st_demonized_crafter_craft_fail">
<text>Íå óäàëîñü ñîçäàòü</text>
</string>
<string id="st_demonized_crafter_craft_possible_combinations">
<text>Âîçìîæíûå êîìáèíàöèè</text>
</string>
<string id="st_demonized_crafter_craft_or">
<text>ÈËÈ</text>
</string>
<string id="st_demonized_crafter_craft_all">
<text>âñå</text>
</string>
<string id="st_demonized_crafter_craft_check_pda_news">
<text>Ðåöåïòû êðàôòà â ÏÄÀ âî âêëàäêå "Íîâîñòè"</text>
</string>
</string_table>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<string id="st_shovel_sharp">
<text>Çàòî÷åííàÿ ëîïàòà</text>
</string>
<string id="st_shovel_sharp_descr">
<text>Çàòî÷åííàÿ ëîïàòà èç ÷åðíîãî ìåòàëëà. Êàæåòñÿ íå î÷åíü ïðî÷íûì, íî îí îïðåäåëåííî îñòðûé. \n \n
%c[ui_gray_3]PROPERTIES:\n
%c[d_blue] • %c[ui_gray_2] Òÿæåëûé ïðåäìåò áëèæíåãî áîÿ\n</text>
</string>
<string id="st_sledge_hammer">
<text>Êóâàëäà</text>
</string>
<string id="st_sledge_hammer_descr">
<text>Òóïàÿ, òÿæåëàÿ ïðîìûøëåííàÿ êóâàëäà. Êîãäà-òî ýòîò èíñòðóìåíò èñïîëüçîâàëñÿ äëÿ âîçâåäåíèÿ çäàíèé âîêðóã íàñ, à òåïåðü èñïîëüçóåòñÿ äëÿ òîãî, ÷òîáû ðàçáèâàòü ãîëîâû òåì, êòî ñèäèò íà êîðòî÷êàõ âíóòðè. \n \n
%c[ui_gray_3]PROPERTIES:\n
%c[d_blue] • %c[ui_gray_2] Òÿæåëûé ïðåäìåò áëèæíåãî áîÿ\n</text>
</string>
<string id="st_sharpen_shovel">
<text>Çàòî÷èòü ëîïàòó</text>
</string>
</string_table>
@@ -0,0 +1,29 @@
<string_table>
<string id="ui_mcm_melee_degrade_onhit_title">
<text>Êîíôèãóðàöèÿ óõóäøåíèÿ â áëèæíåì áîþ</text>
</string>
<string id="ui_mcm_menu_melee_degrade_onhit">
<text>Ðóêîïàøíûé áîé Óõóäøàåòñÿ ïðè ïîïàäàíèè</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_axe_loss_mult">
<text>Ìíîæèòåëü äåãðàäàöèè òîïîðà</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_knife_loss_mult">
<text>Ìíîæèòåëü äåãðàäàöèè íîæà</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_geometry_loss_mult">
<text>Ìíîæèòåëü äåãðàäàöèè òâåðäîé ïîâåðõíîñòè</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_phys_loss_mult">
<text>Ìíîæèòåëü óõóäøåíèÿ ñîñòîÿíèÿ îáúåêòà</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_enemy_loss_mult">
<text>Ìíîæèòåëü äåãðàäàöèè ïðîòèâíèêà</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_light_loss_mult">
<text>Ìíîæèòåëü óõóäøåíèÿ ñâåòîâîé àòàêè</text>
</string>
<string id="ui_mcm_melee_degrade_onhit_heavy_loss_mult">
<text>Òÿæåëàÿ àòàêà Óõóäøàåò ìíîæèòåëü</text>
</string>
</string_table>
@@ -0,0 +1,6 @@
<w>
<file name = "ui\mmf_mcm_banners.dds">
<texture id = "degrade_mcm_banner" x="0" y="0" width="1024" height="67" />
<texture id = "hitstop_mcm_banner" x="0" y="70" width="1024" height="67" />
</file>
</w>
@@ -0,0 +1,115 @@
-- Might want to extend this to track flags based on IDs since detectors have animations too
-- Likely overkill unless someone implements custom anims for them
FLAGS = {}
local active_flags = {}
-- Export: Flags
function get_flag(flag)
return active_flags[flag]
end
function set_flag(flag)
active_flags[flag] = true
end
function remove_flag(flag)
active_flags[flag] = nil
end
function add_flag(flag)
-- Exit early if it already exists
if FLAGS[flag] then return end
FLAGS[flag] = #FLAGS
end
local anim_mutators = {}
-- Export: Animation Mutators
function add_anim_mutator(functor, priority)
-- Add mutator func to list of mutators
table.insert(anim_mutators, {functor=functor, priority=priority})
-- Sort anim_mutators again
table.sort(anim_mutators, function(a,b) return a.priority < b.priority end)
end
function has_animation(section, anm)
local hud_section = ini_sys:r_string_ex(section,"hud") or section
return SYS_GetParam(0, hud_section, anm)
end
function mutate_anim(anm_table, anm_suffix, section)
local new_anm = anm_table.anm_name .. anm_suffix
if has_animation(section, new_anm) then
anm_table.anm_name = new_anm
return true
end
return false
end
-- Sounds
local sound_object_by_path = {}
function get_safe_sound_object(path)
if sound_object_by_path[path] == nil then
sound_object_by_path[path] = sound_object(path)
end
return sound_object_by_path[path]
end
function stop_all_sound_object()
for k,v in pairs(sound_object_by_path) do
if v:playing() then
v:stop()
end
end
sound_object_by_path = {}
end
function get_sound_from_anm(anm_name) -- TODO: allow sound volume to be defined in config
return anm_name:gsub("anm_", "scripted_snd_")
end
-- Probably worth adding an ordered list of functions with conditions that can mutate anm_table
-- and use this script as source of truth for about-to-be-played animations since callback order is random between scripts
function actor_on_hud_animation_play(anm_table, item)
stop_all_sound_object()
if not item then return end
local section = item:section()
-- Execute each mutator functor in turn, ordered by priority
for i, mutator in ipairs(anim_mutators) do
local stop = mutator.functor(anm_table, item)
if stop then break end
end
-- Animation (No Mutation): Clear all flags if holstering weapon
if anm_table.anm_name == "anm_hide" or anm_table.anm_name == "anm_hide_empty" then
active_flags = {}
end
-- Sound: Check if weapon has a valid scripted sound in config
local anm_name = anm_table.anm_name
local snd_name = get_sound_from_anm(anm_name)
local snd_value = SYS_GetParam(0, section, snd_name)
if not snd_value then return end
local snd_values = str_explode(snd_value,",")
local snd_path = snd_values[1]
local never_cancel = snd_values[2]
-- Play sound
local snd_obj = get_safe_sound_object( snd_path )
if not snd_obj then return end
if never_cancel then
snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0, 1.0)
else
snd_obj:play(db.actor, 0, sound_object.s2d)
end
end
function on_game_start()
RegisterScriptCallback("actor_on_hud_animation_play",actor_on_hud_animation_play)
end
@@ -0,0 +1,169 @@
local common = animation_common
valid_anims = {}
local mutate_anim = animation_common.mutate_anim
function animation_common.mutate_anim(anm_table, anm_suffix, section)
table.insert(valid_anims, anm_suffix)
return mutate_anim(anm_table, anm_suffix, section)
end
transitions = {
}
function add_strict_transition(hud_section, start_anm, end_anm, transition_anm)
if not (hud_section and start_anm and end_anm and transition_anm) then
printf("[ERROR] aol_anim_transitions: Could not add new transition (a parameter was nil)")
return
end
-- Make sure transitions is properly set as a table of tables
transitions[hud_section] = transitions[hud_section] or {}
transitions[hud_section][start_anm] = transitions[hud_section][start_anm] or {}
transitions[hud_section][start_anm][end_anm] = transition_anm
end
pattern_transitions = {
}
function add_pattern_transition(hud_section, start_anm, end_anm, transition_anm, priority)
priority = priority or 25565
if not (hud_section and start_anm and end_anm and transition_anm) then
printf("[ERROR] aol_anim_transitions: Could not add new transition (a parameter was nil)")
return
end
pattern_transitions[hud_section] = pattern_transitions[hud_section] or {}
table.insert(pattern_transitions[hud_section], {
["start_anm"] = start_anm,
["end_anm"] = end_anm,
["transition_anm"] = transition_anm,
["priority"] = priority
})
end
local ini_items = ini_file("system.ltx")
local function itr(section)
local is_hud_section = section:match('_hud$')
if is_hud_section then
local line_count = ini_items:line_count(section)
for i=0,line_count-1 do
local result, id, value = ini_items:r_line_ex(section,i,"","")
local is_strict_transition = id:match("^ts_strict_")
if is_strict_transition then
local anm_names = str_explode(value,",")
add_strict_transition(section, anm_names[1], anm_names[2], anm_names[3])
end
local is_pattern_transition = id:match("^ts_pattern_")
if is_pattern_transition then
local anm_names = str_explode(value,",")
add_pattern_transition(section, anm_names[1], anm_names[2], anm_names[3], anm_names[4])
end
end
end
return false
end
ini_items:section_for_each(itr)
table.sort(pattern_transitions, function(a,b) return a["priority"] < b["priority"] end)
local previous_anms = {}
function set_strict_transition(anm_table, hud_section)
-- Make sure item has transitions
local item_transitions = transitions[hud_section]
if not (item_transitions) then
-- previous_anms[hud_section] = anm_table.anm_name
return false
end
-- Make sure there is a previous anm to check
local start_anm = previous_anms[hud_section]
if not start_anm then
-- previous_anms[hud_section] = anm_table.anm_name
return false
end
-- Get transition anm from table
local end_anm = anm_table.anm_name
local transition_anm = item_transitions[start_anm] and item_transitions[start_anm][end_anm]
if not (transition_anm) then
-- previous_anms[hud_section] = anm_table.anm_name
return false
end
-- Re-add valid suffixes from previous mutations
for i, anm_suffix in ipairs(valid_anims) do
if animation_common.has_animation(hud_section, transition_anm .. anm_suffix) then
transition_anm = transition_anm .. anm_suffix
end
end
anm_table.anm_name = transition_anm
return true
end
function set_pattern_transition(anm_table, hud_section)
-- Make sure item has transitions
local item_transitions = pattern_transitions[hud_section]
if not item_transitions then
return false
end
-- Make sure there is a previous anm to check
local start_anm = previous_anms[hud_section]
if not start_anm then
-- previous_anms[hud_section] = anm_table.anm_name
return false
end
local end_anm = anm_table.anm_name
for _, transition in ipairs(item_transitions) do
local transition_anm = transition["transition_anm"]
-- Re-add valid suffixes from previous mutations
for i, anm_suffix in ipairs(valid_anims) do
if animation_common.has_animation(hud_section, transition_anm .. anm_suffix) then
transition_anm = transition_anm .. anm_suffix
end
end
if end_anm:match(transition["end_anm"]) and
start_anm:match(transition["start_anm"]) and
start_anm ~= transition_anm and
end_anm ~= transition_anm and
start_anm ~= end_anm then
anm_table.anm_name = transition_anm
return true
end
end
return false
end
function anm_transitions(anm_table, item)
-- printf("ITEM: " .. item:section() .. " | ANM: " .. anm_table.anm_name)
local hud_section = SYS_GetParam(0, item:section(), "hud", nil)
if not hud_section then
return
end
local has_strict_transition = set_strict_transition(anm_table, hud_section)
if not has_strict_transition then
set_pattern_transition(anm_table, hud_section)
end
-- Track now playing animation
previous_anms[hud_section] = anm_table.anm_name
-- Clear valid anims
valid_anims = {}
-- printf("ITEM: " .. item:section() .. " | ANM: " .. anm_table.anm_name)
end
function on_game_start()
common.add_anim_mutator(anm_transitions, 999)
end
@@ -0,0 +1,47 @@
-- The idea is to stop the walk2sprint animation if the player stops sprinting during the animation
-- Use my transition animations script as 'truth' for currently playing animation
-- Likely to break if multiple scripts are using actor_on_hud_animation_play, but should be good enough for transition animations specifically
local current_animation = ""
local stop_animation = false
-- Slightly cleaner string equivalence check which should ignore variants like _empty or _jammed
function isAnimationEqualTo(anim_name)
if current_animation:match(anim_name) then
return true
end
return false
end
aol_anim_transitions_anm_transitions = aol_anim_transitions.anm_transitions
function aol_anim_transitions.anm_transitions(anm_table, item)
local prev_name = anm_table.anm_name
aol_anim_transitions_anm_transitions(anm_table, item)
-- Restore original animation (probably idle) if previous animation was cancelled
-- This should prevent sprint2walk from playing if its counterpart walk2sprint was cancelled
if stop_animation then
stop_animation = false
if (isAnimationEqualTo("anm_walk2sprint") or isAnimationEqualTo("anm_sprint2walk")) then
anm_table.anm_name = prev_name
end
end
current_animation = anm_table.anm_name
end
-- Detect if the player is not sprinting during the walk2sprint animation
-- Firebreath: added the elseif in because sometimes the player stops sprint animation
-- when interrupted by small obstacles like stairs
function actor_on_movement_changed(num)
if stop_animation then return end
if (not IsMoveState("mcSprint") and isAnimationEqualTo("anm_walk2sprint")) then
stop_animation = true
game.stop_hud_motion()
elseif (IsMoveState("mcSprint") and isAnimationEqualTo("anm_sprint2walk")) then
stop_animation = true
game.stop_hud_motion()
end
end
function on_game_start()
RegisterScriptCallback("actor_on_movement_changed",actor_on_movement_changed)
end
@@ -0,0 +1,80 @@
-- Script by Aoldri, edited it Haruka & BarryBogs
local melee_hitstop = {
["wpn_axe"] = true,
["wpn_axe2"] = true,
["wpn_axe3"] = true,
["wpn_knife"] = true,
["wpn_knife2"] = true,
["wpn_knife3"] = true,
["wpn_knife4"] = true,
["wpn_knife5"] = true,
["mmf_shovel_mili"] = true,
["mmf_shovel_old"] = true
}
local snd_axe = sound_object("weapons\\axe\\axe_hit")
-- settings
local slowmo_resume_time = 0.06
local slowmo_time_factor = 0.08
function on_option_change()
-- update settings
slowmo_resume_time = aoldri_axe_sounds_mcm.get_config("resume_time")
slowmo_time_factor = aoldri_axe_sounds_mcm.get_config("time_factor")
end
function resume_time()
get_console():execute("time_factor 1.0")
level.remove_pp_effector(9001)
return true
end
function play_impact_sound(weapon)
-- skip if player has no weapon out (it wasn't damage dealt directly eg. grenade)
local snd_obj = nil
if (melee_hitstop[weapon:section()]) then
snd_obj = snd_axe
end
if snd_obj == nil then return end
snd_obj:play(db.actor,0,sound_object.s2d)
end
function hitstop_effect(weapon)
if (melee_hitstop[weapon:section()]) then
get_console():execute("time_factor " .. slowmo_time_factor)
CreateTimeEvent("AoldriMelee","HitResume", slowmo_resume_time, resume_time)
level.add_pp_effector("blur.ppe", 9001, false)
end
end
function npc_on_death_callback(npc,killer)
local weapon = db.actor:active_item()
if db.actor:id() == killer:id() and db.actor:active_item() then
if (melee_hitstop[weapon:section()]) then
hitstop_effect(db.actor:active_item())
end
end
end
function npc_on_before_hit(npc,shit,bone_id,flags)
if not (shit.draftsman and shit.draftsman:id() == 0) then return end
if db.actor:active_item() == nil then return end
play_impact_sound(db.actor:active_item())
end
function monster_on_before_hit(npc,shit,bone_id,flags)
if not (shit.draftsman and shit.draftsman:id() == 0) then return end
if db.actor:active_item() == nil then return end
play_impact_sound(db.actor:active_item())
end
function on_game_start()
RegisterScriptCallback("npc_on_death_callback",npc_on_death_callback)
RegisterScriptCallback("npc_on_before_hit",npc_on_before_hit)
RegisterScriptCallback("on_option_change",on_option_change)
RegisterScriptCallback("monster_on_before_hit",monster_on_before_hit)
on_option_change()
end
@@ -0,0 +1,22 @@
-- mcm Settings Script by BarryBogs
function on_mcm_load()
op = {
id= "aoldri_axe_sounds", sh=true ,gr =
{
{ id = "title", type= "slide", link= "hitstop_mcm_banner", text= "", --[[size= {512,50},]]spacing = 20 },
{ id = "resume_time", type = "track", val = 2, max = 0.1, min = 0.01, step = 0.01, def = 0.06},
{ id = "time_factor", type = "track", val = 2, max = 0.1, min = 0.01, step = 0.01, def = 0.08},
}
}
return op
end
local defaults = {
["resume_time"] = 0.06,
["time_factor"] = 0.08,
}
function get_config(key)
if ui_mcm then return ui_mcm.get("aoldri_axe_sounds/"..key) else return defaults[key] end
end
@@ -0,0 +1,538 @@
--[[
Custom Dynamic Functors, written by demonized
Allows to add/remove item functors dynamically from script
Can override ltx-defined functors and can remove the override to return back to ltx functor
To use in your script look at example below
---------------------------------------------------------------------------------------------------------------------
local function name_condition_function(obj, bag, mode)
if obj then
return true
end
end
local function name_function(obj, bag, mode)
return "st_my_functor_string_in_xml"
end
local function action_condition_function(obj, bag, mode)
if obj then
return true
end
end
local function action_function(obj, bag, mode)
alife_create_item(obj:section(), db.actor)
end
local add_functor = custom_functor_autoinject.add_functor
add_functor("my_name_of_functor", name_condition_function, name_function, action_condition_function, action_function, override_bags<true, false>)
---------------------------------------------------------------------------------------------------------------------
to add your functor you use add_functor function which requires these arguments in order:
name: string, your name of your functor, can be any string.
If the name of functor already exists this function will overwrite functions for it
name_condition_function: function, the condition at which you will get your right-click option for item
name_function: function, the name itself, must return string ID defined in XML files for your option.
if set to return nil, the option won't appear
action_condition_function: function, the condition at which the action will be performed, usually its the same as name_condition_function
you can put nil into argument to use the same function as name_condition_function
action_function: function, the action itself to perform
override_bags: boolean. If its true, then you can override bags and modes to check for condition, otherwise it will use defaults (mode == "inventory" and bag == "actor_bag" or bag == "actor_equ" or bag == "actor_belt")
functions themselves accept obj, bag and mode arguments
obj: current object you right-clicked
bag: current bag, list of possible bags: {"actor_equ","actor_belt","actor_bag","actor_trade_bag","actor_trade","npc_bag","npc_trade","npc_trade_bag"}
mode: current mode, list of possible modes: {"inventory" , "loot" , "trade" , "repair"}
bag and mode is not enabled unless you set override_bags flag to true
removal of functor is done by calling this
--------------------------------------------------------------------------------------
local remove_functor = custom_functor_autoinject.remove_functor
remove_functor("my_name_of_functor")
--------------------------------------------------------------------------------------
you can also override existing functors defined in item's ltx by using this
---------------------------------------------------------------------------------------------------------------------
local override_functor = custom_functor_autoinject.override_functor
override_functor(slot, name_condition_function, name_function, action_condition_function, action_function, override_bags<true, false>)
---------------------------------------------------------------------------------------------------------------------
arguments are same, except you have to provide the slot (first argument) for your override. The slots are 1-10
for example if item's ltx have use1_functor and use1_action_functor then
if you want to override it you have to provide slot 1
be aware that if your name_condition_function or action_condition_function may return false
then old functor will be fired
if you don't want that behaviour, you can define generic "return true" function for those
and check condition for firing in name_function and action_function
removal of override is done by calling this
--------------------------------------------------------------------------------------
local remove_override = custom_functor_autoinject.remove_override
remove_override(slot)
--------------------------------------------------------------------------------------
--]]
local function func_index(t,a,b)
return (t[a].index) < (t[b].index)
end
local function func_index_reverse(t,a,b)
return (t[a].index) > (t[b].index)
end
local function func_value(t, a, b)
return t[a] < t[b]
end
local spairs = spairs
local string_find = string.find
local string_gsub = string.gsub
local table_remove = table.remove
local tonumber = tonumber
local unpack = unpack
--Recursive print of tables similar to PHP print_r function
local function print_r(t)
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
printf(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)]=true
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
printf(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
printf(indent..string.rep(" ",string.len(pos)+6).."}")
else
printf(indent.."["..pos.."] => "..tostring(val))
end
end
else
printf(indent..tostring(t))
end
end
end
sub_print_r(t," ")
end
local function print_table(table, subs)
local sub
if subs ~= nil then
sub = subs
else
sub = ""
end
for k,v in pairs(table) do
if type(v) == "table" then
print_table(v, sub.."["..k.."]----->")
elseif type(v) == "function" then
printf(sub.."%s = function",k)
elseif type(v) == "userdata" then
if (v.x) then
printf(sub.."%s = %s",k,utils_data.vector_to_string(v))
else
printf(sub.."%s = userdata", k)
end
elseif type(v) == "boolean" then
if v == true then
if(type(k)~="userdata") then
printf(sub.."%s = true",k)
else
printf(sub.."userdata = true")
end
else
if(type(k)~="userdata") then
printf(sub.."%s = false", k)
else
printf(sub.."userdata = false")
end
end
else
if v ~= nil then
printf(sub.."%s = %s", k,v)
else
printf(sub.."%s = nil", k,v)
end
end
end
end
-- Removing element from table and shifting down both key and value
-- Modes: 0 - index, 1 - value, 2 - key, 3 - key-index
local function table_remove_shift(t, val, mode)
local removed = false
local res
if mode == 0 then
for k, v in spairs(t, func_index) do
if removed then
t[k - 1] = v
if t[k - 1].index then
t[k - 1].index = t[k - 1].index - 1
end
if t[k - 1].properties_index then
t[k - 1].properties_index = t[k - 1].properties_index - 1
end
t[k] = nil
elseif v.index and v.index == val then
res = t[k]
t[k] = nil
removed = true
end
end
elseif mode == 1 then
for k, v in spairs(t, func_value) do
if removed then
t[k - 1] = v - 1
t[k] = nil
elseif v == val then
res = t[k]
t[k] = nil
removed = true
end
end
elseif mode == 2 then
for k, v in spairs(t, func_value) do
if removed then
t[k] = v - 1
elseif v == val then
res = t[k]
t[k] = nil
removed = true
end
end
elseif mode == 3 then
for k, v in spairs(t, func_index) do
if removed then
if t[k].index then
t[k].index = t[k].index - 1
end
elseif v.index and v.index == val then
res = t[k]
t[k] = nil
removed = true
end
end
end
return res
end
local ui_inventory_init = ui_inventory.UIInventory.__init
ui_inventory.UIInventory.__init = function(self)
ui_inventory_init(self)
self.custom_functor = {}
self.custom_functor_names = {}
end
local NameCustom = ui_inventory.UIInventory.Name_Custom
function ui_inventory.UIInventory:Name_Custom(obj, bag, temp, i)
obj = self:CheckItem(obj,"Name_Custom " .. i)
if self.custom_functor[i] and self.custom_functor[i].cond_name(obj, bag, self.mode) then
return self.custom_functor[i].func_name(obj, bag, self.mode)
else
return NameCustom(self, obj, bag, temp, i)
end
end
local ActionCustom = ui_inventory.UIInventory.Action_Custom
function ui_inventory.UIInventory:Action_Custom(obj, bag, temp, i)
obj = self:CheckItem(obj,"Action_Custom " .. i)
if self.custom_functor[i] and self.custom_functor[i].cond_action(obj, bag, self.mode) then
return self.custom_functor[i].func_action(obj, bag, self.mode)
else
return ActionCustom(self, obj, bag, temp, i)
end
end
ui_inventory.UIInventory.get_max_custom_functor = function(self)
local max = 0
local max_custom = {}
local max_index = 0
for k, v in pairs(self.properties) do
if string_find(k, "custom_.*") then
if v.index > max_index then
max_index = v.index
end
local x = tonumber(string_gsub(k, "custom_(.*)", "%1"), nil)
if x > max then
max = x
max_custom = v
end
end
end
return max, max_custom, max_index
end
local modes = {
["inventory"] = true,
["loot"] = true,
["trade"] = true,
["repair"] = true
}
local bags = {
["actor_equ"] = true,
["actor_belt"] = true,
["actor_bag"] = true,
["actor_trade_bag"] = true,
["actor_trade"] = true,
["npc_bag"] = true,
["npc_trade"] = true,
["npc_trade_bag"] = true
}
ui_inventory.UIInventory.Mode_Custom_Functor = function(self, obj, bag, temp, i)
return modes[self.mode]
end
ui_inventory.UIInventory.Cont_Custom_Functor = function(self, obj, bag, temp, i)
return bags[bag]
end
ui_inventory.UIInventory.add_custom_functor = function(self, name, cond_name, func_name, cond_action, func_action, override_bags)
local custom_functor_slot
if self.custom_functor_names[name] then
custom_functor_slot = self.custom_functor_names[name]
self.custom_functor[custom_functor_slot].cond_name = cond_name
self.custom_functor[custom_functor_slot].func_name = func_name
self.custom_functor[custom_functor_slot].cond_action = cond_action
self.custom_functor[custom_functor_slot].func_action = func_action
self.properties["custom_" .. custom_functor_slot].mode_func[1] = override_bags and "Mode_Custom_Functor" or "Mode_Custom"
self.properties["custom_" .. custom_functor_slot].cont_func[1] = override_bags and "Cont_Custom_Functor" or "Cont_Custom"
else
local max, max_custom, max_index = self:get_max_custom_functor()
local custom_num = max + 1
local properties_num = max_index + 1
for k, v in spairs(self.properties, func_index_reverse) do
if v.index > max_index then
printf("%s, %s", k, v.index)
v.index = v.index + 1
else
printf("%s, %s, max custom_functor reached", k, v.index)
break
end
end
self.properties["custom_" .. custom_num] = {
index = properties_num,
name_func = {"Name_Custom", max_custom["name_func"][2] + 1},
mode_func = {override_bags and "Mode_Custom_Functor" or "Mode_Custom", max_custom["mode_func"][2] + 1},
cont_func = {override_bags and "Cont_Custom_Functor" or "Cont_Custom", max_custom["cont_func"][2] + 1},
precondition1 = {"Name_Custom", max_custom["precondition1"][2] + 1},
action = {"Action_Custom", max_custom["action"][2] + 1}
}
custom_functor_slot = custom_num
self.custom_functor[custom_functor_slot] = {
index = custom_functor_slot,
properties_index = properties_num,
name = name,
cond_name = cond_name,
func_name = func_name,
cond_action = cond_action,
func_action = func_action
}
self.custom_functor_names[name] = custom_functor_slot
end
end
ui_inventory.UIInventory.remove_custom_functor = function(self, name)
if not self.custom_functor_names[name] then return end
local index = table_remove_shift(self.custom_functor_names, self.custom_functor_names[name], 2)
if not index then return end
local custom_functor = table_remove_shift(self.custom_functor, index, 0)
if not custom_functor then return end
local removed = false
for k, v in spairs(self.properties, func_index) do
if string_find(k, "custom_.*") then
if removed then
local x = tonumber(string_gsub(k, "custom_(.*)", "%1"), nil) - 1
self.properties["custom_" .. x] = self.properties[k]
self.properties["custom_" .. x].index = self.properties["custom_" .. x].index - 1
self.properties["custom_" .. x].name_func[2] = self.properties["custom_" .. x].name_func[2] - 1
self.properties["custom_" .. x].mode_func[2] = self.properties["custom_" .. x].mode_func[2] - 1
self.properties["custom_" .. x].cont_func[2] = self.properties["custom_" .. x].cont_func[2] - 1
self.properties["custom_" .. x].precondition1[2] = self.properties["custom_" .. x].precondition1[2] - 1
self.properties["custom_" .. x].action[2] = self.properties["custom_" .. x].action[2] - 1
self.properties[k] = nil
elseif v.index == custom_functor.properties_index then
self.properties[k] = nil
removed = true
end
elseif removed then
v.index = v.index - 1
end
end
end
ui_inventory.UIInventory.override_functor = function(self, slot, cond_name, func_name, cond_action, func_action, override_bags)
self.custom_functor[slot] = {
cond_name = cond_name,
func_name = func_name,
cond_action = cond_action,
func_action = func_action
}
self.properties["custom_" .. slot].mode_func[1] = override_bags and "Mode_Custom_Functor" or "Mode_Custom"
self.properties["custom_" .. slot].cont_func[1] = override_bags and "Cont_Custom_Functor" or "Cont_Custom"
end
ui_inventory.UIInventory.remove_override = function(self, slot)
self.custom_functor[slot] = nil
self.properties["custom_" .. slot].mode_func[1] = "Mode_Custom"
self.properties["custom_" .. slot].cont_func[1] = "Cont_Custom"
end
ui_inventory.UIInventory.get_functor_at_slot = function(self, slot)
return self.custom_functor[slot]
end
ui_inventory.UIInventory.get_functor_by_name = function(self, name)
if self.custom_functor_names[name] then
return self.custom_functor[self.custom_functor_names[name]], self.custom_functor_names[name]
end
end
-- Adding
local first_update_pending = true
local functor_queue = {}
local function add_to_queue(type, ...)
functor_queue[#functor_queue + 1] = {
type = type,
data = {...}
}
end
local function process_queue()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
printf("Custom functors, processing queue")
for i, v in ipairs(functor_queue) do
printf("Custom functors, type %s", v.type)
ui_inventory.GUI[v.type](ui_inventory.GUI, unpack(v.data))
end
functor_queue = {}
first_update_pending = false
end
local function actor_on_first_update()
process_queue()
end
function add_functor(name, cond_name, func_name, cond_action, func_action, override_bags)
if not name then return end
local cond_action = cond_action or cond_name
if first_update_pending then
add_to_queue("add_custom_functor", name, cond_name, func_name, cond_action, func_action, override_bags)
return
end
ui_inventory.GUI:add_custom_functor(name, cond_name, func_name, cond_action, func_action, override_bags)
end
function remove_functor(name)
if not name then return end
if first_update_pending then
add_to_queue("remove_custom_functor", name)
return
end
ui_inventory.GUI:remove_custom_functor(name)
end
function override_functor(slot, cond_name, func_name, cond_action, func_action, override_bags)
if slot < 1 or slot > 10 then
printf("functor slot is not valid, min 1, max 10, your slot: %s", slot)
return
end
local cond_action = cond_action or cond_name
if first_update_pending then
add_to_queue("override_functor", slot, cond_name, func_name, cond_action, func_action, override_bags)
return
end
ui_inventory.GUI:override_functor(slot, cond_name, func_name, cond_action, func_action, override_bags)
end
function remove_override(slot)
if slot < 1 or slot > 10 then
printf("functor slot is not valid min 1, max 10, your slot: %s", slot)
return
end
if first_update_pending then
add_to_queue("remove_override", slot)
return
end
ui_inventory.GUI:remove_override(slot)
end
function get_functor_at_slot(slot)
if first_update_pending then
add_to_queue("get_functor_at_slot", slot)
return
end
return ui_inventory.GUI:get_functor_at_slot(slot)
end
function get_functor_by_name(name)
if first_update_pending then
add_to_queue("get_functor_by_name", name)
return
end
return ui_inventory.GUI:get_functor_by_name(name)
end
function print_properties()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
for k, v in spairs(ui_inventory.GUI.properties, func_index) do
printf("[" .. k .. "] => ")
print_r(v)
end
end
function print_custom_functor()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
print_r(ui_inventory.GUI.custom_functor)
end
function print_custom_functor_names()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
print_r(ui_inventory.GUI.custom_functor_names)
end
function on_game_start()
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
end
@@ -0,0 +1,618 @@
-- Crafting items by right clicking
-- Supports multiple entries and any item combinations
-- Supports multicrafting all items at once until enough material in the inventory with holding Left Shift
-- Written by demonized
--[[
Crafting recipes
The structure of crafting recipes is
tool
item1:amount1, (item2:amount2_min-amount2_max), ...
recipe1
recipe2
...
Tool can craft multiple items at once per entry (item1, item2), different amount of items (item1:amount1) or randomized amount of items between min and max (item2:amount2_min-amount2_max)
Recipes has form of "item1:amount1,item2:amount2,..."
Order of recipe matters, first one possible to use will be used
You can omit amount if you except 1 item to be consumed, ie.
vodka,box_matches,prt_i_paper is equivalent to vodka:1,box_matches:1,prt_i_paper:1
Tools that use condition can be written as "item1:0.2" to degrade 20% of item
It is possible to consume the whole tool if it has at least a condition specified in a recipe. To enable that, tool can be written as "item1>0.2". The ">", ">=", "<", "<=" comparisons are supported.
Example of crafting recipes table
craft_recipes = {
vodka = {
["molotov_cocktail"] = {
"vodka,box_matches,prt_i_paper",
"vodka:1,box_matches:1,prt_o_fabrics_1:1",
},
},
vodka2 = {
["molotov_cocktail:2, prt_i_paper:1-2"] = {
"vodka2:1,box_matches:1,prt_i_paper:1",
"vodka2:1,box_matches:1,prt_o_fabrics_1:1",
},
}
}
To add a crafting recipe, use function demonized_crafter.add_craft_recipe(craft_recipe_table, args)
craft_recipe_table is the table with the structure as above
args is optional table and specifies additional arguments to craft menu. Possible table fields in args table are:
before - boolean, tells to add recipe before existing ones
craft_strings - table, contains string ids that will act as replacements for default "Craft: <item>" string in menu, have same structure as craft_recipe_table, for example:
{
vodka = {
molotov_cocktail = "st_make_molotov"
},
vodka2 = {
molotov_cocktail = "st_make_molotov"
},
}
To remove recipes use function demonized_crafter.remove_craft_recipe(craft_recipe_table)
craft_recipe_table is the table with the structure as above
You can remove all recipes for a given tool with function demonized_crafter.remove_all_recipes_for_tool(tool)
When crafting is successful, the tip will be printed telling what items were produced and consumes
When not, the tip will print what recipes is enabled for an item and tool and what items are and not in players inventory
--]]
local text_color = utils_xml.get_color("pda_white")
local arg_color = utils_xml.get_color("d_green")
local bad_color = utils_xml.get_color("d_red")
local function colorize(s)
return arg_color .. s .. text_color
end
local function colorize_bad(s)
return bad_color .. s .. text_color
end
local print_tip = print_tip or function(text, ...)
local text = tostring(text)
-- printf(text, ...)
if not db.actor then
return
end
local ico = "ui_inGame2_Dengi_otdani"
local text_color = utils_xml.get_color("pda_white")
local arg_color = utils_xml.get_color("d_green")
local function colorize(s)
return arg_color .. s .. text_color
end
local i = 0
local t = {...}
if #t > 0 then
local function sr(a)
i = i + 1
if (type(t[i]) == 'userdata') then
if (t[i].x and t[i].y) then
return colorize(vec_to_str(t[i]))
end
return colorize('userdata')
end
return colorize(tostring(t[i]))
end
text = string.gsub(game.translate_string(text), "%%s", sr)
else
text = game.translate_string(text)
end
text = text_color .. text
news_manager.send_tip(db.actor, text, nil, ico, 6000)
end
local gc = game.translate_string
local function table_find(t, el)
for i = 1, #t do
if t[i] == el then
return i
end
end
end
local degradable_cache = {}
function is_degradable(sec, obj)
if degradable_cache[sec] ~= nil then
return degradable_cache[sec]
end
local res
local function degradable()
return utils_item.is_degradable(nil, sec) and not IsItem("part", sec)
end
if obj then
sec = obj:section()
res = degradable() or IsWeapon(obj) or IsOutfit(obj) or IsHeadgear(obj) or IsArtefact(obj)
else
res = degradable()
end
-- Cast to boolean
degradable_cache[sec] = not not res
return degradable_cache[sec]
end
local holding_shift = false
local multi_craft = false
local craft_func_key = "st_demonized_crafter" -- DONT CHANGE THIS!!
craft_recipes = {}
craft_item_strings = {}
-- Helper functions to add and remove recipes
-- They accept same table structure as described above
function add_craft_recipe(craft_recipe_table, args)
if not args then args = {} end
for tool, items in pairs(craft_recipe_table) do
if not craft_recipes[tool] then
craft_recipes[tool] = items
else
for item, recipes in pairs(items) do
if not craft_recipes[tool][item] then
craft_recipes[tool][item] = recipes
else
for _, recipe in ipairs(recipes) do
local recipe = string.gsub(recipe, ":1", "")
if not table_find(craft_recipes[tool][item], recipe) then
if args.before then
table.insert(craft_recipes[tool][item], 1, recipe)
else
table.insert(craft_recipes[tool][item], recipe)
end
end
end
end
end
end
end
if args.craft_strings then
for tool, items in pairs(args.craft_strings) do
if not craft_item_strings[tool] then
craft_item_strings[tool] = {}
end
for item, str in pairs(items) do
craft_item_strings[tool][item] = str
end
end
end
refresh_craft_menu()
return craft_recipes
end
function remove_craft_recipe(craft_recipe_table)
local remove_functor = custom_functor_autoinject.remove_functor
for tool, items in pairs(craft_recipe_table) do
if craft_recipes[tool] then
for item, recipes in pairs(items) do
if craft_recipes[tool][item] then
if craft_item_strings[tool] then
craft_item_strings[tool][item] = nil
end
for _, recipe in ipairs(recipes) do
local pos = table_find(craft_recipes[tool][item], recipe)
if pos then
table.remove(craft_recipes[tool][item], pos)
end
local recipe = string.gsub(recipe, ":1", "")
local pos = table_find(craft_recipes[tool][item], recipe)
if pos then
table.remove(craft_recipes[tool][item], pos)
end
end
if is_empty(craft_recipes[tool][item]) then
remove_functor(craft_func_key .. "_" .. tool .. "_" .. item)
craft_recipes[tool][item] = nil
end
end
end
if is_empty(craft_recipes[tool]) then
craft_recipes[tool] = nil
end
end
end
refresh_craft_menu()
return craft_recipes
end
function remove_all_recipes_for_tool(tool)
if not craft_recipes[tool] then return end
for item, recipes in pairs(craft_recipes[tool]) do
remove_functor(craft_func_key .. "_" .. tool .. "_" .. item)
end
craft_recipes[tool] = nil
refresh_craft_menu()
return craft_recipes
end
-- This function expands craft recipes in a way that any item in recipe is considered a tool and can invoke right click menu
-- Unused for now
function expand_craft()
end
function add_craft_menu(recipe_table)
local add_functor = custom_functor_autoinject.add_functor
local remove_functor = custom_functor_autoinject.remove_functor
for tool, items in pairs(recipe_table) do
for item, recipes in pairs(items) do
local result_item = item
local result_item_table = {}
for i, v in ipairs(str_explode(result_item, ",")) do
local s = str_explode(v, ":")
local res = { section = s[1] }
if s[2] then
if s[2]:find("-") then
local r = str_explode(s[2], "-")
res.amount = function()
return math.random(r[1], r[2])
end
res.amount_str = s[2]
else
res.amount = function() return tonumber(s[2]) end
res.amount_str = s[2]
end
else
res.amount = function() return 1 end
res.amount_str = 1
end
table.insert(result_item_table, res)
end
local function print_result_items()
local s = ""
for i, v in ipairs(result_item_table) do
-- Return craft string + item name to craft
local item_name = ui_item.get_sec_name(v.section)
local amount = v.amount_str
s = s .. item_name
if i ~= #result_item_table then
s = s .. ", "
end
end
return s
end
local craft_func = {
check = function(obj, bag, mode)
-- Check tool
local modes = {
["inventory"] = true,
}
local bags = {
["actor_bag"] = true,
["actor_equ"] = true,
["actor_belt"] = true,
}
return obj:section() == tool and modes[mode] and bags[bag]
end,
str = function(obj, bag, mode)
-- Enable multicraft is shift was held while right clicking
multi_craft = holding_shift
if craft_item_strings[tool] and craft_item_strings[tool][item] then
return gc(craft_item_strings[tool][item])
else
return gc(craft_func_key) .. (multi_craft and (" " .. gc(craft_func_key .. "_craft_all")) or "") .. ": " .. print_result_items()
end
end,
func = function(obj, bag, mode)
-- Parse recipe table
local res = {}
local craft_items = {}
local craft_item_modes = {}
for _, recipe in ipairs(recipes) do
local t = {}
for _, m in pairs(str_explode(trim(recipe), ",")) do
if m:find("[<>]") then
local material_data = {m:match("(.*)([<>][=]*)(.*)")}
local material = material_data[1]
local func = material_data[2]
local amount = material_data[3] and tonumber(material_data[3]) or 1
if not t[material] then
t[material] = amount
end
if not craft_items[material] then
craft_items[material] = amount
end
craft_item_modes[material] = {func, amount}
else
local material = str_explode(m, ":")
if not t[material[1]] then
t[material[1]] = 0
end
if not craft_items[material[1]] then
craft_items[material[1]] = 0
end
if not material[2] then
material[2] = 1
end
material[2] = tonumber(material[2])
t[material[1]] = t[material[1]] + material[2]
craft_items[material[1]] = craft_items[material[1]] + material[2]
end
end
res[#res + 1] = t
end
-- Get items for recipes
local actor = obj:parent()
local inventory_items = {}
local function iterate(npc, obj)
local sec = obj:section()
if not craft_items[sec] then return end
if not inventory_items[sec] then
inventory_items[sec] = {}
end
if IsItem("multiuse", sec) then
inventory_items[sec][obj:id()] = obj:get_remaining_uses()
elseif is_degradable(sec, obj) then
inventory_items[sec][obj:id()] = round_idp(obj:condition(), 2)
else
inventory_items[sec][obj:id()] = 1
end
end
if IsStalker(actor) then
actor:iterate_inventory(iterate, actor)
elseif IsInvbox(actor) then
actor:iterate_inventory_box(iterate, actor)
else
print_tip("item parent is undefined %s, %s", actor:name(), actor:section())
return
end
local function count_items(sec)
if not inventory_items[sec] then return 0 end
local s = 0
for k, v in pairs(inventory_items[sec]) do
s = s + v
end
return s
end
-- Check recipes for possibility to craft
local can_craft_at_all = true
local crafted_amount = 0
local crafted_items = {}
local spent_items = {}
local wasted_items = {}
local function print_crafted_items()
local s = ""
local sep = ", "
for k, v in pairs(crafted_items) do
local item_name = ui_item.get_sec_name(k)
local amount = v
s = s .. item_name .. ":" .. amount .. sep
end
s = s:sub(1, -(sep:len() + 1))
return s
end
local function craft_item_mode_check(craft_item_mode, inv_amount)
local t = {
['>'] = function() return inv_amount > craft_item_mode[2] end,
['>='] = function() return inv_amount >= craft_item_mode[2] end,
['<'] = function() return inv_amount < craft_item_mode[2] end,
['<='] = function() return inv_amount <= craft_item_mode[2] end,
}
return t[craft_item_mode[1]] and t[craft_item_mode[1]]()
end
repeat
can_craft_at_all = true
empty_table(spent_items)
local crafted = false
for i, r in ipairs(res) do
local can_craft = true
spent_items[i] = {}
for recipe_item, recipe_amount in pairs(r) do
if craft_item_modes[recipe_item] then
spent_items[i][recipe_item] = {count_items(recipe_item), 1}
if not craft_item_mode_check(craft_item_modes[recipe_item], count_items(recipe_item)) then
can_craft = false
end
else
spent_items[i][recipe_item] = {count_items(recipe_item), recipe_amount}
if spent_items[i][recipe_item][1] < recipe_amount then
can_craft = false
end
end
end
-- If can craft - craft the item
if can_craft then
local function sort_asc(t, a, b)
return t[a] < t[b]
end
for recipe_item, v in pairs(spent_items[i]) do
local recipe_amount = v[2]
-- Consume items with least uses first
for id, amount in spairs(inventory_items[recipe_item], sort_asc) do
if recipe_amount <= 0 then
break
end
if is_degradable(recipe_item, level.object_by_id(id)) then
if craft_item_modes[recipe_item] then
alife_release_id(id)
else
utils_item.degrade(level.object_by_id(id), recipe_amount)
end
elseif amount < recipe_amount then
alife_release_id(id)
else
utils_item.discharge(level.object_by_id(id), recipe_amount)
end
if not wasted_items[recipe_item] then
wasted_items[recipe_item] = 0
end
wasted_items[recipe_item] = wasted_items[recipe_item] + math.min(recipe_amount, amount)
inventory_items[recipe_item][id] = inventory_items[recipe_item][id] - recipe_amount
recipe_amount = recipe_amount - amount
if inventory_items[recipe_item][id] <= 0 then
inventory_items[recipe_item][id] = nil
end
end
end
for i, v in ipairs(result_item_table) do
local result_item = v.section
local amount = v.amount()
if not crafted_items[result_item] then
crafted_items[result_item] = 0
end
crafted_items[result_item] = crafted_items[result_item] + amount
for j = 1, amount do
alife_create_item(result_item, db.actor)
crafted_amount = crafted_amount + 1
crafted = true
end
end
-- Play camera animation
if not multi_craft then
-- Print what is crafted and what items were consumed
local tip_string = text_color .. gc(craft_func_key .. "_craft_success") .. " " .. colorize(print_crafted_items()) .. " \\n" .. gc(craft_func_key .. "_craft_spent_items")
for recipe_item, recipe_amount in pairs(r) do
tip_string = tip_string .. " \\n" .. ui_item.get_sec_name(recipe_item) .. ": " .. (craft_item_modes[recipe_item] and colorize("1") or (is_degradable(recipe_item) and colorize(round(recipe_amount * 100) .. "%") or colorize(recipe_amount)))
end
print_tip(tip_string)
actor_effects.play_item_fx("item_combination")
return
end
end
end
can_craft_at_all = crafted
until not can_craft_at_all
-- Disable multi craft if it was enabled
multi_craft = false
-- If crafted something and was in multi craft
if crafted_amount > 0 then
-- Print what is crafted and what items were consumed
local tip_string = text_color .. gc(craft_func_key .. "_craft_success") .. " " .. colorize(print_crafted_items()) .. " \\n" .. gc(craft_func_key .. "_craft_spent_items")
for recipe_item, recipe_amount in pairs(wasted_items) do
tip_string = tip_string .. " \\n" .. ui_item.get_sec_name(recipe_item) .. ": " .. (craft_item_modes[recipe_item] and colorize("1") or (is_degradable(recipe_item) and colorize(round(recipe_amount * 100) .. "%") or colorize(recipe_amount)))
end
print_tip(tip_string)
-- Play camera animation
actor_effects.play_item_fx("item_combination")
return
end
-- If cant craft - print tip of possible recipes and required amount
local failed_tip_string = bad_color .. gc(craft_func_key .. "_craft_fail") .. text_color .. " " .. colorize(print_result_items()) .. " \\n" .. gc(craft_func_key .. "_craft_possible_combinations") .. ": "
for i, v in ipairs(spent_items) do
for recipe_item, recipe_amount in pairs(v) do
failed_tip_string = failed_tip_string .. " \\n" .. ui_item.get_sec_name(recipe_item) .. ": " ..
(
craft_item_modes[recipe_item] and
(
(
craft_item_mode_check(craft_item_modes[recipe_item], recipe_amount[1])
and
colorize(round(recipe_amount[1] * 100) .. "%")
or
colorize_bad(round(recipe_amount[1] * 100) .. "%")
) .. " " .. craft_item_modes[recipe_item][1] .. " " .. colorize(round(craft_item_modes[recipe_item][2] * 100) .. "%")
)
or
(
recipe_amount[1] < recipe_amount[2] and
(
is_degradable(recipe_item)
and
colorize_bad(round(recipe_amount[1] * 100))
or
colorize_bad(recipe_amount[1])
)
or
(
is_degradable(recipe_item)
and
colorize(round(recipe_amount[1] * 100))
or
colorize(recipe_amount[1])
)
)
.. "/" ..
(
is_degradable(recipe_item)
and
colorize(round(recipe_amount[2] * 100) .. "%")
or
colorize(recipe_amount[2])
)
)
end
if i ~= #spent_items then
failed_tip_string = failed_tip_string .. " \\n \\n" .. gc(craft_func_key .. "_craft_or") .. " \\n"
end
end
print_tip(failed_tip_string)
-- Print generic message if there are too much recipes
if #recipes > 2 then
local failed_tip_small_string = bad_color .. gc(craft_func_key .. "_craft_fail") .. text_color .. " " .. colorize(print_result_items()) .. " \\n" .. gc(craft_func_key .. "_craft_check_pda_news")
print_tip(failed_tip_small_string)
end
end
}
add_functor(craft_func_key .. "_" .. tool .. "_" .. result_item, craft_func.check, craft_func.str, nil, craft_func.func, true)
end
end
end
function remove_craft_menu()
local add_functor = custom_functor_autoinject.add_functor
local remove_functor = custom_functor_autoinject.remove_functor
for tool, items in pairs(craft_recipes) do
for item, recipes in pairs(items) do
remove_functor(craft_func_key .. "_" .. tool .. "_" .. item)
end
end
end
function refresh_craft_menu()
remove_craft_menu()
add_craft_menu(craft_recipes)
end
function on_key_hold(key)
if key == DIK_keys["DIK_LSHIFT"] then
holding_shift = true
end
end
function on_key_release(key)
if key == DIK_keys["DIK_LSHIFT"] then
holding_shift = false
end
end
function on_game_start()
RegisterScriptCallback("on_key_hold", on_key_hold)
RegisterScriptCallback("on_key_release", on_key_release)
refresh_craft_menu()
end
@@ -0,0 +1,23 @@
craft_recipes = {
mmf_shovel_old = {
wpn_axe2 = {
"sharpening_stones:3, mmf_shovel_old>=0.20",
},
},
mmf_shovel_mili = {
wpn_axe2 = {
"sharpening_stones:3, mmf_shovel_mili>=0.20",
},
}
}
args = {
craft_strings = {
mmf_shovel_old = {
wpn_axe2 = "st_sharpen_shovel"
},
mmf_shovel_mili = {
wpn_axe2 = "st_sharpen_shovel"
}
}
}
demonized_crafter.add_craft_recipe(craft_recipes, args)
@@ -0,0 +1,31 @@
function creature_on_before_hit(npc, shit, bone_id, flags)
if not (shit.draftsman and shit.draftsman:id() == AC_ID) then return end
local wpn = db.actor:active_item()
if not wpn then return end
if (not db.actor:active_detector()) then return end
if (not new_axes[wpn:section()]) then return end
local one_handed_attacks = 0.4
shit.power = shit.power * one_handed_attacks
end
new_axes = {
wpn_axe = true,
wpn_axe2 = true,
wpn_axe3 = true,
mmf_shovel_mili = true,
mmf_shovel_old = true
}
function actor_on_hud_animation_play(anm_table, item)
if not item then return end
if (not new_axes[item:section()]) then return end
if anm_table.anm_name == "anm_show" and db.actor:active_detector() then
anm_table.anm_name = "anm_1h_show"
end
end
function on_game_start()
RegisterScriptCallback("npc_on_before_hit", creature_on_before_hit)
RegisterScriptCallback("monster_on_before_hit", creature_on_before_hit)
RegisterScriptCallback("actor_on_hud_animation_play", actor_on_hud_animation_play)
end
@@ -0,0 +1,26 @@
-- Melee Blocking Script by BarryBogs for Heavy Melee Rework
function on_game_start()
RegisterScriptCallback("actor_on_before_hit", actor_on_before_hit)
-- RegisterScriptCallback("actor_on_weapon_lower", actor_on_weapon_lower)
-- RegisterScriptCallback("actor_on_weapon_raise", actor_on_weapon_raise)
end
function actor_on_before_hit(s_hit)
local wpn = db.actor:active_item()
if not wpn then return end
if game.actor_weapon_lowered() == false then return end
if not heavy_melee[wpn:section()] then return end
if s_hit.type == 5 or s_hit.type == 6 then
local melee_blocking = 0.66
s_hit.power = s_hit.power * melee_blocking
end
end
heavy_melee = {
wpn_axe = true,
wpn_axe2 = true,
wpn_axe3 = true,
mmf_shovel_mili = true,
mmf_shovel_old = true,
}
@@ -0,0 +1,225 @@
-- Script by Utjan
-- Degrades melee weapons on hitting geometry, physics objects or stalkers/mutants.
-- Uses thial's ray script for finding geometry.
function on_game_start()
RegisterScriptCallback("npc_on_before_hit", on_enemy_hit)
RegisterScriptCallback("monster_on_before_hit", on_enemy_hit)
RegisterScriptCallback("actor_on_hud_animation_mark", actor_on_hud_animation_mark)
RegisterScriptCallback("physic_object_on_hit_callback", physic_object_on_hit_callback)
end
-- Geometry is terrain, walls, trees, the map, etc
geometry_degrade = {
wpn_knife = 0.01,
wpn_knife2 = 0.00875,
wpn_knife3 = 0.0075,
wpn_knife4 = 0.00625,
wpn_knife5 = 0.005,
wpn_axe = 0.01,
wpn_axe2 = 0.0075,
wpn_axe3 = 0.005
}
-- Physics object like the breakable wooden boxes
phys_degrade = {
wpn_knife = 0.01,
wpn_knife2 = 0.00875,
wpn_knife3 = 0.0075,
wpn_knife4 = 0.00625,
wpn_knife5 = 0.005,
wpn_axe = 0.01,
wpn_axe2 = 0.0075,
wpn_axe3 = 0.005
}
-- Stalkers and mutants
enemy_degrade = {
wpn_knife = 0.01,
wpn_knife2 = 0.00875,
wpn_knife3 = 0.0075,
wpn_knife4 = 0.00625,
wpn_knife5 = 0.005,
wpn_axe = 0.01,
wpn_axe2 = 0.0075,
wpn_axe3 = 0.005
}
-- Multiplies condition loss on light attack. For modders to modify with scripts.
light_atk_degrade_mult = {
wpn_knife = 1,
wpn_knife2 = 1,
wpn_knife3 = 1,
wpn_knife4 = 1,
wpn_knife5 = 1,
wpn_axe = 1,
wpn_axe2 = 1,
wpn_axe3 = 1,
}
-- Multiplies condition loss on heavy attack. For modders to modify with scripts.
heavy_atk_degrade_mult = {
wpn_knife = 1,
wpn_knife2 = 1,
wpn_knife3 = 1,
wpn_knife4 = 1,
wpn_knife5 = 1,
wpn_axe = 1,
wpn_axe2 = 1,
wpn_axe3 = 1,
}
valid_knife = {
wpn_knife = true,
wpn_knife2 = true,
wpn_knife3 = true,
wpn_knife4 = true,
wpn_knife5 = true,
}
valid_axe = {
wpn_axe = true,
wpn_axe2 = true,
wpn_axe3 = true,
}
local last_value
local last_wpn_section
function actor_on_hud_animation_mark(value , name)
last_value = value -- Indicates light or heavy attack
local wpn = db.actor:active_item()
if not wpn then return end
last_wpn_section = wpn:section()
if last_wpn_section and last_value and IsWeapon(wpn) and (IsItem("fake_ammo_wpn",last_wpn_section)) then
local range = get_melee_range(last_wpn_section, last_value)
local ray = thial_ray.geometry_ray(range + 1, range, nil, 1+2+4+8)
local pos = device().cam_pos
local angle = device().cam_dir
local result = ray:get(vector():set(pos), angle)
if result.in_contact then
CreateTimeEvent("melee_degrade","geometry_degrade", 0.1, function ()
if not geometry_degrade[last_wpn_section] then return true end
local degrade_val = geometry_degrade[last_wpn_section]
local multiplier = valid_axe[last_wpn_section] and get_config("axe_loss_mult") or valid_knife[last_wpn_section] and get_config("knife_loss_mult")
multiplier = multiplier * get_config("geometry_loss_mult")
if last_value == 5 then
multiplier = multiplier * get_config("light_loss_mult") * light_atk_degrade_mult[last_wpn_section]
elseif last_value == 6 then
multiplier = multiplier * get_config("heavy_loss_mult") * heavy_atk_degrade_mult[last_wpn_section]
end
degrade_val = degrade_val * multiplier
--printf("degrade by " .. degrade_val)
utils_item.degrade(wpn, degrade_val)
last_value = nil
last_wpn_section = nil
return true
end)
return last_wpn_section
end
end
end
function physic_object_on_hit_callback(obj, amount, local_direction, who, bone_index)
local wpn = db.actor:active_item()
if not wpn then return end
if last_wpn_section and last_value and IsWeapon(wpn) and (IsItem("fake_ammo_wpn",wpn:section())) then
if not phys_degrade[last_wpn_section] then return end
local degrade_val = phys_degrade[last_wpn_section]
local multiplier = valid_axe[last_wpn_section] and get_config("axe_loss_mult") or valid_knife[last_wpn_section] and get_config("knife_loss_mult")
multiplier = multiplier * get_config("phys_loss_mult")
if last_value == 5 then
multiplier = multiplier * get_config("light_loss_mult") * light_atk_degrade_mult[last_wpn_section]
elseif last_value == 6 then
multiplier = multiplier * get_config("heavy_loss_mult") * heavy_atk_degrade_mult[last_wpn_section]
end
degrade_val = degrade_val * multiplier
--printf("degrade by " .. degrade_val)
utils_item.degrade(wpn, degrade_val)
last_value = nil
last_wpn_section = nil
RemoveTimeEvent("melee_degrade","geometry_degrade")
return last_wpn_section
end
end
function on_enemy_hit(npc,shit,bone_id,flags)
if not (shit.draftsman and shit.draftsman:id() == AC_ID) then return end
local wpn = db.actor:active_item()
if not wpn then return end
if last_wpn_section and last_value and IsWeapon(wpn) and (IsItem("fake_ammo_wpn",wpn:section())) then
if not enemy_degrade[last_wpn_section] then return end
local degrade_val = enemy_degrade[last_wpn_section]
local multiplier = valid_axe[last_wpn_section] and get_config("axe_loss_mult") or valid_knife[last_wpn_section] and get_config("knife_loss_mult")
multiplier = multiplier * get_config("enemy_loss_mult")
if last_value == 5 then
multiplier = multiplier * get_config("light_loss_mult") * light_atk_degrade_mult[last_wpn_section]
elseif last_value == 6 then
multiplier = multiplier * get_config("heavy_loss_mult") * heavy_atk_degrade_mult[last_wpn_section]
end
degrade_val = degrade_val * multiplier
--printf("degrade by " .. degrade_val)
utils_item.degrade(wpn, degrade_val)
last_value = nil
last_wpn_section = nil
RemoveTimeEvent("melee_degrade","geometry_degrade")
return last_wpn_section
end
end
function get_melee_range(sec, value)
local range = 0
if value == 5 then
local dist = SYS_GetParam(2, sec, "spash1_dist")
local radius = SYS_GetParam(2, sec, "spash1_radius")
range = dist + radius
elseif value == 6 then
local dist = SYS_GetParam(2, sec, "spash2_dist")
local radius = SYS_GetParam(2, sec, "spash2_radius")
range = dist + radius
end
return range
end
-- MCM
local defaults = {
["axe_loss_mult"] = 1,
["knife_loss_mult"] = 1,
["geometry_loss_mult"] = 1,
["phys_loss_mult"] = 1,
["enemy_loss_mult"] = 2,
["light_loss_mult"] = 1,
["heavy_loss_mult"] = 2,
}
function get_config(key)
local opt = ui_mcm and ui_mcm.get("melee_degrade_onhit/"..key)
if opt ~= nil then return opt else return defaults[key] end
end
function on_mcm_load()
op = { id= "melee_degrade_onhit",sh=true ,gr={
{ id = "title", type= "slide", link= "degrade_mcm_banner", text= "", --[[size= {512,50},]]spacing = 20 },
{id = "axe_loss_mult", type = "track", val = 2, min=0.1,max=5,step=0.1, def = 1},
{id = "knife_loss_mult", type = "track", val = 2, min=0.1,max=5,step=0.1, def = 1},
{ id = "line" , type = "line" },
{id = "geometry_loss_mult", type = "track", val = 2, min=0.1,max=5,step=0.1, def = 1},
{id = "phys_loss_mult", type = "track", val = 2, min=0.1,max=5,step=0.1, def = 1},
{id = "enemy_loss_mult", type = "track", val = 2, min=0.1,max=5,step=0.1, def = 2},
{ id = "line" , type = "line" },
{id = "light_loss_mult", type = "track", val = 2, min=0.1,max=5,step=0.1, def = 1},
{id = "heavy_loss_mult", type = "track", val = 2, min=0.1,max=5,step=0.1, def = 2},
}
}
return op
end
@@ -0,0 +1,107 @@
--[[
Custom trade injector made for CW weapon pack
Author: HarukaSai
Credits: Arti, for creating trader_autoinject.script and being amazing
Last edit: 19-10-2021
]]
-- this is where you add custom trade profiles for specific dudes
-- by default only suppliers are able to sell faction stuff
-- you can bypass this by adding trader in this table
-- [name that you can see when you look at npc in debug] = ini_file("path to your ini")
local ini_by_name = {}
local ini_by_faction = {
["stalker"] = ini_file("items\\trade_melee_rework\\trade_stalker.ltx"),
["bandit"] = ini_file("items\\trade_melee_rework\\trade_bandit.ltx"),
["csky"] = ini_file("items\\trade_melee_rework\\trade_csky_spore.ltx"),
["dolg"] = ini_file("items\\trade_melee_rework\\trade_duty.ltx"),
["freedom"] = ini_file("items\\trade_melee_rework\\trade_freedom.ltx"),
["killer"] = ini_file("items\\trade_melee_rework\\trade_mercenary.ltx"),
["army"] = ini_file("items\\trade_melee_rework\\trade_military_esc.ltx"),
--["ecolog"] = ini_file("items\\trade_melee_rework\\trade_ecolog.ltx"),
["monolith"] = ini_file("items\\trade_melee_rework\\trade_monolith.ltx"),
["renegade"] = ini_file("items\\trade_melee_rework\\trade_renegade.ltx"),
["greh"] = ini_file("items\\trade_melee_rework\\trade_greh.ltx"),
["isg"] = ini_file("items\\trade_melee_rework\\trade_isg.ltx")
}
local format_table = utils_data.print_table
local to_array = utils_data.parse_ini_section_to_array
local math_random = math.random
function vks_spawn_stock(npc)
if trader_autoinject.get_trader_type(npc) ~= trader_autoinject.SUPPLIER then
return
end
local npc_name = npc:section()
local community = get_trader_community(npc)
local supply_level = trader_autoinject.supply_level(npc)
if not supply_level then return end
local ini_trade = ini_by_name[npc_name] or ini_by_faction[community]
local supply_table = to_array(ini_trade, supply_level)
if not supply_table then
printf("! Trader has no supplies for this supply level [%s] - [%s]", npc_name, supply_level)
return
end
local to_spawn = {}
for item, amount in pairs(supply_table) do
local str_amount = str_explode(amount, ",")
to_spawn[item] = chance_for_each(tonumber(str_amount[1]), tonumber(str_amount[2]))
end
trader_autoinject.spawn_items(npc, to_spawn)
end
TraderAuto = trader_autoinject.update
function trader_autoinject.update(npc)
TraderAuto(npc)
vks_spawn_stock(npc)
end
function chance_for_each(n, chance)
local total = 0
for i = 1, n do
if math_random() < chance then
total = total + 1
end
end
return total
end
local furniture = {
["esc_m_trader"] = true,
["red_m_lesnik"] = true
}
local blacklisted_comms = {
["trader"] = true,
["monster"] = true
}
function get_trader_community(npc, default)
if furniture[npc:name()] then
return "stalker"
end
local community = character_community(npc)
if not blacklisted_comms[community] then
return community
end
local squad_community = get_object_squad(npc):get_squad_community()
if not blacklisted_comms[squad_community] then
return squad_community
else
return default
end
end
@@ -0,0 +1,18 @@
local from_to = {
["shovel_old"] = "mmf_shovel_old",
["shovel_mili"] = "mmf_shovel_mili"
}
function item_rack(obj)
local sec = obj:section()
local p = obj:parent() or db.actor
if from_to[sec] then
alife_release(obj)
alife_create_item(from_to[sec], p)
end
end
function on_game_start()
RegisterScriptCallback("actor_item_to_ruck",item_rack)
end
@@ -0,0 +1,55 @@
class "geometry_ray"
--[[
(At least one range parameter should be specified)
ray_range:
Defines the total range of the ray. If you want to attach the ray to
a fast moving object it is good to extend the ray so that you can reduce
the polling rate by using the get function.
contact_range:
Defines the distance at which the result will report being in contact.
You can skip it or set it to a value lower than the ray_range to
still be able to get the intersection position from the result while
marking the ray as not being in contact yet
distance_offset:
Defines how much the intersection position is offset.
You can use both positive and negative values or you can leave it blank.
flags (bit map = values can be added together for combined effect):
0 : None
1 : Objects
2 : Statics
4 : Shapes
8 : Obstacles
]]--
function geometry_ray:__init(ray_range, contact_range, distance_offset, flags)
if ray_range == nil and contact_range == nil then
return nil
end
self.ray_range = ray_range or contact_range
self.contact_range = contact_range or ray_range
self.distance_offset = distance_offset ~= nil and distance_offset or 0
self.ray = ray_pick()
self.ray:set_flags(flags or 2)
self.ray:set_range(self.ray_range)
end
--[[
position:
position from which the ray will start
direction:
direction in which the ray will be fired
]]--
function geometry_ray:get(position, direction)
if position == nil or direction == nil then
return nil
end
self.ray:set_position(position)
self.ray:set_direction(direction)
local distance = self.ray:query() and self.ray:get_distance() or self.ray_range
local result = {}
result.in_contact = distance <= self.contact_range
result.position = position:add(direction:mul(distance + self.distance_offset))
return result
end
@@ -0,0 +1,130 @@
local common = animation_common
-- Flags
common.add_flag("SHOTGUN_PUMP")
-------------------------------------------------
-- Animation Mutators
-------------------------------------------------
-- Animation: Append animation name with '_empty' if weapon is empty and has valid anim for it
local function anm_empty(anm_table, item)
local section = item:section()
if IsWeapon(item) and item.get_ammo_in_magazine then
local ammo = item:get_ammo_in_magazine()
-- check if weapon is empty
if ammo == 0 then
-- check if anim is defined in config
common.mutate_anim(anm_table, "_empty", section)
common.set_flag("SHOTGUN_PUMP")
end
end
end
common.add_anim_mutator(anm_empty, 1)
-- Animation: Append with '_g' if weapon has a grenade launcher and can fire a grenade
-- Append with '_w_gl' if weapon has a grenade launcher, but is not in GL mode (can fire bullets)
-- Append with '_alt' if weapon does not have a GL, but is in alt aim mode
local function anm_alt_modes(anm_table, item)
local section = item:section()
local alt = item:weapon_in_grenade_mode()
local has_gl = utils_item.has_attached_gl(item)
if alt and has_gl then
common.mutate_anim(anm_table, "_g", section)
elseif has_gl then
common.mutate_anim(anm_table, "_w_gl", section)
elseif alt then
common.mutate_anim(anm_table, "_alt", section)
end
end
common.add_anim_mutator(anm_alt_modes, 1.1)
-- Animation: Append with '_aim' is player is aiming down sights
local function actor_on_weapon_zoom_in(obj)
common.set_flag("AIM_MODE")
end
local function actor_on_weapon_zoom_out(obj)
common.remove_flag("AIM_MODE")
end
local function anm_ads(anm_table, item)
local section = item:section()
if common.get_flag("AIM_MODE") then
common.mutate_anim(anm_table, "_aim", section)
end
end
common.add_anim_mutator(anm_ads, 1.3)
-- Animation: Append with '_jammed' if weapon misfires (vanilla) or fails to eject (WPO)
-- Append with '_superjammed' if magazine needs to be removed before unjam (WPO)
local function anm_jammed(anm_table, item)
local section = item:section()
local jam_type = nil
-- Check for WPO jams
if arti_jamming then
local jam_status = arti_jamming.get_jam_status(item:id())
if jam_status == arti_jamming.JamType.FailureToEject then
jam_type = "_jammed"
elseif jam_status == arti_jamming.JamType.DoubleFeed then
jam_type = "_superjammed"
end
end
-- Check for vanilla jams (vanilla jams appear in anm_shots before WPO catches them)
if not jam_type then
local wpn = item:cast_Weapon()
if not wpn then return end
jam_type = item:cast_Weapon():IsMisfire() and "_jammed" or nil
end
if jam_type then
local success = common.mutate_anim(anm_table, jam_type, section)
-- Fallback to '_jammed' if '_superjammed' does not exist
if not success and jam_type == "_superjammed" then
common.mutate_anim(anm_table, jam_type, section)
end
end
end
common.add_anim_mutator(anm_jammed, 2)
-- Animation: Prepend with _pump if performing empty reload
local function anm_pump(anm_table, item)
local section = item:section()
if common.get_flag("SHOTGUN_PUMP") then
if anm_table.anm_name == "anm_close" then
common.mutate_anim(anm_table, "_pump", section)
-- Clear flag
common.remove_flag("SHOTGUN_PUMP")
end
end
end
common.add_anim_mutator(anm_pump, 3)
-- Animation: Randomly select between variants of the same animation
local function anm_variants(anm_table, item)
local section = item:section()
local variants = {anm_table.anm_name}
local i = 2
while (true) do
local anm_variant = anm_table.anm_name .. "_variant" .. (i-1)
if common.has_animation(section, anm_variant) then
variants[i] = "_variant" .. (i-1)
else
break
end
i = i + 1
end
if #variants > 1 then
local rand_i = random_number(1, #variants)
common.mutate_anim(anm_table, variants[rand_i], section)
end
end
common.add_anim_mutator(anm_variants, 4)
-------------------------------------------------
-- Callbacks
-------------------------------------------------
function on_game_start()
RegisterScriptCallback("actor_on_weapon_zoom_in", actor_on_weapon_zoom_in)
RegisterScriptCallback("actor_on_weapon_zoom_out", actor_on_weapon_zoom_out)
end
@@ -0,0 +1,43 @@
function on_game_start()
if melee_degrade_onhit_mcm then
melee_degrade_onhit_mcm.valid_axe["wpn_axe"] = true
melee_degrade_onhit_mcm.heavy_atk_degrade_mult["wpn_axe"] = 1.2
melee_degrade_onhit_mcm.light_atk_degrade_mult["wpn_axe"] = 1.0 -- Axe
melee_degrade_onhit_mcm.enemy_degrade["wpn_axe"] = 0.01
melee_degrade_onhit_mcm.phys_degrade["wpn_axe"] = 0.005
melee_degrade_onhit_mcm.geometry_degrade["wpn_axe"] = 0.005
melee_degrade_onhit_mcm.valid_axe["wpn_axe3"] = true
melee_degrade_onhit_mcm.heavy_atk_degrade_mult["wpn_axe3"] = 1.2
melee_degrade_onhit_mcm.light_atk_degrade_mult["wpn_axe3"] = 1.0 -- Sledge
melee_degrade_onhit_mcm.enemy_degrade["wpn_axe3"] = 0.0007
melee_degrade_onhit_mcm.phys_degrade["wpn_axe3"] = 0.0001
melee_degrade_onhit_mcm.geometry_degrade["wpn_axe3"] = 0.0001
melee_degrade_onhit_mcm.valid_axe["mmf_shovel_mili"] = true
melee_degrade_onhit_mcm.heavy_atk_degrade_mult["mmf_shovel_mili"] = 1.2
melee_degrade_onhit_mcm.light_atk_degrade_mult["mmf_shovel_mili"] = 1.0
melee_degrade_onhit_mcm.enemy_degrade["mmf_shovel_mili"] = 0.04 -- Mili Shovel
melee_degrade_onhit_mcm.phys_degrade["mmf_shovel_mili"] = 0.02
melee_degrade_onhit_mcm.geometry_degrade["mmf_shovel_mili"] = 0.02
melee_degrade_onhit_mcm.valid_axe["mmf_shovel_old"] = true
melee_degrade_onhit_mcm.heavy_atk_degrade_mult["mmf_shovel_old"] = 1.2
melee_degrade_onhit_mcm.light_atk_degrade_mult["mmf_shovel_old"] = 1.0
melee_degrade_onhit_mcm.enemy_degrade["mmf_shovel_old"] = 0.04 -- Old Shovel
melee_degrade_onhit_mcm.phys_degrade["mmf_shovel_old"] = 0.02
melee_degrade_onhit_mcm.geometry_degrade["mmf_shovel_old"] = 0.02
melee_degrade_onhit_mcm.valid_axe["wpn_axe2"] = true
melee_degrade_onhit_mcm.heavy_atk_degrade_mult["wpn_axe2"] = 1.2
melee_degrade_onhit_mcm.light_atk_degrade_mult["wpn_axe2"] = 1.0
melee_degrade_onhit_mcm.enemy_degrade["wpn_axe2"] = 0.04 -- Sharp Shovel
melee_degrade_onhit_mcm.phys_degrade["wpn_axe2"] = 0.02
melee_degrade_onhit_mcm.geometry_degrade["wpn_axe2"] = 0.02
--[[
for section, value in pairs(geometry_degrade) do
geometry_degrade[section] = geometry_degrade[section] * 2
end
]]--
end
end
+35
View File
@@ -0,0 +1,35 @@
[General]
gameName=stalkeranomaly
modid=0
version=d2024.12.7.0
newestVersion=
category="-1,"
nexusFileStatus=1
installationFile=More-Melee-Features_v0.8.zip
repository=Nexus
ignoredVersion=
comments=
notes=
nexusDescription=
url=
hasCustomURL=false
lastNexusQuery=
lastNexusUpdate=
nexusLastModified=2024-12-07T20:46:36Z
nexusCategory=0
converted=false
validated=false
color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0)
tracked=0
[installedFiles]
1\modid=0
size=1
1\fileid=0
[Plugins]
BAIN%20Installer\option0=001 Shovels (MAIN)
BAIN%20Installer\option1=002 Melee Durability
BAIN%20Installer\option2=003 Melee Blocking
BAIN%20Installer\option3=004 Hitstop
BAIN%20Installer\option4=005 FDDA Patch