local damagescale = zzz_player_injuries_mcm.get_config("damage_scale")
local regen = zzz_player_injuries_mcm.get_config("regen") 	-- Automatic blue health regeneration (in game minutes, each tick will heal 1 random limb for 1 hp)
local enable_display = zzz_player_injuries_mcm.get_config("enable_display")
local display_numeric_at = zzz_player_injuries_mcm.get_config("numeric_at")				-- if medicine heal for this value or more then show it as number
local show_numeric_always = zzz_player_injuries_mcm.get_config("numeric_always")		-- always show medicine values as numbers

local hud_type = zzz_player_injuries_mcm.get_config("hud_type")
local alt_mode_health = zzz_player_injuries_mcm.get_config("alt_mode_health")
local mcm_pos_x = zzz_player_injuries_mcm.get_config("position_x")
local mcm_pos_y = zzz_player_injuries_mcm.get_config("position_y")
local vanilla_bars = zzz_player_injuries_mcm.get_config("vanilla_bars")

local custom_colors = zzz_player_injuries_mcm.get_config("custom_colors")
local clr_main_r = zzz_player_injuries_mcm.get_config("clr_main_r")
local clr_main_g = zzz_player_injuries_mcm.get_config("clr_main_g")
local clr_main_b = zzz_player_injuries_mcm.get_config("clr_main_b")

local clr_timed_r = zzz_player_injuries_mcm.get_config("clr_timed_r")
local clr_timed_g = zzz_player_injuries_mcm.get_config("clr_timed_g")
local clr_timed_b = zzz_player_injuries_mcm.get_config("clr_timed_b")

local def_clr_t = {
	["default"] = { main = { 90, 140, 215 }, timed = { 230, 200, 15 } },
	["eft"] = { main = { 255, 255, 255 }, timed = { 50, 255, 50 } },
}

local ctime_to_t = utils_data.CTime_to_table
local t_to_ctime = utils_data.CTime_from_table

local prev_health
local damaged_limb
local preview_sec
local timedhp_timer
local heal_timer


maxhp = {
	head = 11,
	torso = 11,
	leftarm = 5,
	rightarm = 5,
	leftleg = 5,
	rightleg = 5
}

health = {
	head = maxhp.head,
	torso = maxhp.torso,
	leftarm = maxhp.leftarm,
	rightarm = maxhp.rightarm,
	leftleg = maxhp.leftleg,
	rightleg = maxhp.rightleg
}

timedhp = {
	head = 0,
	torso = 0,
	leftarm = 0,
	rightarm = 0,
	leftleg = 0,
	rightleg = 0,
}

