Divergent/mods/Immersive Sleep/gamedata/scripts/ui_sleep_dialog.script

456 lines
12 KiB
Plaintext
Raw Normal View History

2024-03-17 20:18:03 -04:00
--[[
Modified by Tronex
Last modification: 2018/5/23
Prevent sleeping abuse of Ironman Life Granter feature
--]]
local last_sleep, last_sleep_chk, pwr_chk
------------------------------------------------------------
-- UI
------------------------------------------------------------
GUI = nil -- instance, don't touch
class "UISleep" (CUIScriptWnd)
function UISleep:__init() super()
self:InitControls()
self:InitCallbacks()
end
function UISleep:__finalize()
GUI = nil
end
function UISleep:InitControls()
self:SetWndRect(Frect():set(0,0,1024,768))
self.wide = (device().width/device().height) > (1024/768 + 0.01)
self:SetAutoDelete(true)
local xml = CScriptXmlInit()
xml:ParseFile("ui_sleep_dialog.xml")
self.back = xml:InitStatic("background", self)
-- self.sleep_static = xml:InitSleepStatic("sleep_static", self.back)
self.sleep_static = xml:InitStatic("sleep_static", self.back)
self.sleep_static2 = xml:InitStatic("sleep_static", self.back)
self.static_cover = xml:InitStatic("static_cover", self.back)
self.st_marker = xml:InitStatic("st_marker", self.static_cover)
self.sleep_st_tbl = {}
for i = 1, 24 do
self.sleep_st_tbl[i] = xml:InitStatic("sleep_st_"..i, self.back)
end
self.time_track = xml:InitTrackBar("time_track", self.back)
self:Register(self.time_track, "time_track")
self.btn_sleep = xml:Init3tButton("btn_sleep", self.back)
self:Register(self.btn_sleep, "btn_sleep")
self.btn_cancel = xml:Init3tButton("btn_cancel", self.back)
self:Register(self.btn_cancel, "btn_cancel")
end
function UISleep:InitCallbacks()
self:AddCallback("btn_sleep", ui_events.BUTTON_CLICKED, self.OnButtonSleep, self)
self:AddCallback("btn_cancel", ui_events.BUTTON_CLICKED, self.Close, self)
end
function UISleep:Initialize()
local cur_hours = level.get_time_hours()
for i = 1, 24 do
local hours = cur_hours + i
if (hours >= 24) then
hours = hours - 24
end
self.sleep_st_tbl[i]:TextControl():SetText(hours..game.translate_string("st_sleep_hours"))
end
local delta = math.floor(591/24*cur_hours)
local r = Frect():set(delta,413,591,531)
self.sleep_static:SetTextureRect(r)
local width = 591-delta
if (self.wide) then
width = width * 0.8
end
self.sleep_static:SetWndSize(vector2():set(width, 118))
r = Frect():set(0,413,delta,531)
self.sleep_static2:SetTextureRect(r)
local width = delta
if (self.wide) then
width = width * 0.8
end
self.sleep_static2:SetWndSize(vector2():set(width, 118))
local pos = self.sleep_static2:GetWndPos()
pos.x = self.sleep_static:GetWndPos().x+self.sleep_static:GetWidth()
self.sleep_static2:SetWndPos(pos)
end
function UISleep:TestAndShow(force)
local last_sleep = actor_status_sleep.get_last_sleep()
printdbg("#Immersive Sleep | last_sleep: %s",tostring(last_sleep))
if(last_sleep < 3000) then
actor_menu.set_msg(1, game.translate_string("st_sleep_awake"),4)
return
end
if (force ~= true) then
local bleeding = db.actor.bleeding > 0
local radiation = db.actor.radiation > 0
-- Prevent sleep if bleeding and/or iradiated.
if (bleeding or radiation) then
if (bleeding and radiation) then
actor_menu.set_msg(1, game.translate_string("st_sleep_bleeding_irradiated"),5)
elseif (bleeding) then
actor_menu.set_msg(1, game.translate_string("st_sleep_bleeding"),4)
elseif (radiation) then
actor_menu.set_msg(1, game.translate_string("st_sleep_irradiated"),4)
end
return
end
-- Check if actor is inside a safe zone
local actor_hide = GetEvent("current_safe_cover") and true or false
-- Check if actor is inside a tent
if (not actor_hide) then
actor_hide = item_tent.get_nearby_tent(1.5)
end
-- If all is no, dont sleep
if (not actor_hide) then
actor_menu.set_msg(1, game.translate_string("st_cant_sleep_find_shelter_mlr"),4)
return
end
end
self:Initialize()
self:ShowDialog(true)
Register_UI("UISleep","ui_sleep_dialog")
end
function UISleep:Update()
CUIScriptWnd.Update(self)
if self:IsShown() then
local sleep_time = self.time_track:GetIValue()-1
local x = math.floor(591/24 * sleep_time)
if (x==0) then
x = 5
end
if (self.wide) then
x = x * 0.8
end
self.st_marker:SetWndPos(vector2():set(x, 0))
end
end
function UISleep:OnTrackButton()
end
function UISleep:OnButtonSleep()
if self:IsShown() then
self:HideDialog()
Unregister_UI("UISleep")
end
save_var(db.actor,"heli_enemy_flag",nil)
xr_effects.disable_ui(db.actor, nil)
level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "ui_sleep_dialog.dream_callback")
level.add_pp_effector("sleep_fade.ppe", 11, false)
_G.mus_vol = get_console_cmd(2,"snd_volume_music")
_G.amb_vol = get_console_cmd(2,"snd_volume_eff")
exec_console_cmd("snd_volume_music 0")
exec_console_cmd("snd_volume_eff 0")
if self.forced then
level.add_cam_effector("camera_effects\\surge_02.anm", 10, false, "ui_sleep_dialog.dream_callback")
else
level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "ui_sleep_dialog.dream_callback")
exec_console_cmd("snd_volume_music 0")
exec_console_cmd("snd_volume_eff 0")
db.actor:activate_slot(0) -- hide weapon
local flist = getFS():file_list_open_ex("$game_saves$", bit_or(FS.FS_ListFiles,FS.FS_RootOnly),"*".. ui_load_dialog.saved_game_extension)
local f_cnt = flist and flist:Size() or 0
local inc = 0
if (f_cnt > 0) then
flist:Sort(FS.FS_sort_by_modif_down)
for it=0, f_cnt-1 do
local file_name = flist:GetAt(it):NameFull():sub(0,-6):lower()
-- grab last modified quicksave increment count
local d = tonumber( string.match(file_name,"sleep_autosave(%d+)") )
if (d) then
inc = d
break
end
end
end
inc = (inc >= ui_options.get("other/quicksave_cnt")) and 1 or inc + 1
end
level.add_pp_effector("surge_fade.ppe", 11, false) --sleep_fade.ppe
db.actor:give_info_portion("actor_is_sleeping")
end
function UISleep:OnKeyboard(dik, keyboard_action)
local res = CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
if (res == false) then
local bind = dik_to_bind(dik)
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
if dik == DIK_keys.DIK_ESCAPE then
self:Close()
end
end
end
return res
end
function UISleep:Close()
if (self:IsShown()) then
self:HideDialog()
end
--db.actor:give_info_portion("tutorial_sleep")
disable_info("actor_is_sleeping")
disable_info("sleep_active")
Unregister_UI("UISleep")
end
------------------------------------------------------------
-- Utilities
------------------------------------------------------------
-- Immersive Sleep By TKCrits
-- v1.2
function get_immersive_sleep_hours(hours)
local sleepiness = actor_status_sleep.get_last_sleep() or 0
local hours_fully_rested = 0
local max_sleep_percentage = 0.9 -- 90% of total hours
local comfy = 0
local comfy0_rest = 520
local comfy1_rest = 624 -- 520 +20% (104) = 624
local comfy2_rest = 676 -- 520 +30% (156) = 676
local rest_per_hour = comfy0_rest
local early_wakeup_percentage = 0 -- 0% chance of waking early (base value)
local early_wakeup_multiplier = 8.3 -- hours * 8.3 = percentage (12 * 8.3 = 100)
local early_wakeup_hour = 0.63 -- 63% of total hours
--------------------------------------------------------
-- Get Comfort
-- Comfy sleep (bedspread / sleeping bag)
-- Sleeping bag = +20% comfort
-- Sleeping bag & bedspread = +30% comfort
printdbg("#Immersive Sleep | Sleeping Bag: %s",tostring(GUI.ph_sleepbag_id))
if((GUI.ph_sleepbag_id or 0) > 0) then
comfy = 1
rest_per_hour = comfy1_rest
if(db.actor:object("beadspread")) then
printdbg("#Immersive Sleep | Bedspread and Sleeping bag available")
comfy = 2
rest_per_hour = comfy2_rest
end
end
-- Get fully rested hour
if(sleepiness > 0) then
hours_fully_rested = math.floor(sleepiness/rest_per_hour)
end
-- Dont sleep longer than fully rested
if(hours > hours_fully_rested) then
hours = hours_fully_rested
end
printdbg("#Immersive Sleep | Fully Rested: %s",tostring(hours_fully_rested))
-- On comfort 0, don't sleep longer than 90% of fully rested hours
if(comfy == 0) then
hours = math.floor(hours * max_sleep_percentage)
end
-- Calculate Wakeup Chance (12 hrs * 8.3 = 100%)
early_wakeup_percentage = early_wakeup_percentage + math.floor(hours * early_wakeup_multiplier)
-- Set Comfort Bonuses
if(comfy == 1) then
early_wakeup_percentage = early_wakeup_percentage - 20
actor_status_sleep.set_rest_per_hour(comfy1_rest)
elseif (comfy == 2) then
early_wakeup_percentage = early_wakeup_percentage - 30
actor_status_sleep.set_rest_per_hour(comfy2_rest)
else
actor_status_sleep.set_rest_per_hour(comfy0_rest)
end
printdbg("#Immersive Sleep | Early Wakeup Chance: %s",tostring(early_wakeup_percentage))
-- Random chance of waking up
local woke_early = 0
local rng = math.random(0,100)
if (rng < early_wakeup_percentage) then
woke_early = 1
local min_wakeup_hour = math.floor(hours * early_wakeup_hour)
hours = math.random(min_wakeup_hour,(hours-1))
printdbg("#Immersive Sleep | Waking up early after: %s",tostring(hours))
end
if(woke_early == 1) then
-- "Woke up early after "
actor_menu.set_msg(1, string.format(game.translate_string("st_sleep_awake_woke_early"),tostring(hours)),4)
elseif(comfy < 2) then
-- "Slept for "
actor_menu.set_msg(1, string.format(game.translate_string("st_sleep_awake_slept_for"),tostring(hours)),4)
elseif(comfy == 2) then
-- "Slept very well for "
actor_menu.set_msg(1, string.format(game.translate_string("st_sleep_awake_slept_well"),tostring(hours)),4)
end
return hours
end
function dream_callback()
if GUI.forced then
level.add_cam_effector("camera_effects\\surge_01.anm", 10, false, "ui_sleep_dialog.dream_callback2")
else
level.add_cam_effector("camera_effects\\sleep.anm", 10, false, "ui_sleep_dialog.dream_callback2")
end
local hours = GUI.forced or GUI.time_track:GetIValue() --printf("dream_callback hours=%s",hours)
hours = get_immersive_sleep_hours(hours)
level.change_game_time(0,hours,0)
db.actor.power = 1
SendScriptCallback("actor_on_sleep",hours)
end
function dream_callback2()
xr_effects.enable_ui(db.actor, nil)
exec_console_cmd("snd_volume_music "..tostring(_G.mus_vol))
exec_console_cmd("snd_volume_eff "..tostring(_G.amb_vol))
exec_console_cmd("save " .. (user_name() or "") .. " - sleep")
_G.amb_vol = 0
_G.mus_vol = 0
disable_info("tutorial_sleep")
disable_info("actor_is_sleeping")
disable_info("sleep_active")
end
function sleep(force)
if (GUI == nil) then
GUI = ui_sleep_dialog.UISleep()
end
GUI.forced = nil
GUI.time_track:SetCurrentValue()
GUI:TestAndShow(force)
end
function sleep_forced(hours)
if (GUI == nil) then
GUI = ui_sleep_dialog.UISleep()
end
GUI.forced = hours or math.random(3,9)
GUI:OnButtonSleep()
end
function sleep_bag(ph_sleepbag_id, sec)
if (GUI == nil) then
GUI = ui_sleep_dialog.UISleep()
end
GUI.forced = nil
GUI.item_section = sec
GUI.ph_sleepbag_id = ph_sleepbag_id
GUI.time_track:SetCurrentValue()
GUI:TestAndShow()
--return GUI
end
local sleep_zones = {
"actor_surge_hide_2",
"agr_army_sleep",
"agr_sr_sleep_tunnel",
"agr_sr_sleep_wagon",
"bar_actor_sleep_zone",
"cit_merc_sleep",
"ds_farmhouse_sleep",
"esc_basement_sleep_area",
"esc_secret_sleep",
"gar_angar_sleep",
"gar_dolg_sleep",
"jup_a6_sr_sleep",
"mar_a3_sr_sleep",
"mil_freedom_sleep",
"mil_smart_terran_2_4_sleep",
"pri_a16_sr_sleep",
"pri_monolith_sleep",
"pri_room27_sleep",
"rad_sleep_room",
"ros_vagon_sleep",
"val_abandoned_house_sleep",
"val_vagon_sleep",
"yan_bunker_sleep_restrictor",
"zat_a2_sr_sleep",
"pol_secret_sleep"
}
function sleep_in_zone(actor, npc)
for k,v in pairs(sleep_zones) do
if utils_obj.npc_in_zone(db.actor, v) then
sleep()
give_info("sleep_active")
break
end
end
end
function main()
sleep()
end
------------------------------------------------------------
-- Debug
------------------------------------------------------------
local function on_game_load()
-- Debug Commands
local CMD = debug_cmd_list.command_get_list()
function CMD.sleep(_,__,x)
sleep(true)
x:SendOutput('-Sleeping time')
end
-- Debug Launcher executions
ui_debug_launcher.inject("action", { name = "Sleep" , cmd = "sleep" , hide_ui = 2 } )
end
function on_game_start()
if DEV_DEBUG then
RegisterScriptCallback("on_game_load",on_game_load)
end
end