--[[ 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