medkits = {
	morphine = {head = 8, torso = 5, rightleg = 4, leftleg = 4, rightarm = 4, leftarm = 4},
	rebirth = {head = 11, torso = 11, rightleg = 5, leftleg = 5, rightarm = 5, leftarm = 5},
	adrenalin = {head = 10, torso = 10, rightleg = 5, leftleg = 5, rightarm = 5, leftarm = 5},
	cocaine = {head = 8, torso = 4, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	analgetic = {head = 3, torso = 3, rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	salicidic_acid = {head = 5, torso = 5, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	stimpack = {head = 5, torso = 5, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	stimpack_army = {head = 5, torso = 7, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	stimpack_scientic = {head = 6, torso = 9, rightleg = 4, leftleg = 4, rightarm = 4, leftarm = 4},
	medkit = {head = 5, torso = 5, rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	medkit_army = {head = 7, torso = 8, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	medkit_scientic = {head = 10, torso = 8, rightleg = 4, leftleg = 4, rightarm = 4, leftarm = 4},
	jgut = {rightleg = 5, leftleg = 5, rightarm = 5, leftarm = 5},
	survival_kit = {torso = 11, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	bandage = {torso = 2, torso = 2, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
}

healhelp = {
	--bandage = {rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	caffeine = {head = 3},
	drug_psy_blockade = {head = 5, rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	drug_sleepingpills = {head = 8},
	drug_booster = {torso = 6},
	drug_anabiotic = {head = 11, torso = 11, rightleg = 11, leftleg = 11, rightarm = 11, leftarm = 11},
	rebirth = {head = 8, torso = 8, rightleg = 4, leftleg = 4, rightarm = 4, leftarm = 4},
	glucose_s = {head = 2, torso = 2, rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	glucose = {head = 4, torso = 4, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	medkit_army = {rightleg = 1, leftleg = 1, rightarm = 1, leftarm = 1},
	medkit_scientic = {rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	salicidic_acid = {rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	analgetic = {torso = 2, rightleg = 1, leftleg = 1, rightarm = 1, leftarm = 1},
	stimpack_army = {head = 2, torso = 2, rightleg = 1, leftleg = 1, rightarm = 1, leftarm = 1},
	stimpack_scientic = {head = 3, torso = 6, rightleg = 1, leftleg = 1, rightarm = 1, leftarm = 1},
	tetanus = {head = 3, rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	drug_coagulant = {torso = 3},
	yadylin = {head = 4, torso = 4, rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	survival_kit = {torso = 11, rightleg = 3, leftleg = 3, rightarm = 3, leftarm = 3},
	akvatab = {rightleg = 4, leftleg = 4, rightarm = 4, leftarm = 4},
	vinca = {torso = 3},
	antibio_chlor = {head = 1, torso = 2},
	antibio_sulfad = {torso = 2, rightarm = 1, leftarm = 1},
	antiemetic = {head = 2, rightleg = 1, leftleg = 1},
	antirad = {head = 1, torso = 2, rightleg = 2, leftleg = 2, rightarm = 2, leftarm = 2},
	antirad_cystamine = {head = 3, torso = 3},
	antirad_kalium = {head = 1, torso = 1, rightleg = 1, leftleg = 1, rightarm = 1, leftarm = 1},
	drug_antidot = {head = 4, torso = 2},
	drug_radioprotector = {head = 1, rightleg = 1, leftleg = 1, rightarm = 1, leftarm = 1},
}


HUD = nil

function activate_hud()
	if HUD == nil then
		HUD = BHS()
		get_hud():AddDialogToRender(HUD)
	end
end

function deactivate_hud()
	if HUD ~= nil then
		get_hud():RemoveDialogToRender(HUD)
		HUD = nil
	end
end

function actor_on_first_update()
	-- disable vanilla health / stamina / psi bars
	if not vanilla_bars then
		ActorMenu.get_maingame().m_ui_hud_states.m_ui_health_bar:SetWndPos(vector2():set(9999, 9999))
		ActorMenu.get_maingame().m_ui_hud_states.m_ui_stamina_bar:SetWndPos(vector2():set(9999, 9999))
		ActorMenu.get_maingame().m_ui_hud_states.m_ui_psy_bar:SetWndPos(vector2():set(9999, 9999))
		ActorMenu.get_maingame().m_ui_hud_states.m_back:SetWndPos(vector2():set(9999, 9999))
	end

	activate_hud()
end
------------------------------------------------------------------------------
---------------------------------- HUD -------------------------------------
------------------------------------------------------------------------------
class "BHS" (CUIScriptWnd)

function BHS:__init() super()
	self:InitControls()
end

function BHS:InitControls()
	self:SetWndRect(Frect():set(0, 0, 1024, 768))
	self:SetAutoDelete(true)

	if hud_type == "text" then
		self:BuildAltHUD()
	else
		self:BuildGraphicalHUD()
	end

	self:UpdatePos()
	self:UpdateBars()
end

function BHS:BuildGraphicalHUD()
	self.xml = CScriptXmlInit()
	local xml = self.xml
	local xml_name = (hud_type == "eft" and "ui_bhs_eft\\ui_bhs_eft.xml") or "ui_bhs\\ui_bhs.xml"
	xml:ParseFile(xml_name)

	-- backgrounds
	self.bg = xml:InitStatic("body_health_system", self)
	self.hud_bg = xml:InitStatic("body_health_system_hud", self.bg)

	-- bars
	self.health_bar_bg = xml:InitStatic("bhs_health_bar_bg", self.hud_bg)
	self.health_bar = xml:InitProgressBar("bhs_health", self.health_bar_bg)
	self.health_bar:SetProgressPos(0.0)

	self.stamina_bar_bg = xml:InitStatic("bhs_stamina_bar_bg", self.hud_bg)
	self.stamina_bar = xml:InitProgressBar("bhs_stamina", self.stamina_bar_bg)
	self.stamina_bar:SetProgressPos(0.0)

	self.psi_bar = xml:InitProgressBar("bhs_psi", self.hud_bg)
	self.psi_bar:SetProgressPos(0.0)

	for limb, _ in pairs(maxhp) do
		self[limb .. "_bg"] = xml:InitStatic("bhs_health_" .. limb .. "_bar_bg", self.hud_bg)
		self[limb .. "_green"] = xml:InitProgressBar("bhs_health_bodypart_green", self[limb .. "_bg"])
		self[limb .. "_green"]:SetProgressPos(0.0)
		self[limb] = xml:InitProgressBar("bhs_health_bodypart", self[limb .. "_bg"])
		self[limb]:SetProgressPos(0.0)
	end


	-- colors
	local main_r, main_g, main_b, timed_r, timed_g, timed_b = 255, 255, 255, 255, 255, 255
	if def_clr_t[hud_type] then
		local t = def_clr_t[hud_type]
		main_r, main_g, main_b = t.main[1], t.main[2], t.main[3]
		timed_r, timed_g, timed_b = t.timed[1], t.timed[2], t.timed[3]
	end

	if custom_colors then
		main_r, main_g, main_b = clr_main_r, clr_main_g, clr_main_b
		timed_r, timed_g, timed_b = clr_timed_r, clr_timed_g, clr_timed_b
	end

	self.health_bar:SetColor(GetARGB(255, main_r, main_g, main_b))
	self.stamina_bar:SetColor(GetARGB(255, main_r, main_g, main_b))
	self.psi_bar:SetColor(GetARGB(255, main_r, main_g, main_b))
	for limb, _ in pairs(maxhp) do
		self[limb .. "_green"]:SetColor(GetARGB(255, timed_r, timed_g, timed_b))
		self[limb]:SetColor(GetARGB(255, main_r, main_g, main_b))
	end

end

function BHS:BuildAltHUD()
	self.xml = CScriptXmlInit()
	local xml = self.xml
	xml:ParseFile("ui_bhs_alt\\ui_bhs_alt.xml")

	-- background
	self.bg = xml:InitStatic("bhs_alt", self)

	for limb, _ in pairs(maxhp) do
		self[limb .. "_cont"] = xml:InitStatic("bhs_alt:" .. limb .. "_cont", self.bg)
		self[limb .. "_bg"] = xml:InitStatic("bhs_alt:" .. limb .. "_cont:bar_bg", self[limb .."_cont"])
		self[limb .. "_green"] = xml:InitProgressBar("bhs_alt:" .. limb .. "_cont:bar_green", self[limb .. "_bg"])
		self[limb .. "_green"]:SetProgressPos(0.0)
		self[limb] = xml:InitProgressBar("bhs_alt:" .. limb .. "_cont:bar", self[limb .. "_bg"])
		self[limb]:SetProgressPos(0.0)
	end

	-- text
	self.head_text = xml:InitTextWnd("bhs_alt:head_cont:head_text", self.head_cont)
	self.torso_text = xml:InitTextWnd("bhs_alt:torso_cont:torso_text", self.torso_cont)
	self.arms_text = xml:InitTextWnd("bhs_alt:text_arms", self.bg)
	self.legs_text = xml:InitTextWnd("bhs_alt:text_legs", self.bg)

	-- psi/hp/stamina
	if alt_mode_health then
		self.main_cont = xml:InitStatic("bhs_alt:main_cont", self.bg)

		self.psi_bar = xml:InitProgressBar("bhs_alt:main_cont:psi_bar", self.main_cont)
		self.psi_bar:SetProgressPos(0.0)

		self.health_bar_bg = xml:InitStatic("bhs_alt:main_cont:health_bar_bg", self.main_cont)
		self.health_bar = xml:InitProgressBar("bhs_alt:main_cont:health_bar", self.health_bar_bg)
		self.health_bar:SetProgressPos(0.0)

		self.stamina_bar_bg = xml:InitStatic("bhs_alt:main_cont:stamina_bar_bg", self.main_cont)
		self.stamina_bar = xml:InitProgressBar("bhs_alt:main_cont:stamina_bar", self.stamina_bar_bg)
		self.stamina_bar:SetProgressPos(0.0)
	end

end

function BHS:UpdatePos()
	local add_x = hud_type ~= "text" and -7 or 0		-- to compensate how bhs grabs texture
	local add_y = hud_type ~= "text" and -15 or 0
	self.bg:SetWndPos(vector2():set(mcm_pos_x + add_x, mcm_pos_y + add_y))
end

function BHS:UpdateBars()
	if self.health_bar then
		self.health_bar:SetProgressPos(db.actor.health)
		self.stamina_bar:SetProgressPos(db.actor.power)
		self.psi_bar:SetProgressPos(arszi_psy and arszi_psy.get_psy_health() or 0)
	end

	for limb, val in pairs(health) do

		local timed_preview_val = 0
		local preview_val = 0
		if preview_sec then
			-- no need to clamp, xml settings handle it
			timed_preview_val = medkits[preview_sec] and medkits[preview_sec][limb] or 0
			preview_val = healhelp[preview_sec] and healhelp[preview_sec][limb] or 0
		end

		self[limb .. "_green"]:SetProgressPos( (val + timedhp[limb] + timed_preview_val) / maxhp[limb])
		self[limb]:SetProgressPos( (val + preview_val) / maxhp[limb])

	end
end

function BHS:Update()
	CUIScriptWnd.Update(self)

	self:UpdateBars()

	local hide_cond = actor_menu.last_mode == 1 or main_hud_shown()
	self.bg:Show(hide_cond)
end

function BHS:__finalize()
end


------------------------------------------------------------------------------
----------------------------- Events / Updates -------------------------------
------------------------------------------------------------------------------
local hitboxes = {
	[14] = "head", [15] = "head", [16] = "head", [17] = "head", [18] = "head", [19] = "head",

	[2] = "torso", [11] = "torso", [12] = "torso", [13] = "torso", [20] = "torso", [33] = "torso",

	[21] = "leftarm", [22] = "leftarm", [23] = "leftarm", [24] = "leftarm", [25] = "leftarm", [26] = "leftarm",
	[27] = "leftarm", [28] = "leftarm", [29] = "leftarm", [30] = "leftarm", [31] = "leftarm", [32] = "leftarm",

	[34] = "rightarm", [35] = "rightarm", [36] = "rightarm", [37] = "rightarm", [38] = "rightarm", [39] = "rightarm",
	[40] = "rightarm", [41] = "rightarm", [42] = "rightarm", [43] = "rightarm", [44] = "rightarm", [45] = "rightarm",

	[3] = "leftleg", [4] = "leftleg", [5] = "leftleg", [6] = "leftleg",

	[7] = "rightleg", [8] = "rightleg", [9] = "rightleg", [10] = "rightleg",
}

local anomalies_hit = {
	[hit.burn] = { "torso", "leftarm", "rightarm", "leftleg", "rightleg" },
	[hit.strike] = { "torso", "leftarm", "rightarm", "leftleg", "rightleg" },
	[hit.wound] = { "torso", "leftarm", "rightarm", "leftleg", "rightleg" },
	[hit.shock] = { "torso", "leftarm", "rightarm", "leftleg", "rightleg" },
	[hit.chemical_burn] = { "leftleg", "rightleg" },
}

local limb_msg = {
	head = "Head fatally", torso = "Torso fatally", leftarm = "Left arm",
	rightarm = "Right arm", leftleg = "Left leg", rightleg = "Right leg",
}

function actor_on_before_hit(s_hit, bone_id)
	local draft = s_hit.draftsman

	-- if none
	if bone_id == 65535 then
		return
	end

	-- if anomaly
	if draft and IsAnomaly(draft) and bone_id == 0 and anomalies_hit[s_hit.type] then
		local ar = anomalies_hit[s_hit.type]
		damaged_limb = ar[math.random(1, #ar)]
		return
	end

	-- if mutant
	if draft and IsMonster(draft) and bone_id == 0 then
		local near_bone_id = get_nearest_actor_bone_id(draft)
		if near_bone_id and hitboxes[near_bone_id] then
			damaged_limb = hitboxes[near_bone_id]
		end
		return
	end

	-- if fall
	if s_hit.type == hit.strike and draft and draft:id() == 0 then
		damaged_limb = math.random(2) == 1 and "leftleg" or "rightleg"
		return
	end

	-- if bullet
	if hitboxes[bone_id] then
		damaged_limb = hitboxes[bone_id]
	end
end

function hit_on_update()
	-- skip first update
	if not prev_health then
		prev_health = db.actor.health
		return
	end

	local old_hp = prev_health
	prev_health = db.actor.health

	-- register only_on_hit
	if not damaged_limb then
		return
	end

	local limb = damaged_limb
	damaged_limb = nil

	-- same check as old BHS for compatibility with ballistics etc
	local amount = old_hp - db.actor.health
	if amount <= 0.0293 then
		return
	end

	local head_mult = limb == "head" and 2 or 1
	local damage = math.ceil((amount * head_mult * 100) / 11 * damagescale)

	health[limb] = health[limb] - damage
	if health[limb] <= 0 then

		-- reduce remnant from timedhp
		timedhp[limb] = timedhp[limb] + health[limb]

		-- clamp timedhp and send msg if health at 0 and timedhp at 0
		if timedhp[limb] <= 0 then
			timedhp[limb] = 0
			actor_menu.set_msg(1, limb_msg[limb] .. " damaged!", 8)
		end

		-- clamp health
		health[limb] = 0
	end

	-- for concussion
	if limb == "head" and (health["head"] + timedhp["head"]) > 0 then
		zzz_player_injuries_effects.head_concussion_start(damage)
	end

end

function actor_on_item_use(obj, sec)
	if medkits[sec] then
		for limb, val in pairs(medkits[sec]) do
			timedhp[limb] = timedhp[limb] + val
			local diff = health[limb] + timedhp[limb] - maxhp[limb]
			-- clamp timedhp
			if diff > 0 then
				timedhp[limb] = timedhp[limb] - diff
			end
		end
		timedhp_timer = nil
	end


	if healhelp[sec] then
		for limb, val in pairs(healhelp[sec]) do
			-- restore only timedhp
			if val > timedhp[limb] then
				health[limb] = health[limb] + timedhp[limb]
				timedhp[limb] = 0
			-- restore val
			else
				health[limb] = health[limb] + val
				timedhp[limb] = timedhp[limb] - val
			end

		end
		timedhp_timer = nil
	end

end

local med_tmr = 0
function medicine_on_update()
	local tg = time_global()
	if med_tmr > tg then return end
	med_tmr = tg + 5000

	local cur_time = game.get_game_time()
	if not timedhp_timer then
		timedhp_timer = ctime_to_t(cur_time)
	end

	local diff = cur_time:diffSec(t_to_ctime(timedhp_timer)) / 600		-- each per 10 game minutes

	if diff >= 1 then
		timedhp_timer = ctime_to_t(cur_time)

		for limb, val in pairs(timedhp) do
			timedhp[limb] = timedhp[limb] - (math.floor(diff))
			if timedhp[limb] < 0 then
				timedhp[limb] = 0
			end
		end
	end

end

local heal_tmr = 0
function heal_on_update()
	if regen <= 0 then return end

	local tg = time_global()
	if heal_tmr > tg then return end
	heal_tmr = tg + 3000

	local cur_time = game.get_game_time()
	if not heal_timer then
		heal_timer = ctime_to_t(cur_time)
	end

	local diff = cur_time:diffSec(t_to_ctime(heal_timer)) / (regen * 60)		-- each per "regen" game minutes

	if diff >= 1 then
		heal_timer = ctime_to_t(cur_time)

		for i = 1, math.floor(diff) do
			heal_random_limb()
		end
	end

end

function kill_on_update()
	if (health.torso + timedhp.torso) <= 0 or (health.head + timedhp.head) <= 0 then
		db.actor.health = -1
	end
end

function heal_random_limb()
	local t = dup_table(health)
	local t_size = size_table(t)

	-- keep picking randomly until we find limb that needs healing
	for i = 1, t_size do
		local rnd_limb = random_key_table(t)
		if t[rnd_limb] < maxhp[rnd_limb] then
			health[rnd_limb] = health[rnd_limb] + 1
			if timedhp[rnd_limb] > 0 then
				timedhp[rnd_limb] = timedhp[rnd_limb] - 1
			end
			break
		end
		t[rnd_limb] = nil
	end
end

-- preview
function ActorMenu_on_item_focus_receive(obj)
	if not preview_sec then
		preview_sec = obj:section()
	end
end

function ActorMenu_on_item_focus_lost(obj)
	if preview_sec == obj:section() then
		preview_sec = nil
	end
end

function ActorMenu_on_mode_changed(mode, last_mode)
	if last_mode == 1 or last_mode == 4 then
		preview_sec = nil
	end
end


------------------------------------------------------------------------------
------------------------------- Utils / Misc ----------------------------------
------------------------------------------------------------------------------
function get_nearest_actor_bone_id(npc)
	local head_bone_name = ini_sys:r_string_ex(npc:section(), "bone_head")
	local head_bone_pos = head_bone_name and vector():set(npc:bone_position(head_bone_name))
	if not head_bone_pos then return end

	local min_dist = 99
	local picked_bone_id
	for bone_id, _ in pairs(hitboxes) do
		local bone_name = db.actor:bone_name(bone_id)
		local bone_pos = bone_name and vector():set(db.actor:bone_position(bone_name))
		local dist = bone_pos and head_bone_pos:distance_to(bone_pos)
		if dist and dist < min_dist then
			min_dist = dist
			picked_bone_id = bone_id
		end
	end

	return picked_bone_id
end

-- item descr
local gt = game.translate_string
BuildHeaderBHS = ui_item.build_desc_header
function ui_item.build_desc_header(obj, sec, str)
	str = str or gt(ini_sys:r_string_ex(sec, "description"))
	if (not str) then return "" end

	if not enable_display then
		return BuildHeaderBHS(obj, sec, str)
	end

	local _str = ""
	local blue_main = utils_xml.get_color("d_blue")
	local blue_clr = strformat("%c[%s,%s,%s,%s]", 255, 74, 134, 232)
	local yel_clr = strformat("%c[%s,%s,%s,%s]", 0, 252, 186, 3)
	local grey_clr = utils_xml.get_color("ui_gray_2")
	local obj_sec = obj and obj:section()

	-- get circles/number for string
	local function val_to_fkn_circles(val)
		local circles = ""
		if val >= display_numeric_at or show_numeric_always then
			return val
		elseif val > 0 then
			for i = 1, val do
				circles = circles .. gt("st_bhs_mihail_krug")
			end
		end
		return circles
	end

	-- get string
	local function build_string(t_name, sec, color)
		local head_str = ""
		local torso_str = ""
		local arm_str = ""
		local leg_str = ""
		local timeregen_str = ""
		if sec and t_name[sec] then
			for limb, val in pairs(t_name[sec]) do
				if limb == "head" then
					head_str = grey_clr .. gt("st_bhs_head_str") .. color .. val_to_fkn_circles(val) .. " "
				elseif limb == "torso" then
					torso_str = grey_clr .. gt("st_bhs_torso_str") .. color .. val_to_fkn_circles(val) .. " "
				elseif limb == "rightarm" then
					arm_str = grey_clr .. gt("st_bhs_rightarm_str") .. color .. val_to_fkn_circles(val) .. " "
				elseif limb == "rightleg" then
					leg_str = grey_clr .. gt("st_bhs_rightleg_str") .. color .. val_to_fkn_circles(val) .. " "
			--	elseif limb == "timeregen" and show_timed_heal_time then
			--		timeregen_str = grey_clr .. gt("st_bhs_timeregen") .. color .. (val / 1000) .. " "
				end
			end
		end
		local main_string = head_str .. torso_str .. arm_str .. leg_str .. (timeregen_str ~= "" and (" " .. timeregen_str) or "")
		return main_string
	end

	local medkits_pre = "  " .. yel_clr .. gt("st_bhs_mihail_krug") .. " " .. yel_clr .. " " .. gt("st_bhs_timed_heal") .. "  "
	local medkits_str = build_string(medkits, obj_sec, yel_clr)
	local healhelp_pre = "  " .. blue_main .. gt("st_bhs_mihail_krug") .. " " .. blue_clr .. " " .. gt("st_bhs_full_heal") .. "  "
	local healhelp_str = build_string(healhelp, obj_sec, blue_clr)

	if obj_sec then
		if medkits_str ~= "" and healhelp_str ~= "" then
			_str = medkits_pre .. medkits_str .. "\\n" .. healhelp_pre .. healhelp_str .. "\\n" .. utils_xml.get_color("ui_gray_1")
			return BuildHeaderBHS(obj, sec, str) .. _str
		elseif medkits_str ~= "" then
			_str = medkits_pre .. medkits_str .. "\\n" .. utils_xml.get_color("ui_gray_1")
			return BuildHeaderBHS(obj, sec, str) .. _str
		elseif healhelp_str ~= "" then
			_str = healhelp_pre .. healhelp_str .. "\\n" .. utils_xml.get_color("ui_gray_1")
			return BuildHeaderBHS(obj, sec, str) .. _str
		else
			return BuildHeaderBHS(obj, sec, str)
		end
	else
		return BuildHeaderBHS(obj, sec, str)
	end

end

-- dialogues
function limb_is_damaged()
	for k, v in pairs(health) do
		if health[k] < maxhp[k] then
			return true
		end
	end
end

function heal_all_limbs()
	for k, v in pairs(health) do
		health[k] = maxhp[k]
		timedhp[k] = 0
	end
end

base_not_healthy = dialogs.is_actor_not_healthy
function dialogs.is_actor_not_healthy(a, b)
	if base_not_healthy(a, b) or limb_is_damaged() then
		return true
	end
end

base_actor_injured = dialogs.is_actor_injured
function dialogs.is_actor_injured(a, b)
	if base_actor_injured(a, b) or (db.actor:money() >= 1850 and limb_is_damaged()) then
		return true
	end
end

base_actor_injured_irradiated = dialogs.is_actor_injured_irradiated
function dialogs.is_actor_injured_irradiated(a, b)
	if base_actor_injured_irradiated(a, b) or (db.actor:money() >= 3350 and limb_is_damaged()) then
		return true
	end
end

base_heal_injury = dialogs.heal_actor_injury
function dialogs.heal_actor_injury(a, b)
	base_heal_injury(a, b)
	heal_all_limbs()
end

base_heal_injury_radiation = dialogs.heal_actor_injury_radiation
function dialogs.heal_actor_injury_radiation(a, b)
	base_heal_injury_radiation(a, b)
	heal_all_limbs()
end

-- items use override
function itms_manager.actor_on_item_before_use(obj, flags)
	local sec = obj:section()

	local ini_eff = ini_file("items\\items\\animations_settings.ltx")

	-- headgear anims
	if z_headgear_animations_fdda_strict_helmets and headgear_animations_mcm and headgear_animations_mcm.get_config("strict_helmets") then
        if ini_eff:r_bool_ex(sec, "helm") == false then
            if z_headgear_animations_fdda_strict_helmets.is_have_helmet() then
                actor_menu.set_msg(1, game.translate_string("liz_ha_text_cant_consume_item"), 3)
                flags.ret_value = false
                return
            end
        end
	end
	---------

	if IsItem("tool",sec) then
		flags.ret_value = true
		return
	end

	local pass = true

	local require_tool = ini_sys:r_string_ex(sec, "required_tool")
	local obj_tool = require_tool and ini_sys:section_exist(require_tool) and db.actor:object(require_tool)
	if require_tool and (not obj_tool) then
		str = strformat(game.translate_string("st_itm_manager_missing_requirements"), ui_item.get_sec_name(require_tool))
		pass = false
	end

	if pass then
		flags.ret_value = true
		if obj_tool then
			utils_item.discharge(obj_tool)
		end
	else
		flags.ret_value = false
		utils_xml.hide_menu()
		actor_menu.set_msg(1, str, 3)
	end

	-- fdda
	if enhanced_animations then
		if IsMoveState("mcClimb") then
			actor_menu.set_msg(1, game.translate_string("st_EA_ladder_item_not_allowed"), 3)
			flags.ret_value = false
			return
		end

		local enable_animations = ui_mcm and ui_mcm.get("EA_settings/enable_animations") or ui_options.get("video/player/animations")
		if ini_eff:r_string_ex(sec, "snd") and enable_animations and flags.ret_value then
			enhanced_animations.use_item(obj)
			flags.ret_value = false
			return
		end
	end
	---------

end
--------------------------------------


function bhs_dbg_hit(limb, dmg)
	-- zzz_player_injuries.bhs_dbg_hit("head", 0.3)
	dmg = dmg >= db.actor.health and db.actor.health - 0.01 or dmg
	damaged_limb = limb
	db.actor:set_health_ex(db.actor.health - dmg)
end

function bhs_dbg_heal()
	-- zzz_player_injuries.bhs_dbg_heal()
	for k, _ in pairs(health) do
		health[k] = maxhp[k]
		timedhp[k] = 0
	end
end

function bhs_dbg_set_health(limb, val)
	-- zzz_player_injuries.bhs_dbg_set_health("head", 3)
	val = (val > maxhp[limb] and maxhp[limb]) or (val <= 0 and 0) or val
	health[limb] = val
end


------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
function actor_on_update()
	hit_on_update()
	medicine_on_update()
	heal_on_update()
	kill_on_update()
end

function save_state(m_data)
	m_data.bhs_health = health
	m_data.bhs_timedhp = timedhp
	m_data.bhs_timedhp_timer = timedhp_timer
	m_data.bhs_heal_timer = heal_timer
end

function load_state(m_data)
	health = m_data.bhs_health or health
	timedhp = m_data.bhs_timedhp or timedhp
	timedhp_timer = m_data.bhs_timedhp_timer
	heal_timer = m_data.bhs_heal_timer
end

function on_option_change()
	damagescale = zzz_player_injuries_mcm.get_config("damage_scale")
	regen = zzz_player_injuries_mcm.get_config("regen")

	enable_display = zzz_player_injuries_mcm.get_config("enable_display")
	display_numeric_at = zzz_player_injuries_mcm.get_config("numeric_at")
	show_numeric_always = zzz_player_injuries_mcm.get_config("numeric_always")

	hud_type = zzz_player_injuries_mcm.get_config("hud_type")
	alt_mode_health = zzz_player_injuries_mcm.get_config("alt_mode_health")
	mcm_pos_x = zzz_player_injuries_mcm.get_config("position_x")
	mcm_pos_y = zzz_player_injuries_mcm.get_config("position_y")
	vanilla_bars = zzz_player_injuries_mcm.get_config("vanilla_bars")

	custom_colors = zzz_player_injuries_mcm.get_config("custom_colors")
	clr_main_r = zzz_player_injuries_mcm.get_config("clr_main_r")
	clr_main_g = zzz_player_injuries_mcm.get_config("clr_main_g")
	clr_main_b = zzz_player_injuries_mcm.get_config("clr_main_b")

	clr_timed_r = zzz_player_injuries_mcm.get_config("clr_timed_r")
	clr_timed_g = zzz_player_injuries_mcm.get_config("clr_timed_g")
	clr_timed_b = zzz_player_injuries_mcm.get_config("clr_timed_b")

	deactivate_hud()
	activate_hud()
end

function on_game_start()
	RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
	RegisterScriptCallback("actor_on_net_destroy", deactivate_hud)
	RegisterScriptCallback("actor_on_before_death", deactivate_hud)
	RegisterScriptCallback("actor_on_before_hit", actor_on_before_hit)
	RegisterScriptCallback("actor_on_item_use", actor_on_item_use)
	RegisterScriptCallback("ActorMenu_on_item_focus_receive", ActorMenu_on_item_focus_receive)
	RegisterScriptCallback("ActorMenu_on_item_focus_lost", ActorMenu_on_item_focus_lost)
	RegisterScriptCallback("ActorMenu_on_mode_changed", ActorMenu_on_mode_changed)
	RegisterScriptCallback("save_state", save_state)
	RegisterScriptCallback("load_state", load_state)
	RegisterScriptCallback("actor_on_update", actor_on_update)
	RegisterScriptCallback("on_option_change", on_option_change)
end