--------------------------------- ----- Written by Darryl123 ------ --------------------------------- -- Column and row limits. local column_limit = 5 local row_limit = 10 local SINGLETON = nil function get_ui() SINGLETON = SINGLETON or pda_contacts_tab() SINGLETON:Reset() return SINGLETON end -- Constructor. class "pda_contacts_tab" (CUIScriptWnd) function pda_contacts_tab:__init() super() self.contact_info = {} self:InitControls() end -- Initialise the interface. function pda_contacts_tab:InitControls() self:SetWndRect(Frect():set(0, 0, 1024, 768)) -- Main frame. local xml = CScriptXmlInit() xml:ParseFile("pda_contacts.xml") xml:InitFrame("frame1", self) xml:InitFrame("frame2", self) xml:InitStatic("frame1:caption", self) -- Refresh checkbox. self.auto_chk = xml:InitCheck("auto_check", self) self.auto_chk:SetCheck(axr_main.config:r_value("pda_contacts", "check_refresh", 1, false)) self:Register(self.auto_chk, "check_refresh") self:AddCallback("check_refresh", ui_events.BUTTON_CLICKED, self.SaveCheckBoxSettings, self) -- 'Known contacts' checkbox. self.show_all = xml:InitCheck("show_all", self) self.show_all:SetCheck(axr_main.config:r_value("pda_contacts", "check_show_known", 1, true)) self:Register(self.show_all, "check_show_known") self:AddCallback("check_show_known", ui_events.BUTTON_CLICKED, self.SaveCheckBoxSettings, self) -- List of contact rows. self.listbox = xml:InitListBox("listbox", self) self.listbox:SetItemHeight(140) self:Register(self.listbox, "listbox") for i = 1, row_limit do self.listbox:AddExistingItem(ui_contact_row(self, i, xml)) end -- Hint Window self.hint_wnd = xml:InitFrame("hint_wnd:background", self) self.hint_wnd:SetAutoDelete(false) self.hint_wnd_text = xml:InitTextWnd("hint_wnd:text", self.hint_wnd) self.hint_wnd:Show(false) end -- Save checkboxes. function pda_contacts_tab:SaveCheckBoxSettings() axr_main.config:w_value("pda_contacts", "check_refresh", self.auto_chk:GetCheck()) axr_main.config:w_value("pda_contacts", "check_show_known", self.show_all:GetCheck()) axr_main.config:save() end -- Set the hint window text. function pda_contacts_tab:SetHint(text, pos) if (text == "") then return end self.hint_wnd:Show(true) self.hint_wnd_text:SetText(text) self.hint_wnd_text:AdjustHeightToText() self.hint_wnd:SetWndSize(vector2():set(self.hint_wnd:GetWidth(), self.hint_wnd_text:GetHeight() + 44)) pos.y = pos.y - self.hint_wnd:GetHeight() pos.x = pos.x - self.hint_wnd:GetWidth() self.hint_wnd:SetWndPos(pos) FitInRect(self.hint_wnd,Frect():set(0,0,1024,768),0,100) end -- Update the window, call via engine. function pda_contacts_tab:Update() CUIScriptWnd.Update(self) -- Auto-update if checked. if self.auto_chk:GetCheck() then local tg = time_global() if not self._tmr or self._tmr < tg then self._tmr = tg + 5000 self:Reset() end end -- Create the hint window. for i=1, (column_limit * row_limit) do if (self.contact_info[i].icon_field:IsShown()) then local pos = GetCursorPosition() local rect = Frect():set(0, 0, 0, 0) self.contact_info[i].icon_field:GetAbsoluteRect(rect) if (utils.pos_in_rect(pos, rect)) then self:SetHint(self.contact_info[i].hint, pos) return end end end self.hint_wnd:Show(false) end -- Reset the interface. function pda_contacts_tab:Reset() -- Retrieve the detection radius used by contact counter. local radius = (system_ini():r_float_ex("device_pda", "radius") or 68) ^ 2 -- Erase all pre-existing information. for i = 1, (column_limit * row_limit) do if (self.contact_info[i]) then self.contact_info[i].comm_field:SetText("") self.contact_info[i].comm_label:SetText("") self.contact_info[i].icon_field:Show(false) self.contact_info[i].name_field:SetText("") self.contact_info[i].rank_field:SetText("") self.contact_info[i].rank_label:SetText("") self.contact_info[i].rept_field:SetText("") self.contact_info[i].rept_label:SetText("") self.contact_info[i].hint = "" end end -- Loop through all currently online stalkers. local display_list = {} local m_data = alife_storage_manager.get_state() for i=1, #db.OnlineStalkers do local npc = db.storage[db.OnlineStalkers[i]] npc = npc and npc.object or level.object_by_id(db.OnlineStalkers[i]) if (npc and IsStalker(npc) and npc:alive()) then -- Display stalkers who are within the PDA contact radius. local distance = db.actor:position():distance_to_sqr(npc:position()) or 0 if (distance <= radius) then if npc:relation(db.actor) ~= game_object.enemy then if self.show_all:GetCheck() then if (m_data.actor_contacts and m_data.actor_contacts[db.OnlineStalkers[i]]) then table.insert(display_list, npc) end else table.insert(display_list, npc) end end end end end -- Special case for Sidorovich and Forester. local sor = story_objects.get_story_objects_registry() local function add_by_sid(sid) local id = sor:get(sid) if (id) then local npc = db.storage[id] and db.storage[id].object if (npc and db.actor:position():distance_to_sqr(npc:position()) <= radius) then table.insert(display_list, npc) end end end add_by_sid("esc_m_trader") add_by_sid("red_tech_forester") -- Loop through all stalkers to display. for index,stalker in ipairs(display_list) do -- Retrieve required information. local stalker_comm = stalker:character_community() local stalker_icon = stalker:character_icon() local stalker_name = stalker:character_name() local stalker_rank = ranks.get_obj_rank_name(stalker) local stalker_rept = alun_utils.get_reputation_name(stalker:character_reputation()) stalker_icon = stalker_icon and stalker_icon ~= "" and stalker_icon or "ui\\ui_noise" self.contact_info[index].icon_field:InitTexture(stalker_icon) self.contact_info[index].icon_field:Show(true) local name = string.gsub(stalker_name, "Junior", "Jr.") name = string.gsub(name, "Senior", "Sr.") name = string.gsub(name, "Master ", "M.") name = string.gsub(name, "Private", "Pvt.") name = string.gsub(name, "Sergeant", "Sgt.") name = string.gsub(name, "Lieutenant", "Lt.") name = string.gsub(name, "Captain", "Cpt.") name = string.len(name) <= 22 and name or string.sub(name, 0, 19) .. "..." self.contact_info[index].name_field:SetText(name) self.contact_info[index].comm_label:SetText(game.translate_string("ui_st_community") .. ": ") self.contact_info[index].rank_label:SetText(game.translate_string("ui_st_rank") .. ": ") self.contact_info[index].rept_label:SetText(game.translate_string("ui_st_reputation") .. ": ") self.contact_info[index].comm_field:SetText(game.translate_string(stalker_comm)) self.contact_info[index].rank_field:SetText(game.translate_string("st_rank_" .. stalker_rank)) self.contact_info[index].rept_field:SetText(game.translate_string(stalker_rept)) -- Display relation by colouring the stalker's faction name appropriately. if (xr_conditions.is_factions_friends(nil, nil, { stalker_comm, character_community(db.actor) })) then self.contact_info[index].comm_field:SetTextColor(GetARGB(255, 1, 255, 1)) elseif (xr_conditions.is_factions_enemies(nil, nil, { stalker_comm, character_community(db.actor) })) then self.contact_info[index].comm_field:SetTextColor(GetARGB(255, 255, 1, 1)) else self.contact_info[index].comm_field:SetTextColor(GetARGB(255, 255, 255, 1)) end -- Display reputation status (whether it's good or bad) by colouring the text. if (stalker:character_reputation() >= 500) then self.contact_info[index].rept_field:SetTextColor(GetARGB(255, 1, 255, 1)) elseif (stalker:character_reputation() <= -500) then self.contact_info[index].rept_field:SetTextColor(GetARGB(255, 255, 1, 1)) else self.contact_info[index].rept_field:SetTextColor(GetARGB(255, 255, 255, 1)) end -- Hint local m_data = alife_storage_manager.get_se_obj_state(alife_object(stalker:id())) if (m_data) then local s_stalker, s_mutant, s_arte, s_sold local state_str = [[ %c[255, 255, 160, 255]%c[default] %s \n \n%c[255, 215, 215, 215]st_mm_pda_statistics:%c[default] \n %c[255, 160, 160, 160]st_mm_pda_stalkers_killed:%c[default] %s \n %c[255, 160, 160, 160]st_mm_pda_mutants_killed:%c[default] %s \n %c[255, 160, 160, 160]st_mm_pda_artes_found:%c[default] %s \n %c[255, 160, 160, 160]st_mm_pda_items_sold:%c[default] %s ]] s_stalker = m_data.stalkers_killed or 0 s_mutant = m_data.mutants_killed or 0 s_arte = m_data.artefacts_found or 0 s_sold = m_data.items_sold or 0 for s in string.gmatch(state_str,"(st_mm_pda_[%w%d_]*)") do state_str = string.gsub(state_str,s,game.translate_string(s)) end state_str = strformat(state_str, stalker_name, s_stalker, s_mutant, s_arte, s_sold) self.contact_info[index].hint = state_str end end end ----- -- Row constructor. class "ui_contact_row" (CUIListBoxItem) function ui_contact_row:__init(parent, row, xml) super(parent, row, xml) self:GetTextItem():SetText("") self:SetWndSize(vector2():set(740, 140)) local index = 0 local is_widescreen = utils.is_widescreen() local offset_comm = is_widescreen and 36 or 49 local offset_rank = is_widescreen and 25 or 34 local offset_rept = is_widescreen and 51 or 68 local x = is_widescreen and 40 or 55 -- Five stalkers are listed on each row. -- Create the components for each info slot. for i = 1, column_limit do -- Calculate the index for each entry. index = i + (column_limit * (row - 1)) -- Create the components for each entry. parent.contact_info[index] = { ["comm_field"] = self:AddTextField("", 1), ["comm_label"] = self:AddTextField("", 1), ["icon_field"] = self:AddIconField(1), ["name_field"] = self:AddTextField("", 1), ["rept_label"] = self:AddTextField("", 1), ["rept_field"] = self:AddTextField("", 1), ["rank_label"] = self:AddTextField("", 1), ["rank_field"] = self:AddTextField("", 1), ["hint"] = "" } parent.contact_info[index].icon_field:InitTexture("ui\\ui_noise") parent.contact_info[index].icon_field:SetStretchTexture(true) parent.contact_info[index].icon_field:SetWndSize(vector2():set(64, 64)) parent.contact_info[index].icon_field:SetWndPos(vector2():set(x, 0)) parent.contact_info[index].name_field:SetFont(GetFontLetterica16Russian()) parent.contact_info[index].name_field:SetWndSize(vector2():set(120, 20)) parent.contact_info[index].name_field:SetWndPos(vector2():set(x, 65)) parent.contact_info[index].rank_label:SetFont(GetFontLetterica16Russian()) parent.contact_info[index].rank_label:SetWndSize(vector2():set(120, 20)) parent.contact_info[index].rank_label:SetWndPos(vector2():set(x, 80)) parent.contact_info[index].rank_field:SetFont(GetFontLetterica16Russian()) parent.contact_info[index].rank_field:SetWndSize(vector2():set(120, 20)) parent.contact_info[index].rank_field:SetWndPos(vector2():set(x + offset_rank, 80)) parent.contact_info[index].rept_label:SetFont(GetFontLetterica16Russian()) parent.contact_info[index].rept_label:SetWndSize(vector2():set(120, 20)) parent.contact_info[index].rept_label:SetWndPos(vector2():set(x, 95)) parent.contact_info[index].rept_field:SetFont(GetFontLetterica16Russian()) parent.contact_info[index].rept_field:SetWndSize(vector2():set(120, 20)) parent.contact_info[index].rept_field:SetWndPos(vector2():set(x + offset_rept, 95)) parent.contact_info[index].comm_label:SetFont(GetFontLetterica16Russian()) parent.contact_info[index].comm_label:SetWndSize(vector2():set(120, 20)) parent.contact_info[index].comm_label:SetWndPos(vector2():set(x, 110)) parent.contact_info[index].comm_field:SetFont(GetFontLetterica16Russian()) parent.contact_info[index].comm_field:SetWndSize(vector2():set(120, 20)) parent.contact_info[index].comm_field:SetWndPos(vector2():set(x + offset_comm, 110)) x = x + (is_widescreen and 150 or 180) end end