Removed EGUI in favor of UI Rework by Sota Added in GTR Optimized for higher res textures, over Zone Reality Remade and removed all files that conflicted from ZRR to save storage space.
3546 lines
105 KiB
Plaintext
3546 lines
105 KiB
Plaintext
|
|
--[[
|
|
|
|
- Tronex
|
|
- 2020/2/3
|
|
- Item cell utilities
|
|
- Simulation to engine CUI classes in LUA, have a full control over how things work
|
|
|
|
Item cell:
|
|
Item icon and its related elements (Icon layers, attachments, condition bar, stack counter, upgrade indicator, color)
|
|
Support: set/update function to adapt to changes, highlight area with custom color
|
|
|
|
Item container:
|
|
A place to holds and organize item cells together, easy to set or remove item cells with indexing methods
|
|
Support for cell hover/highlight, drag and drop and callbacks with owner classes
|
|
|
|
Item properties:
|
|
Show a list of context that player can set and customize for the item cell
|
|
|
|
Item info box:
|
|
For item cells
|
|
Consist of: name, weight, price/points (based on mode), description, stats list (icon / text), ammo list
|
|
Support stats comparison with equipped items of the same slot
|
|
|
|
Upgrade info box:
|
|
For item upgrade cells
|
|
Consist of: name, description, state or pre-requirements, stats list (icon + text)
|
|
|
|
|
|
------------------
|
|
TODO:
|
|
- Upgrades support for info box
|
|
- info box pos relative to mouse need improvements
|
|
|
|
--]]
|
|
|
|
|
|
local ratio = utils_xml.screen_ratio()
|
|
local uwide_ratio = ((ratio < 0.75) and 0.75 or 1) -- Added by Sota
|
|
|
|
local XMLP = CScriptXmlInit()
|
|
XMLP:ParseFile("utils.xml")
|
|
|
|
-- Icon coloring base on inventory mode and interaction
|
|
local clr_list = {
|
|
["def"] = GetARGB(255, 255, 255, 255),
|
|
["red"] = GetARGB(255, 255, 50, 50),
|
|
["green"] = GetARGB(255, 100, 255, 150),
|
|
["blue"] = GetARGB(255, 100, 150, 255),
|
|
["black"] = GetARGB(255, 0, 0, 0),
|
|
|
|
["drag"] = GetARGB(150, 255, 255, 255),
|
|
["hide"] = GetARGB(70, 255, 255, 255),
|
|
["shadow"] = GetARGB(200, 20, 20, 20),
|
|
["hide_shadow"] = GetARGB(70, 20, 20, 20),
|
|
|
|
["p1"] = GetARGB(255, 170, 170, 170),
|
|
["n1"] = GetARGB(255, 200, 50, 50),
|
|
["p2"] = GetARGB(255, 51, 255, 102),
|
|
["n2"] = GetARGB(255, 204, 0, 51),
|
|
|
|
["info_def"] = GetARGB(200, 255, 255, 255),
|
|
["info_p"] = GetARGB(255, 56, 209, 115),
|
|
["info_n"] = GetARGB(255, 238, 28, 36),
|
|
["info_p_txt"] = GetARGB(200, 100, 255, 100),
|
|
["info_n_txt"] = GetARGB(200, 255, 100, 100),
|
|
}
|
|
|
|
local clr_list_hl = {
|
|
["def"] = GetARGB(25, 255, 255, 255),
|
|
["green"] = GetARGB(30, 100, 255, 150),
|
|
["blue"] = GetARGB(40, 100, 200, 255),
|
|
}
|
|
|
|
-- Progress bar profiles based on "condition_bar" parameter in item section
|
|
local bar_list = {
|
|
["condition_progess_bar"] = { min= {255,196,18,18,0}, mid= {255,255,255,118,0.5}, max= {255,107,207,119,1}, background= true},
|
|
["power_progess_bar"] = { def= GetARGB(255,86,196,209), background= true },
|
|
["uses_progess_bar"] = { def= GetARGB(255,255,255,255), background= false },
|
|
}
|
|
|
|
-- UI events
|
|
local K_M1 = DIK_keys.MOUSE_1
|
|
local K_M2 = DIK_keys.MOUSE_2
|
|
local K_SHFT = DIK_keys.DIK_LSHIFT
|
|
local E_PRESS = ui_events.WINDOW_KEY_PRESSED
|
|
local E_RELEASE = ui_events.WINDOW_KEY_RELEASED
|
|
|
|
-- Utils
|
|
local has_upgrades = utils_item.has_upgrades
|
|
local sync_element = utils_xml.sync_element
|
|
local sync_cursor = utils_xml.sync_cursor
|
|
local get_item_axis = utils_xml.get_item_axis
|
|
local get_item_trade_status = utils_item.get_item_trade_status
|
|
local get_item_cost = utils_item.get_item_cost
|
|
local lerp_color = utils_xml.lerp_color
|
|
|
|
-- Main Menu
|
|
local mm_active = true
|
|
|
|
function main_menu_on()
|
|
mm_active = true
|
|
end
|
|
|
|
function main_menu_off()
|
|
mm_active = false
|
|
end
|
|
|
|
function on_game_start()
|
|
RegisterScriptCallback("main_menu_on_init", main_menu_on)
|
|
RegisterScriptCallback("main_menu_on_quit", main_menu_off)
|
|
end
|
|
|
|
function get_time()
|
|
return mm_active and time_continual() or time_global()
|
|
end
|
|
|
|
-- Item order
|
|
local item_order = {}
|
|
function set_item_order()
|
|
local n = ini_sys:line_count("item_kind_order")
|
|
for i=0,n-1 do
|
|
local result, kind, order = ini_sys:r_line_ex("item_kind_order",i,"","")
|
|
if kind and order then
|
|
item_order[kind] = tonumber(order) or 30
|
|
end
|
|
end
|
|
item_order["na"] = size_table(item_order) + 1
|
|
end
|
|
set_item_order()
|
|
|
|
local ab_w, ab_h, ab_k = {}, {}, {}
|
|
local a_sec, a_w, a_h, a_k
|
|
local b_sec, b_w, b_h, b_k
|
|
function sort_info(asec, bsec)
|
|
-- A
|
|
a_sec = asec
|
|
if (not ab_w[a_sec]) then ab_w[a_sec] = SYS_GetParam(2,a_sec,"inv_grid_width",1) end
|
|
if (not ab_h[a_sec]) then ab_h[a_sec] = SYS_GetParam(2,a_sec,"inv_grid_height",1) end
|
|
if (not ab_k[a_sec]) then
|
|
ab_k[a_sec] = SYS_GetParam(0,a_sec,"kind","na")
|
|
if (not item_order[ab_k[a_sec]]) then
|
|
ab_k[a_sec] = "na"
|
|
end
|
|
end
|
|
a_w = ab_w[a_sec]
|
|
a_h = ab_h[a_sec]
|
|
a_k = item_order[ab_k[a_sec]]
|
|
|
|
-- B
|
|
b_sec = bsec
|
|
if (not ab_w[b_sec]) then ab_w[b_sec] = SYS_GetParam(2,b_sec,"inv_grid_width",1) end
|
|
if (not ab_h[b_sec]) then ab_h[b_sec] = SYS_GetParam(2,b_sec,"inv_grid_height",1) end
|
|
if (not ab_k[b_sec]) then
|
|
ab_k[b_sec] = SYS_GetParam(0,b_sec,"kind","na")
|
|
if (not item_order[ab_k[b_sec]]) then
|
|
ab_k[b_sec] = "na"
|
|
end
|
|
end
|
|
b_w = ab_w[b_sec]
|
|
b_h = ab_h[b_sec]
|
|
b_k = item_order[ab_k[b_sec]]
|
|
end
|
|
|
|
function sort_by_size(t,a,b)
|
|
if (type(t[a]) == "string") then
|
|
sort_info(t[a], t[b])
|
|
else
|
|
sort_info(t[a]:section(), t[b]:section())
|
|
end
|
|
|
|
-- Comparison
|
|
--printf("%s - %s", a_sec, b_sec)
|
|
if (a_w == b_w) then
|
|
if (a_h == b_h) then
|
|
if (a_sec == b_sec) then
|
|
if (type(t[a]) == "string") then
|
|
return false --true
|
|
end
|
|
return t[a]:id() > t[b]:id()
|
|
end
|
|
return a_sec < b_sec -- alphaptic order
|
|
end
|
|
return a_h > b_h
|
|
end
|
|
return a_w > b_w
|
|
end
|
|
|
|
function sort_by_kind(t,a,b)
|
|
if (type(t[a]) == "string") then
|
|
sort_info(t[a], t[b])
|
|
else
|
|
sort_info(t[a]:section(), t[b]:section())
|
|
end
|
|
|
|
if a_k == b_k then
|
|
return sort_by_size(t,a,b)
|
|
end
|
|
return a_k < b_k
|
|
end
|
|
|
|
function sort_by_index(t,a,b)
|
|
return t[a].index < t[b].index
|
|
end
|
|
|
|
function sort_by_sizekind(t,a,b)
|
|
if (type(t[a]) == "string") then
|
|
sort_info(t[a], t[b])
|
|
else
|
|
sort_info(t[a]:section(), t[b]:section())
|
|
end
|
|
|
|
-- Comparison
|
|
--printf("%s - %s", a_sec, b_sec)
|
|
|
|
--\\ bigger width wins
|
|
if (a_w == b_w) then
|
|
--\\ bigger height wins
|
|
if (a_h == b_h) then
|
|
--\\ important kind wins
|
|
if a_k == b_k then
|
|
--\\ alphaptic order wins
|
|
if (a_sec == b_sec) then
|
|
--\\ better condition wins
|
|
if (type(t[a]) == "string") then
|
|
return false --true
|
|
end
|
|
return t[a]:condition() > t[b]:condition()
|
|
end
|
|
return a_sec < b_sec
|
|
end
|
|
return a_k < b_k
|
|
end
|
|
return a_h > b_h
|
|
end
|
|
return a_w > b_w
|
|
end
|
|
|
|
function sort_by_props(t,a,b)
|
|
-- Only for objects with same sections
|
|
local sec = t[a]:section()
|
|
|
|
-- For ammo, bigger ammo counts wins
|
|
if IsItem("ammo",sec) and (not IsItem("grenade_ammo",sec)) then
|
|
return t[a]:ammo_get_count() > t[b]:ammo_get_count()
|
|
|
|
-- Upgraded items wins
|
|
elseif utils_item.has_upgrades(t[a]) and (not utils_item.has_upgrades(t[b])) then
|
|
return true
|
|
end
|
|
|
|
-- Better condition wins
|
|
return t[a]:condition() > t[b]:condition()
|
|
end
|
|
|
|
|
|
-- Item stats
|
|
stats_table = {}
|
|
function prepare_stats_table()
|
|
--[[
|
|
index : showing stat by numric order
|
|
typ : parameter value type, important for parsing the value out of parameter section
|
|
name : translation string
|
|
icon_p : icon to show on positive value
|
|
icon_n : icon to show on negavtive value (empty means use positive icon for all occasions)
|
|
track : should stat be represnted by a progress bar or text
|
|
magnitude : multiplier for parameter value, to represent it to the player for better readings
|
|
unit :
|
|
compare : allow state comparison with different items (for item info box)
|
|
sign : show number sign +/-
|
|
show_always : should we show state even if value was 0
|
|
value_functor: calculate paramter value by using a special function
|
|
--]]
|
|
if is_not_empty(stats_table) then return end
|
|
|
|
stats_table["weapon"] = {
|
|
["accuracy"] = { index= 1, typ= "float", name= "ui_inv_accuracy", icon_p= "ui_wp_prop_tochnost", icon_n= "", track= true, magnitude= 1, unit= "", compare= false, sign= false, show_always= true, value_functor= {"utils_ui","prop_accuracry"} },
|
|
["handling"] = { index= 2, typ= "float", name= "ui_inv_handling", icon_p= "ui_wp_prop_ergonomics", icon_n= "", track= true, magnitude= 1, unit= "", compare= false, sign= true, show_always= true, value_functor= {"utils_ui","prop_handling"} },
|
|
["damage"] = { index= 3, typ= "float", name= "ui_inv_damage", icon_p= "ui_wp_prop_damage", icon_n= "", track= true, magnitude= 1, unit= "", compare= false, sign= true, show_always= true , value_functor= {"utils_ui","prop_damage"} },
|
|
["fire_rate"] = { index= 4, typ= "float", name= "ui_inv_rate_of_fire", icon_p= "ui_wp_prop_skorostrelnost", icon_n= "", track= true, magnitude= 1, unit= "", compare= false, sign= false, show_always= true, value_functor= {"utils_ui","prop_rpm"} },
|
|
["ammo_mag_size"] = { index= 5, typ= "float", name= "ui_ammo_count", icon_p= "ui_wp_propery_07", icon_n= "", track= false, magnitude= 1, unit= "", compare= false, sign= false ,show_always= true },
|
|
}
|
|
|
|
stats_table["outfit"] = {
|
|
["fire_wound_protection"] = { index= 1, typ= "float", name= "ui_inv_outfit_fire_wound_protection", icon_p= "ui_am_propery_01", icon_n= "", track= true, magnitude= (1/SYS_GetParam(2,"actor_condition","max_fire_wound_protection")), unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "FireWound"}},
|
|
["burn_protection"] = { index= 2, typ= "float", name= "ui_inv_outfit_burn_protection", icon_p= "ui_am_prop_thermo", icon_n= "", track= true, magnitude= (1/SYS_GetParam(2,"actor_condition","fire_zone_max_power")), unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "Burn"} },
|
|
["shock_protection"] = { index= 3, typ= "float", name= "ui_inv_outfit_shock_protection", icon_p= "ui_am_prop_electro", icon_n= "", track= true, magnitude= (1/SYS_GetParam(2,"actor_condition","electra_zone_max_power")), unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "Shock"}},
|
|
["chemical_burn_protection"] = { index= 4, typ= "float", name= "ui_inv_outfit_chemical_burn_protection", icon_p= "ui_am_prop_chem", icon_n= "", track= true, magnitude= (1/SYS_GetParam(2,"actor_condition","acid_zone_max_power")), unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "ChemicalBurn"}},
|
|
["radiation_protection"] = { index= 5, typ= "float", name= "ui_inv_outfit_radiation_protection", icon_p= "ui_am_propery_09", icon_n= "", track= true, magnitude= (1/SYS_GetParam(2,"actor_condition","radio_zone_max_power")), unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "Radiation"}},
|
|
["telepatic_protection"] = { index= 6, typ= "float", name= "ui_inv_outfit_telepatic_protection", icon_p= "ui_am_propery_11", icon_n= "", track= true, magnitude= (1/SYS_GetParam(2,"actor_condition","psi_zone_max_power")), unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "Telepatic"}},
|
|
["wound_protection"] = { index= 7, typ= "float", name= "ui_inv_outfit_wound_protection", icon_p= "ui_am_prop_wound", icon_n= "", track= true, magnitude= (1/SYS_GetParam(2,"actor_condition","max_wound_protection")), unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "Wound"}},
|
|
["strike_protection"] = { index= 8, typ= "float", name= "ui_inv_outfit_strike_protection", icon_p= "ui_am_prop_strike", icon_n= "", track= true, magnitude= 1, unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "Strike"}},
|
|
["explosion_protection"] = { index= 9, typ= "float", name= "ui_inv_outfit_explosion_protection", icon_p= "ui_am_prop_explo", icon_n= "", track= true, magnitude= 1, unit= "", condition= true, compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_protection", "Explosion"}},
|
|
["artefact_count"] = { index= 10, typ= "float", name= "ui_inv_outfit_artefact_count", icon_p= "ui_am_prop_artefact",icon_n= "", track= false, magnitude= 1, unit= "", compare= false, sign= false,show_always= true , value_functor= {"utils_item","get_outfit_belt_size"}},
|
|
["additional_inventory_weight"]= { index= 11, typ= "float", name= "ui_inv_outfit_additional_weight", icon_p= "ui_am_propery_08", icon_n= "ui_am_prop_carry_weight_negative", track= false, magnitude= 1, unit= "st_kg", compare= false, sign= true, show_always= true , value_functor= {"utils_item","get_outfit_property", "additional_inventory_weight"}},
|
|
}
|
|
|
|
stats_table["backpack"] = {
|
|
["additional_inventory_weight"]= { index= 1, typ= "float", name= "ui_inv_outfit_additional_weight", icon_p= "ui_am_propery_08", icon_n= "ui_am_prop_carry_weight_negative", track= false, magnitude= 1, unit= "st_kg", compare= false, sign= true, show_always= true},
|
|
}
|
|
|
|
stats_table["artefact"] = {
|
|
["condition"] = { index= 1, typ= "float", name= "ui_inv_af_condition", icon_p= "ui_am_condition", icon_n= "", track= false, magnitude= 100, unit= "st_perc", compare= false, sign= true, show_always= true , value_functor= {"utils_ui","prop_condition"} },
|
|
["health_restore_speed"] = { index= 2, typ= "float", name= "ui_inv_health", icon_p= "ui_am_propery_05", icon_n= "ui_am_prop_health_negative", track= false, magnitude= 6600, unit= "", condition= true, compare= false, sign= true, show_always= false },
|
|
["radiation_restore_speed"] = { index= 3, typ= "float", name= "ui_inv_radiation", icon_p= "ui_am_propery_09", icon_n= "ui_am_prop_radio_restore", track= false, magnitude= 47000, unit= "st_msv_sec", condition= true, compare= false, sign= true, show_always= false, sign_inverse= true },
|
|
["satiety_restore_speed"] = { index= 4, typ= "float", name= "ui_inv_satiety", icon_p= "ui_am_prop_satiety_restore_speed", icon_n= "ui_am_prop_satiety", track= false, magnitude= 100, unit= "", condition= true, compare= false, sign= true, show_always= false },
|
|
["power_restore_speed"] = { index= 5, typ= "float", name= "ui_inv_power", icon_p= "ui_am_propery_07", icon_n= "ui_am_prop_power_restore", track= false, magnitude= 30000, unit= "st_perc", condition= true, compare= false, sign= true, show_always= false },
|
|
["bleeding_restore_speed"] = { index= 6, typ= "float", name= "ui_inv_bleeding", icon_p= "ui_am_prop_restore_bleeding", icon_n= "ui_am_prop_bleeding_restore", track= false, magnitude= 15000, unit= "st_ml_min", condition= true, compare= false, sign= true, show_always= false },
|
|
["burn_immunity"] = { index= 7, typ= "float", name= "ui_inv_outfit_burn_protection", icon_p= "ui_am_prop_thermo", icon_n= "ui_am_prop_burn_immunity", track= false, magnitude= 84800, unit= "st_perc", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["shock_immunity"] = { index= 8, typ= "float", name= "ui_inv_outfit_shock_protection", icon_p= "ui_am_prop_electro", icon_n= "ui_am_prop_shock_immunity", track= false, magnitude= 8000, unit= "st_kv", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["radiation_immunity"] = { index= 9, typ= "float", name= "ui_inv_outfit_radiation_protection", icon_p= "ui_am_propery_09", icon_n= "ui_am_prop_radiation_immunity", track= false, magnitude= 750, unit= "st_perc", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["telepatic_immunity"] = { index= 10, typ= "float", name= "ui_inv_outfit_telepatic_protection", icon_p= "ui_am_propery_11", icon_n= "ui_am_prop_telepat_immunity", track= false, magnitude= 5800, unit= "st_perc", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["chemical_burn_immunity"] = { index= 11, typ= "float", name= "ui_inv_outfit_chemical_burn_protection", icon_p= "ui_am_prop_chem", icon_n= "ui_am_prop_chemburn_immunity", track= false, magnitude= 19100, unit= "st_perc", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["wound_immunity"] = { index= 12, typ= "float", name= "ui_inv_outfit_wound_protection", icon_p= "ui_am_prop_wound", icon_n= "ui_am_prop_wound_minus", track= false, magnitude= 2500, unit= "st_j", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["fire_wound_immunity"] = { index= 13, typ= "float", name= "ui_inv_outfit_fire_wound_protection", icon_p= "ui_am_propery_01", icon_n= "ui_am_prop_fire_wound_negative", track= false, magnitude= 2500, unit= "st_j", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["explosion_immunity"] = { index= 14, typ= "float", name= "ui_inv_outfit_explosion_protection", icon_p= "ui_am_prop_explo", icon_n= "ui_am_prop_explo_minus", track= false, magnitude= 2500, unit= "st_j", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["strike_immunity"] = { index= 15, typ= "float", name= "ui_inv_outfit_strike_protection", icon_p= "ui_am_prop_strike", icon_n= "ui_am_prop_strike_minus", track= false, magnitude= 2500, unit= "st_j", condition= true, compare= false, sign= true, show_always= false ,section= "hit_absorbation_sect" },
|
|
["additional_inventory_weight"]= { index= 16, typ= "float", name= "ui_inv_outfit_additional_weight", icon_p= "ui_am_propery_08", icon_n= "ui_am_prop_carry_weight_negative", track= false, magnitude= 1000, unit= "st_g", compare= false, sign= true, show_always= false },
|
|
}
|
|
|
|
stats_table["booster"] = {
|
|
["boost_time"] = { index= 1, typ= "float", name= "ui_inv_effect_time", icon_p= "ui_am_prop_time_period", icon_n= "", track= false, magnitude= 1, unit= "ui_inv_seconds", compare= false, sign= true, show_always= false },
|
|
["boost_health_restore"] = { index= 2, typ= "float", name= "ui_inv_health", icon_p= "ui_am_propery_05", icon_n= "", track= false, magnitude= 1000, unit= "st_perc", compare= false, sign= true, show_always= false },
|
|
["boost_radiation_restore"] = { index= 3, typ= "float", name= "ui_inv_radiation", icon_p= "ui_am_propery_09", icon_n= "", track= false, magnitude= 30000, unit= "st_msv_sec", compare= false, sign= true, show_always= false, sign_inverse_txt= true },
|
|
["eat_satiety"] = { index= 4, typ= "float", name= "ui_inv_satiety", icon_p= "ui_am_prop_satiety_restore_speed", icon_n= "ui_am_prop_satiety", track= false, magnitude= 1000, unit= "st_kcal", compare= false, sign= true, show_always= false },
|
|
["boost_anabiotic"] = { index= 5, typ= "float", name= "", icon_p= "ui_am_prop_Vibros", icon_n= "ui_am_prop_anabiotic", track= false, magnitude= 1000, unit= "", compare= false, sign= true, show_always= false },
|
|
["boost_power_restore"] = { index= 6, typ= "float", name= "ui_inv_power", icon_p= "ui_am_propery_07", icon_n= "ui_am_prop_power_restore", track= false, magnitude= 100000, unit= "st_microg", compare= false, sign= true, show_always= false },
|
|
["boost_bleeding_restore"] = { index= 7, typ= "float", name= "ui_inv_bleeding", icon_p= "ui_am_prop_restore_bleeding", icon_n= "ui_am_prop_bleeding_restore", track= false, magnitude= 150000, unit= "st_ml_min", compare= false, sign= true, show_always= false },
|
|
["boost_radiation_protection"] = { index= 8, typ= "float", name= "ui_inv_outfit_radiation_protection", icon_p= "ui_am_propery_09", icon_n= "ui_am_prop_radiation_protection", track= false, magnitude= 12000, unit= "st_msv", compare= false, sign= true, show_always= false },
|
|
["boost_telepat_protection"] = { index= 9, typ= "float", name= "ui_inv_outfit_telepatic_protection", icon_p= "ui_am_propery_11", icon_n= "ui_am_prop_telepat_protection", track= false, magnitude= 1500, unit= "st_mt", compare= false, sign= true, show_always= false },
|
|
["boost_chemburn_protection"] = { index= 10, typ= "float", name= "ui_inv_outfit_chemical_burn_protection", icon_p= "ui_am_prop_chem", icon_n= "ui_am_prop_chemburn_protection", track= false, magnitude= 24750, unit= "st_perc", compare= false, sign= true, show_always= false },
|
|
["boost_burn_immunity"] = { index= 11, typ= "float", name= "ui_inv_outfit_burn_protection", icon_p= "ui_am_prop_thermo", icon_n= "ui_am_prop_burn_immunity", track= false, magnitude= 300, unit= "st_kw_m2", compare= false, sign= true, show_always= false },
|
|
["boost_shock_immunity"] = { index= 12, typ= "float", name= "ui_inv_outfit_shock_protection", icon_p= "ui_am_prop_electro", icon_n= "ui_am_prop_shock_immunity", track= false, magnitude= 480, unit= "st_v", compare= false, sign= true, show_always= false },
|
|
["boost_radiation_immunity"] = { index= 13, typ= "float", name= "ui_inv_outfit_radiation_protection", icon_p= "ui_am_propery_09", icon_n= "ui_am_prop_radiation_immunity", track= false, magnitude= 3000, unit= "st_msv", compare= false, sign= true, show_always= false },
|
|
["boost_telepat_immunity"] = { index= 14, typ= "float", name= "ui_inv_outfit_telepatic_protection", icon_p= "ui_am_propery_11", icon_n= "ui_am_prop_telepat_immunity", track= false, magnitude= 300, unit= "st_mt", compare= false, sign= true, show_always= false },
|
|
["boost_chemburn_immunity"] = { index= 15, typ= "float", name= "ui_inv_outfit_chemical_burn_protection", icon_p= "ui_am_prop_chem", icon_n= "ui_am_prop_chemburn_immunity", track= false, magnitude= 380000, unit= "st_perc", compare= false, sign= true, show_always= false },
|
|
["boost_max_weight"] = { index= 16, typ= "float", name= "ui_inv_outfit_additional_weight", icon_p= "ui_am_propery_08", icon_n= "ui_am_prop_max_weight", track= false, magnitude= 1000, unit= "st_g", compare= false, sign= true, show_always= false },
|
|
}
|
|
end
|
|
|
|
function add_stats_table(k1,k2,v)
|
|
if is_not_empty(stats_table) then return end
|
|
|
|
if (not stats_table[k1]) then
|
|
stats_table[k1] = {}
|
|
end
|
|
|
|
stats_table[k1][k2] = v
|
|
end
|
|
|
|
function get_stats_table(sec)
|
|
prepare_stats_table()
|
|
|
|
if ini_sys:r_string_ex(sec, "ammo_class") and (not IsItem("fake_ammo_wpn", sec)) then
|
|
return stats_table["weapon"]
|
|
elseif IsItem("outfit", sec) or IsItem("helmet", sec) then
|
|
return stats_table["outfit"]
|
|
elseif IsItem("artefact", sec) then
|
|
return stats_table["artefact"]
|
|
elseif IsItem("consumable", sec) then
|
|
return stats_table["booster"]
|
|
elseif IsItem("backpack", sec) then
|
|
return stats_table["backpack"]
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function get_stats_value(obj, sec, gr, stat)
|
|
prepare_stats_table()
|
|
|
|
if type(gr) == "string" then
|
|
gr = stats_table[gr]
|
|
end
|
|
if (not gr) then
|
|
return
|
|
end
|
|
|
|
local sect = gr.section and SYS_GetParam(0, sec, gr.section) or sec
|
|
|
|
local value = gr.value_functor and get_stats_func_value(obj, sec, unpack(gr.value_functor))
|
|
if (not value) then
|
|
value = utils_item.get_param(sect, obj and obj:id(), stat, (gr.typ or "float"), true)
|
|
end
|
|
|
|
if obj and value and gr.condition then
|
|
value = value * obj:condition()
|
|
end
|
|
|
|
return (value ~= 0) and value
|
|
end
|
|
|
|
function get_stats_func_value(obj, sec, file, func, ...)
|
|
if file and func and _G[file] and _G[file][func] then
|
|
return _G[file][func](obj,sec,...)
|
|
end
|
|
end
|
|
|
|
function get_stats_string_value(obj, sec, gr, stat, to_text)
|
|
if type(gr) == "string" then
|
|
gr = stats_table[gr]
|
|
end
|
|
if (not gr) then
|
|
return
|
|
end
|
|
|
|
local value = get_stats_value(obj, sec, gr, stat)
|
|
if (not value) then
|
|
return
|
|
end
|
|
|
|
if gr.track then
|
|
local valbar = clamp((math.abs(value) * gr.magnitude), 0, 1)
|
|
return to_text and (math.ceil(valbar * 100) .. "%") or valbar
|
|
else
|
|
local valbar = value * gr.magnitude
|
|
local unit = gr.unit and gr.unit ~= "" and game.translate_string(gr.unit) or ""
|
|
local clr = valbar >= 0 and clr_list["p1"] or clr_list["n1"]
|
|
valbar = math.ceil(valbar)
|
|
|
|
if gr.sign_inverse then
|
|
clr = valbar < 0 and clr_list["p1"] or clr_list["n1"]
|
|
end
|
|
local sign = gr.sign and valbar > 0 and "+" or ""
|
|
|
|
if gr.sign_inverse_txt then
|
|
if valbar > 0 then
|
|
sign = "-"
|
|
elseif valbar < 0 then
|
|
valbar = -1 * valbar
|
|
sign = "+"
|
|
end
|
|
end
|
|
|
|
return ( sign .. valbar .. " " .. unit ), (clr == clr_list["n1"] and true or false)
|
|
end
|
|
end
|
|
|
|
function get_stats_xml(handler, obj, sec, gr, stat)
|
|
if type(gr) == "string" then
|
|
gr = stats_table[gr]
|
|
end
|
|
if (not gr) then
|
|
return
|
|
end
|
|
|
|
local value, nclr = get_stats_string_value(obj, sec, gr, stat)
|
|
if (not value) then
|
|
return
|
|
end
|
|
|
|
local st = XMLP:InitStatic("item_info:stats_box", handler)
|
|
|
|
-- Set up icon
|
|
local st_icon = XMLP:InitStatic("item_info:stats_box:icon", st)
|
|
local icon_p = gr.icon_p
|
|
local icon_n = (gr.icon_n ~= "") and gr.icon_n or icon_p
|
|
local icon = icon_p
|
|
if (type(value) == "number") then
|
|
icon = value < 0 and icon_n or icon_p
|
|
if gr.sign_inverse then
|
|
icon = value < 0 and icon_p or icon_n
|
|
end
|
|
end
|
|
st_icon:InitTexture( icon )
|
|
|
|
-- Set up name
|
|
local st_cap = XMLP:InitTextWnd("item_info:stats_box:cap", st)
|
|
st_cap:SetText( game.translate_string(gr.name) )
|
|
|
|
-- Set up bar
|
|
if gr.track then
|
|
local st_bar = XMLP:InitProgressBar("item_info:stats_box:prog_bar", st)
|
|
st_bar:SetProgressPos( clamp(value,0,1) )
|
|
st_bar:SetColor( clr_list["info_def"] )
|
|
|
|
-- Set up text
|
|
else
|
|
local st_txt = XMLP:InitTextWnd("item_info:stats_box:prog_txt", st)
|
|
st_txt:SetText( value )
|
|
st_txt:SetTextColor( nclr and clr_list["n1"] or clr_list["p1"] )
|
|
end
|
|
|
|
st:SetAutoDelete(true)
|
|
|
|
return st
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------
|
|
-- Item Cell
|
|
-------------------------------------------------------------------
|
|
class "UICellItem"
|
|
|
|
function UICellItem:__init(container, st, indx, manual)
|
|
|
|
-- To define free item cell:
|
|
-- UICellItem( { path= <string> , xml= <xml_file> , grid_size= <number>, grid_line= <number> } , { path= <string>, base= <xml_element>} )
|
|
|
|
self.manual = manual -- manual placement on container, some properties are disabled
|
|
self.container = container
|
|
self.path = container.path
|
|
self.indx = indx
|
|
self.showcase = 0 -- [0] attached to object / [1] attached to section (showcase) / [2] same as 1 with no cell room adjust
|
|
self.cx = manual and ("cell_" .. indx) or "cell" -- in manual placement, cells are specified by their index in xml file
|
|
|
|
self.grid_size = container.grid_size or 41
|
|
self.grid_line = container.grid_line or 0
|
|
|
|
self.flags = {} -- you can pass custom info here
|
|
self.disable_bar = container.disable_bar and true or false
|
|
|
|
self:InitControls(self.path, st)
|
|
|
|
self:Print(nil, "__init for path (%s)", self.path)
|
|
end
|
|
|
|
function UICellItem:InitControls(path, st)
|
|
local xml = self:GetXML()
|
|
|
|
-- Free cell
|
|
local free_cell = (type(st) == "table")
|
|
if free_cell then
|
|
st = self.container.xml:InitStatic(st.path, st.base)
|
|
self.st = st
|
|
end
|
|
|
|
self.hl = xml:InitStatic(path .. ":" .. self.cx .. ":highlight", st)
|
|
self.cell = xml:InitStatic(path .. ":" .. self.cx, st)
|
|
self.shadow = xml:InitStatic(path .. ":" .. self.cx .. ":pic", self.cell)
|
|
self.ico = xml:InitStatic(path .. ":" .. self.cx .. ":pic", self.cell)
|
|
|
|
|
|
-- Highlight texture
|
|
--self.hl:InitTexture("ui_button_inv_h")
|
|
self.hl:SetStretchTexture(true)
|
|
self.hl:Show(false)
|
|
sync_element(self.hl, self.cell)
|
|
end
|
|
|
|
function UICellItem:Set(obj, area)
|
|
local xml = self:GetXML()
|
|
local path = self.path
|
|
local is_obj = (self.showcase == 0)
|
|
local grid_size = self.grid_size
|
|
|
|
local sec = is_obj and obj:section() or obj
|
|
local clsid = is_obj and obj:clsid()
|
|
|
|
local x = SYS_GetParam(2,sec, "inv_grid_x")
|
|
local y = SYS_GetParam(2,sec, "inv_grid_y")
|
|
local w = SYS_GetParam(2,sec, "inv_grid_width")
|
|
local h = SYS_GetParam(2,sec, "inv_grid_height")
|
|
|
|
if not x or not y or not w or not h then
|
|
return false
|
|
end
|
|
|
|
x = x * grid_size
|
|
y = y * grid_size
|
|
w = w * grid_size
|
|
h = h * grid_size
|
|
|
|
self.ID = is_obj and obj:id() or nil
|
|
self.section = sec
|
|
self.area = area
|
|
--self.X = x
|
|
--self.Y = y
|
|
self.W = w
|
|
self.H = h
|
|
|
|
-- Trade mode
|
|
--if self:Check_TradeMode(obj, sec) then
|
|
--return false
|
|
--end
|
|
|
|
-- Cell pos
|
|
if area and (not self.manual) then
|
|
local area_x = ((area.x * grid_size) - grid_size) * ratio
|
|
local area_y = (area.y * grid_size) - grid_size
|
|
-- Edited by Sota
|
|
--local area_xl = self.grid_line * area.x
|
|
local area_xl = self.grid_line * area.x * ratio
|
|
|
|
local area_yl = self.grid_line * area.y
|
|
|
|
self.cell:SetWndPos(vector2():set( area_x + area_xl , area_y + area_yl ))
|
|
self.cell:SetWndSize(vector2():set(w * ratio , h))
|
|
sync_element(self.hl, self.cell)
|
|
self:Print(nil, "Set for [%s] in (%s,%s,%s,%s)", sec, area_x, area_y, w, h)
|
|
|
|
-- Cell pos (free cell)
|
|
elseif self.st then
|
|
local st_x = ((self.st:GetWidth() /2) - ((w * ratio) /2))
|
|
local st_y = ((self.st:GetHeight() /2) - (h /2))
|
|
self.cell:SetWndPos(vector2():set( st_x , st_y ))
|
|
self.cell:SetWndSize(vector2():set(w * ratio , h))
|
|
sync_element(self.hl, self.cell)
|
|
self:Print(nil, "Set for [%s] in free cell", sec)
|
|
end
|
|
|
|
-- Icon
|
|
self:Add_Icon(sec, w, h)
|
|
self:Add_Shadow(sec, w, h)
|
|
|
|
-- Icon layers
|
|
self:Add_Layers(xml, obj, sec, clsid)
|
|
|
|
-- Update cell
|
|
local is_updated = self:Update(is_obj and obj)
|
|
if (not is_updated) then
|
|
self:Print(nil, "Updating failed for [%s] | Reset cell", sec)
|
|
self:Reset()
|
|
return false
|
|
end
|
|
|
|
self.cell:Show(true)
|
|
return true
|
|
end
|
|
|
|
function UICellItem:Update(obj)
|
|
obj = obj or (self.ID and level.object_by_id(self.ID))
|
|
if (self.showcase == 0) and (not obj) then
|
|
self:ResetToChild()
|
|
return false
|
|
end
|
|
self:Print(nil, "Update for [%s]", sec)
|
|
|
|
local sec = self.section
|
|
local xml = self:GetXML()
|
|
|
|
if obj then
|
|
local clsid = obj:clsid()
|
|
|
|
-- Update condition bar
|
|
self:Add_ProgressBar(xml, obj, sec, clsid)
|
|
|
|
-- Update attachments
|
|
self:Add_Attachements(xml, obj, sec, clsid)
|
|
end
|
|
|
|
-- Update stack counter
|
|
self:Add_Counter(xml, obj, sec)
|
|
|
|
-- Update upgrade indicator
|
|
self:Add_Upgrade(xml, obj, sec)
|
|
|
|
-- Update trade mode
|
|
if self:Check_TradeMode(obj, sec) then
|
|
return false
|
|
end
|
|
|
|
-- Update color
|
|
self:Colorize( self.flags.no_trade and "red" or "def" )
|
|
|
|
return true
|
|
end
|
|
|
|
function UICellItem:Add_Icon(sec, w, h)
|
|
local rot = self.ico:GetHeading() > 0
|
|
|
|
self.ico:InitTexture( utils_xml.get_icons_texture(sec) )
|
|
self.ico:SetTextureRect(Frect():set( get_item_axis(sec, nil, true) ))
|
|
self.ico:SetStretchTexture(true)
|
|
self.ico:SetWndSize(vector2():set( w * (rot and 1 or ratio) , h * (rot and ratio or 1) ))
|
|
self.ico:Show(true)
|
|
utils_xml.align_to_center(self.ico, self.cell)
|
|
|
|
self:Print(nil, "Show icon")
|
|
end
|
|
|
|
function UICellItem:Add_Shadow(sec, w, h)
|
|
local rot = self.shadow:GetHeading() > 0
|
|
|
|
self.shadow:InitTexture( utils_xml.get_icons_texture(sec) )
|
|
self.shadow:SetTextureRect(Frect():set( get_item_axis(sec, nil, true) ))
|
|
self.shadow:SetStretchTexture(true)
|
|
self.shadow:SetWndSize(vector2():set( w * (rot and 1 or ratio) , h * (rot and ratio or 1) ))
|
|
self.shadow:Show(true)
|
|
self.shadow:Show(true)
|
|
utils_xml.align_to_center(self.shadow, self.cell)
|
|
|
|
local pos = self.ico:GetWndPos()
|
|
self.shadow:SetWndPos( vector2():set( pos.x + 1 , pos.y + 2 ) )
|
|
self.shadow:SetTextureColor( clr_list["shadow"] )
|
|
|
|
self:Print(nil, "Show shadow")
|
|
end
|
|
|
|
function UICellItem:Add_Layers(xml, obj, sec, clsid)
|
|
|
|
-- Hide all layers
|
|
if self.layer then
|
|
for i=1,#self.layer do
|
|
self.layer[i]:Show(false)
|
|
end
|
|
end
|
|
|
|
-- Add all possible layers
|
|
local ii = 0
|
|
while (SYS_GetParam(0, sec, (ii+1).."icon_layer") ~= nil) do
|
|
ii = ii + 1
|
|
|
|
if (not self.layer) then
|
|
self.layer = {}
|
|
end
|
|
if (not self.layer[ii]) then
|
|
if (not xml) then
|
|
xml = self:GetXML()
|
|
end
|
|
self.layer[ii] = xml:InitStatic(self.path .. ":" .. self.cx .. ":pic", self.ico)
|
|
end
|
|
|
|
local icon_layer = SYS_GetParam(0, sec, ii.."icon_layer")
|
|
self:Create_Layer(self.layer[ii], self.ico, sec, icon_layer, ii.."icon_layer_x", ii.."icon_layer_y", ii.."icon_layer_scale")
|
|
|
|
self:Print(nil, "Show layer (%s) [%s]", ii, icon_layer)
|
|
end
|
|
end
|
|
|
|
function UICellItem:Add_ProgressBar(xml, obj, sec, clsid)
|
|
|
|
-- Hide all bars
|
|
if self.bar then
|
|
self.bar:Show(false)
|
|
end
|
|
|
|
-- On full stacking, hide bar
|
|
if self.container.stack_all and (self.childs and is_not_empty(self.childs)) then
|
|
return
|
|
end
|
|
|
|
-- No bar on showcase cells
|
|
if (self.showcase ~= 0) or self.disable_bar then
|
|
return
|
|
end
|
|
|
|
-- Bar is applied only to classes that support conditon
|
|
local has_cond = SYS_GetParam(1,sec, "use_condition") or IsWeapon(nil,clsid) or IsOutfit(nil,clsid) or IsHeadgear(nil,clsid)
|
|
if (not has_cond) then
|
|
return
|
|
end
|
|
|
|
-- Get bar type
|
|
local str = SYS_GetParam(0,sec, "condition_bar","condition_progess_bar")
|
|
|
|
-- Init if it doesn't exist
|
|
if (not self.bar) then
|
|
if (not xml) then
|
|
xml = self:GetXML()
|
|
end
|
|
self.bar = xml:InitProgressBar(self.path .. ":" .. self.cx .. ":bar", self.cell)
|
|
--self.bar:UseColor( true )
|
|
end
|
|
|
|
-- Not manual -> bar is set at the left-bottom corner
|
|
if (not self.manual) then
|
|
local h_bar = self.bar:GetHeight()
|
|
self.bar:SetWndPos(vector2():set( 0 , (self.H - h_bar)))
|
|
end
|
|
|
|
-- Set progress
|
|
local cond = obj:condition()
|
|
if IsItem("multiuse",sec) then
|
|
cond = (obj:get_remaining_uses()/10)
|
|
else
|
|
cond = round_idp(cond,1)
|
|
end
|
|
self.bar:SetProgressPos( clamp(cond,0,1) )
|
|
|
|
-- Bar properties
|
|
local props = bar_list[str]
|
|
local color = props.def or lerp_color( cond , props.min , props.mid , props.max )
|
|
if color then
|
|
self.bar:SetColor( color )
|
|
end
|
|
|
|
self.bar:ShowBackground( props.background )
|
|
self.bar:Show(true)
|
|
|
|
self:Print(nil, "Show progress bar: %s - cond: %s", str, cond)
|
|
end
|
|
|
|
function UICellItem:Add_Counter(xml, obj, sec)
|
|
|
|
-- Hide counter
|
|
if self.cnt then
|
|
self.cnt:Show(false)
|
|
end
|
|
|
|
-- We don't need counter for showcase icons
|
|
if (self.showcase ~= 0) then
|
|
return
|
|
end
|
|
|
|
-- Bar is applied only to ammo or stacked items
|
|
local is_ammo = IsItem("ammo",sec) and (not IsItem("grenade_ammo",sec))
|
|
local has_childs = self:HasChild()
|
|
if not (is_ammo or has_childs) then
|
|
return
|
|
end
|
|
|
|
-- Init if it doesn't exist
|
|
if (not self.cnt) then
|
|
if (not xml) then
|
|
xml = self:GetXML()
|
|
end
|
|
self.cnt = xml:InitStatic(self.path .. ":" .. self.cx .. ":cnt", self.cell)
|
|
end
|
|
|
|
-- Ammo count
|
|
if is_ammo then
|
|
local cnt = 0
|
|
if self.childs then
|
|
for id,c in pairs(self.childs) do
|
|
cnt = cnt + c
|
|
end
|
|
end
|
|
local ammo_cnt = ((self.showcase ~= 0) and IsItem("ammo",sec)) or (obj and obj:ammo_get_count()) or 0
|
|
self.cnt:TextControl():SetText("x" .. (ammo_cnt + cnt) )
|
|
self.cnt:Show(true)
|
|
|
|
-- Stacked items
|
|
elseif has_childs then
|
|
self.cnt:TextControl():SetText("x" .. (size_table(self.childs) + 1) )
|
|
self.cnt:Show(true)
|
|
end
|
|
|
|
self:Print(nil, "Show counter | ammo: %s - stacked: %s", is_ammo, has_childs)
|
|
end
|
|
|
|
function UICellItem:Add_Upgrade(xml, obj, sec)
|
|
|
|
-- Hide upgrade indicator
|
|
if self.upgr then
|
|
self.upgr:Show(false)
|
|
end
|
|
|
|
-- On full stacking, hide upgrade indicator
|
|
if self.container.stack_all and (self.childs and is_not_empty(self.childs)) then
|
|
return
|
|
end
|
|
|
|
-- Bar is applied only to upgraded items
|
|
if (not has_upgrades(obj, sec)) then
|
|
return
|
|
end
|
|
|
|
-- Init if it doesn't exist
|
|
if (not self.upgr) then
|
|
if (not xml) then
|
|
xml = self:GetXML()
|
|
end
|
|
self.upgr = xml:InitStatic(self.path .. ":cell:upgrade", self.ico)
|
|
end
|
|
|
|
-- Positioning
|
|
local ico = self.ico
|
|
local xx = 1
|
|
local yy = 1
|
|
local rot = ico:GetHeading() > 0
|
|
if rot then
|
|
local w_b, h_b = ico:GetWidth(), ico:GetHeight()
|
|
local x_st = (w_b/2) - (h_b/2)
|
|
local y_st = h_b + x_st
|
|
xx = xx + x_st
|
|
yy = yy + (y_st - w_b)
|
|
end
|
|
|
|
self.upgr:SetWndPos(vector2():set( xx , yy ))
|
|
self.upgr:Show(true)
|
|
|
|
self:Print(nil, "Show upgrade indicator")
|
|
end
|
|
|
|
function UICellItem:Add_Attachements(xml, obj, sec, clsid)
|
|
|
|
-- Hide attachments
|
|
if self.ico_scope then self.ico_scope:Show(false) end
|
|
if self.ico_sil then self.ico_sil:Show(false) end
|
|
if self.ico_gl then self.ico_gl:Show(false) end
|
|
|
|
-- On full stacking, hide counter
|
|
if self.container.stack_all and (self.childs and is_not_empty(self.childs)) then
|
|
return
|
|
end
|
|
|
|
-- No attachments on showcase cells
|
|
if (self.showcase ~= 0) then
|
|
return
|
|
end
|
|
|
|
-- No attachments for non-firearms
|
|
local magazined_wpn = IsWeapon(nil,clsid) and (not IsItem("fake_ammo_wpn",sec))
|
|
if (not magazined_wpn) then
|
|
return
|
|
end
|
|
|
|
-- Scope
|
|
local scope = (not utils_item.has_scope(sec)) and utils_item.get_attached_scope(obj)
|
|
if scope then
|
|
if (not self.ico_scope) then
|
|
if (not xml) then
|
|
xml = self:GetXML()
|
|
end
|
|
self.ico_scope = xml:InitStatic(self.path .. ":" .. self.cx .. ":pic", self.ico)
|
|
end
|
|
local scopes_sect = utils_item.get_param(sec, obj:id(), "scopes_sect", "string", false)
|
|
self:Create_Layer(self.ico_scope, self.ico, scopes_sect, scope, "scope_x", "scope_y")
|
|
self:Print(nil, "Show scope")
|
|
end
|
|
|
|
-- Silencer
|
|
local sil = utils_item.get_attached_silencer(obj)
|
|
if sil then
|
|
if (not self.ico_sil) then
|
|
if (not xml) then
|
|
xml = self:GetXML()
|
|
end
|
|
self.ico_sil = xml:InitStatic(self.path .. ":" .. self.cx .. ":pic", self.ico)
|
|
end
|
|
self:Create_Layer(self.ico_sil, self.ico, sec, sil, "silencer_x", "silencer_y")
|
|
self:Print(nil, "Show silencer")
|
|
end
|
|
|
|
-- Grenade Launcher
|
|
local gl = utils_item.get_attached_gl(obj)
|
|
if gl then
|
|
if (not self.ico_gl) then
|
|
if (not xml) then
|
|
xml = self:GetXML()
|
|
end
|
|
self.ico_gl = xml:InitStatic(self.path .. ":" .. self.cx .. ":pic", self.ico)
|
|
end
|
|
self:Create_Layer(self.ico_gl, self.ico, sec, gl, "grenade_launcher_x", "grenade_launcher_y")
|
|
self:Print(nil, "Show grenade launcher")
|
|
end
|
|
end
|
|
|
|
function UICellItem:Add_CustomText(txt, align_h, align_v, clr, fnt)
|
|
if self.ctxt then
|
|
self.ctxt:Show(false)
|
|
self.ctxts:Show(false)
|
|
end
|
|
|
|
if (not txt) then
|
|
return
|
|
end
|
|
|
|
if (not self.ctxt) then
|
|
local xml = self:GetXML()
|
|
self.ctxts = xml:InitTextWnd(self.path .. ":" .. self.cx .. ":ctxt", self.cell)
|
|
self.ctxt = xml:InitTextWnd(self.path .. ":" .. self.cx .. ":ctxt", self.cell)
|
|
self.ctxts:SetTextColor(clr_list["black"])
|
|
end
|
|
|
|
utils_xml.sync_size(self.cell, self.ctxt)
|
|
utils_xml.sync_size(self.ctxt, self.ctxts)
|
|
|
|
local pos = self.ctxt:GetWndPos()
|
|
self.ctxts:SetWndPos(vector2():set( pos.x+1 , pos.y+1 ))
|
|
|
|
self.ctxt:SetText(txt)
|
|
self.ctxts:SetText(txt)
|
|
|
|
if align_h then -- [2] center / [4] right
|
|
self.ctxt:SetTextAlignment(align_h)
|
|
self.ctxts:SetTextAlignment(align_h)
|
|
end
|
|
if align_v then
|
|
self.ctxt:SetVTextAlignment(align_v)
|
|
self.ctxts:SetVTextAlignment(align_v)
|
|
end
|
|
|
|
if fnt then
|
|
self.ctxt:SetFont(fnt)
|
|
self.ctxts:SetFont(fnt)
|
|
end
|
|
|
|
self.ctxt:SetTextColor(clr or clr_list["def"])
|
|
|
|
self.ctxt:Show(true)
|
|
self.ctxts:Show(true)
|
|
|
|
self:Print(nil, "Show custom text | txt: %s", txt)
|
|
end
|
|
|
|
function UICellItem:Create_Layer(ele, base, sec_m, sec_l, str_x, str_y, str_scale)
|
|
local grid_size = self.grid_size
|
|
local x = str_x and SYS_GetParam(2,sec_m, str_x) or 0
|
|
local y = str_y and SYS_GetParam(2,sec_m, str_y) or 0
|
|
local w = SYS_GetParam(2,sec_l, "inv_grid_width",1) * grid_size
|
|
local h = SYS_GetParam(2,sec_l, "inv_grid_height",1) * grid_size
|
|
local scale = str_scale and SYS_GetParam(2,sec_m, str_scale) or 1
|
|
local scale_pos = scale * (grid_size/50)
|
|
|
|
local rot = ele:GetHeading() > 0
|
|
local x_s = x * ratio * scale_pos
|
|
local y_s = y * scale_pos
|
|
local w_s = w * ratio * scale
|
|
local h_s = h * scale
|
|
local w_off = (w_s/2)
|
|
local h_off = (h_s/2)
|
|
|
|
if rot then
|
|
-- despite rotation, movement for x and y stays normal!
|
|
-- Move start pos to match the one for rotated base icon
|
|
local w_b, h_b = base:GetWidth(), base:GetHeight()
|
|
local x_st = (w_b/2) - (h_b/2)
|
|
local y_st = h_b + x_st
|
|
|
|
-- On 90 rotation, x and y are inverted, y axis goes negative simulate normal x movement
|
|
x_s = x_st + (y * ratio * scale_pos)
|
|
y_s = y_st - (x * scale_pos)
|
|
w_s = w * scale
|
|
h_s = h * ratio * scale
|
|
w_off = (h_s * (1/ratio))/2
|
|
h_off = -w_s/2
|
|
end
|
|
|
|
ele:InitTexture( utils_xml.get_icons_texture(sec_l) )
|
|
ele:SetTextureRect(Frect():set( get_item_axis(sec_l, nil, true) ))
|
|
ele:SetStretchTexture(true)
|
|
ele:SetWndPos(vector2():set( x_s + w_off , y_s + h_off ))
|
|
ele:SetWndSize(vector2():set( w_s , h_s ))
|
|
ele:Show(true)
|
|
end
|
|
|
|
function UICellItem:Colorize(clr_id)
|
|
self:Print(nil, "Colorize [%s]", clr_id)
|
|
|
|
local clr = clr_list[clr_id]
|
|
if self.ico then self.ico:SetTextureColor( clr ) end
|
|
if self.ico_scope then self.ico_scope:SetTextureColor( clr ) end
|
|
if self.ico_sil then self.ico_sil:SetTextureColor( clr ) end
|
|
if self.ico_gl then self.ico_gl:SetTextureColor( clr ) end
|
|
if self.layer then
|
|
for i=1,#self.layer do
|
|
self.layer[i]:SetTextureColor( clr )
|
|
end
|
|
end
|
|
|
|
if self.shadow then
|
|
self.shadow:SetTextureColor( (clr_id == "hide") and clr_list["hide_shadow"] or clr_list["shadow"] )
|
|
end
|
|
end
|
|
|
|
function UICellItem:Highlight(state, clr_id, main_clr)
|
|
if state and (not self:IsShown()) and (not self.manual) then
|
|
return
|
|
end
|
|
|
|
self.hl:Show(state)
|
|
if (not state) then
|
|
return
|
|
end
|
|
|
|
if main_clr then
|
|
self.hl:SetTextureColor( clr_id and clr_list[clr_id] or clr_list["def"] )
|
|
else
|
|
self.hl:SetTextureColor( clr_id and clr_list_hl[clr_id] or clr_list_hl["def"] )
|
|
end
|
|
end
|
|
|
|
function UICellItem:Check_TradeMode(obj, sec)
|
|
|
|
if (self.showcase ~= 0) then
|
|
return false
|
|
end
|
|
|
|
-- Reset
|
|
self.flags.value = nil
|
|
self.flags.value_str = nil
|
|
self.flags.note = nil
|
|
self.flags.no_trade = nil
|
|
self.flags.note_str = nil
|
|
|
|
local profile = self.container.trade_profile
|
|
if not (profile and profile.mode) then
|
|
return false
|
|
end
|
|
|
|
local status = get_item_trade_status(obj, profile)
|
|
if status == 4 then
|
|
local cost = get_item_cost(obj, profile)
|
|
self.flags.value = math.floor(cost)
|
|
self.flags.value_str = (game.translate_string("st_base_cost") .. ": " .. math.floor(cost) .. " RU")
|
|
|
|
elseif status == 3 or (not status) then
|
|
self:Print(nil, "Removed [%s] for NPC. Not proper item", sec)
|
|
return true
|
|
|
|
elseif status == 1 or status == 2 then
|
|
self.flags.note = status
|
|
self.flags.no_trade = true
|
|
self.flags.note_str = game.translate_string("st_no_trade_tip_" .. status)
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function UICellItem:GetCost()
|
|
|
|
end
|
|
|
|
function UICellItem:AddChild(obj)
|
|
-- no need for childs in manual cells
|
|
if self.manual then
|
|
return false
|
|
end
|
|
|
|
if (not self.childs) then
|
|
self.childs = {}
|
|
end
|
|
|
|
-- Real
|
|
local sec = obj:section()
|
|
if (self.showcase == 0) then
|
|
local id = obj:id()
|
|
if (id ~= self.ID) then
|
|
|
|
-- Trade mode for child
|
|
local profile = self.container.trade_profile
|
|
if (profile and profile.mode == 2) then
|
|
local status = get_item_trade_status(obj, profile)
|
|
if (status == 3) then
|
|
self:Print(nil, "AddChild [%s] | not tradable by NPC!", obj:name())
|
|
return false
|
|
end
|
|
end
|
|
|
|
self.childs[id] = IsAmmo(obj) and obj:ammo_get_count() or 1
|
|
|
|
self:Update()
|
|
|
|
return true
|
|
end
|
|
return false
|
|
|
|
-- Dummy
|
|
else
|
|
table.insert(self.childs, IsItem("ammo",sec) or 1)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function UICellItem:PopChild(obj, id)
|
|
if self.childs then
|
|
|
|
-- Real
|
|
if (self.showcase == 0) then
|
|
self.childs[ obj and obj:id() or id ] = nil
|
|
self:Update()
|
|
|
|
-- Dummy
|
|
elseif #self.childs > 0 then
|
|
self.childs[ #self.childs ] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellItem:HasChild(obj, id)
|
|
if obj or id then
|
|
return self.childs and self.childs[ obj and obj:id() or id ]
|
|
end
|
|
return self.childs and is_not_empty(self.childs)
|
|
end
|
|
|
|
function UICellItem:CountChilds()
|
|
return self.childs and table_size(self.childs) or 0
|
|
end
|
|
|
|
function UICellItem:ResetToChild()
|
|
local id_child
|
|
if self.childs then
|
|
for id,cnt in pairs(self.childs) do
|
|
id_child = id
|
|
break
|
|
end
|
|
end
|
|
|
|
if id_child then
|
|
|
|
-- Real
|
|
if (self.showcase == 0) then
|
|
local obj = level.object_by_id(id_child)
|
|
self.childs[id_child] = nil
|
|
|
|
self.ID = id_child
|
|
self.section = obj and obj:section()
|
|
self:Update(obj)
|
|
|
|
-- Dummy
|
|
else
|
|
self.childs[id_child] = nil
|
|
self:Update()
|
|
end
|
|
|
|
return false
|
|
else
|
|
self:Reset()
|
|
return true
|
|
end
|
|
end
|
|
|
|
function UICellItem:Reset()
|
|
self.ID = nil
|
|
self.section = nil
|
|
if self.childs then
|
|
empty_table(self.childs)
|
|
end
|
|
|
|
empty_table(self.flags)
|
|
|
|
self:Highlight(false)
|
|
if (self.manual) then
|
|
self.ico:Show(false)
|
|
self.shadow:Show(false)
|
|
if self.bar then self.bar:Show(false) end
|
|
if self.cnt then self.cnt:Show(false) end
|
|
if self.upgr then self.upgr:Show(false) end
|
|
if self.ctxt then self.ctxt:Show(false) end
|
|
if self.ctxts then self.ctxts:Show(false) end
|
|
else
|
|
if (self.showcase ~= 2) and self.container["FreeRoom"] then
|
|
-- Freeing cell area
|
|
local a = self.area
|
|
self.container:FreeRoom(a.y, a.x, a.w, a.h)
|
|
end
|
|
|
|
self:Show(false)
|
|
end
|
|
end
|
|
|
|
function UICellItem:Show(state, obj)
|
|
if state then
|
|
self:Update(obj)
|
|
end
|
|
self.cell:Show(state)
|
|
end
|
|
|
|
function UICellItem:IsShown()
|
|
if self.manual then
|
|
return self.ico:IsShown()
|
|
end
|
|
return self.cell:IsShown()
|
|
end
|
|
|
|
function UICellItem:IsCursorOverWindow()
|
|
return self.cell:IsCursorOverWindow()
|
|
end
|
|
|
|
function UICellItem:GetXML()
|
|
return self.manual and self.container.xml or XMLP
|
|
end
|
|
|
|
function UICellItem:Print(mark, fmt,...)
|
|
--printf( (mark or "=") .. " UICellItem [%s] | " .. fmt, self.section, ...)
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------
|
|
-- Container for item cells
|
|
-------------------------------------------------------------------
|
|
class "UICellContainer"
|
|
|
|
function UICellContainer:__init(id, owner, path, prof, ele_base, manual, use_frame)
|
|
self.ID = id -- unique id for class instance, so we can deal with many instances outside
|
|
self.owner = owner
|
|
self.path = path or "container"
|
|
self.xml = manual and owner.xml or XMLP
|
|
|
|
-- Item cells
|
|
self.grid_size = 41
|
|
self.grid_line = 2
|
|
self.grid = {} -- [row][col] = bool ( true = unoccupied , false = occupied )
|
|
self.cell = {}
|
|
self.line = {}
|
|
self.line_cnt = 0
|
|
self.indx_id = {} --[id] = idx
|
|
self.indx_sec = {} --[sec][id] = idx
|
|
self.idxer = 0
|
|
self.row_end = 0
|
|
self.col_end = 0
|
|
self.scroll_pos = 0
|
|
self.cell_vis_offset = 20 --[px]
|
|
self.rKind = { last = false , current = false , row = 1 }
|
|
|
|
-- Properties
|
|
self.sort_method = "sizekind"
|
|
self.showcase = false
|
|
self.manual = manual
|
|
self.can_select = false
|
|
self.stack_all = false
|
|
self.ignore_scroll = false
|
|
self.disable_scroll = manual
|
|
self.disable_scroll_dragdrop = false
|
|
self.disable_drag = false
|
|
self.disable_highlight = false
|
|
self.disable_info = false
|
|
self.disable_stack = false
|
|
self.disable_bar = false
|
|
self.disable_callback = {} --[name] = true
|
|
self.scolling_power_up = 3
|
|
|
|
-- Cell management
|
|
self.selected = nil
|
|
self.hover = { idx = false }
|
|
self.hold = { idx = false , ico = false , tg = 0 , w = 0 , h = 0 }
|
|
self.db = { idx = false , tg = 0 }
|
|
self.drag_area = { up = 0 , down = 0 , step = 200 }
|
|
self.pd = { update = false , off = 0 , start = 0 , hold = false , power = 1}
|
|
self.scolling_power = 1
|
|
self.use_frame = use_frame
|
|
|
|
self:InitControls(owner, prof, ele_base)
|
|
self:EnableScrolling(not manual)
|
|
|
|
self:Print(nil, "__init for path (%s)", path)
|
|
end
|
|
|
|
function UICellContainer:InitControls(owner, prof, ele_base)
|
|
local xml = self.xml
|
|
local path = self.path
|
|
|
|
if self.use_frame then
|
|
self.prof = owner.xml:InitFrame(prof, ele_base)
|
|
else
|
|
self.prof = owner.xml:InitStatic(prof, ele_base)
|
|
end
|
|
|
|
-- Drag up area
|
|
self.drag_up = xml:InitStatic(path .. ":st", self.prof)
|
|
self.drag_up:SetWndPos(vector2():set( 0 , 0 ))
|
|
self.drag_up:SetWndSize(vector2():set( self.prof:GetWidth() , self.grid_size ))
|
|
|
|
-- Drag down area
|
|
self.drag_down = xml:InitStatic(path .. ":st", self.prof)
|
|
self.drag_down:SetWndPos(vector2():set( 0 , self.prof:GetHeight() - self.grid_size ))
|
|
self.drag_down:SetWndSize(vector2():set( self.prof:GetWidth() , self.grid_size ))
|
|
|
|
self.scroll = xml:InitScrollView(path .. ":scroll", self.prof)
|
|
utils_xml.sync_size( self.prof , self.scroll)
|
|
|
|
self.st = xml:InitStatic(path .. ":st", nil)
|
|
utils_xml.sync_size( self.prof , self.st)
|
|
|
|
-- Scroll pad
|
|
self.pad = xml:InitStatic(path .. ":st", self.prof)
|
|
self.pad:InitTexture("ui_inGame2_white_rect")
|
|
self.pad:SetTextureColor( GetARGB(100,255,255,255) )
|
|
self.pad:SetWndPos(vector2():set( self.prof:GetWidth() , 0 ))
|
|
-- Edited by Sota
|
|
--self.pad:SetWndSize(vector2():set( 5 , self.prof:GetHeight() ))
|
|
self.pad:SetWndSize(vector2():set( 5 * uwide_ratio , self.prof:GetHeight() ))
|
|
|
|
self.pad:Show(false)
|
|
self:SetGridSpecs()
|
|
end
|
|
|
|
function UICellContainer:Reinit(t, tf)
|
|
|
|
self:Reset()
|
|
|
|
-- If no inventory is passed, this function will just clear cells
|
|
if (not t) then
|
|
return
|
|
end
|
|
|
|
-- Create cells
|
|
self.ignore_scroll = true
|
|
self:Print(nil, "Reset | START Number of cells: %s", #self.cell)
|
|
|
|
local sort_order = self:GetSortMethod()
|
|
if self.showcase then
|
|
for i,sec in spairs(t, sort_order) do
|
|
self:AddItem(nil,sec, tf and tf[i])
|
|
end
|
|
else
|
|
for i,obj in spairs(t, sort_order) do
|
|
self:AddItem(obj, nil, tf and tf[i])
|
|
end
|
|
end
|
|
|
|
self.ignore_scroll = false
|
|
self:Print(nil, "Reset | END Number of cells: %s", #self.cell)
|
|
|
|
self:Scroll_Reinit()
|
|
end
|
|
|
|
function UICellContainer:AddIndex(id, sec, indx)
|
|
self:Print(nil, "AddIndex | id: %s - sec: %s - indx: %s", id, sec, indx)
|
|
|
|
self.indx_id[id] = indx
|
|
if (not sec) then
|
|
return
|
|
end
|
|
|
|
if (not self.indx_sec[sec]) then
|
|
self.indx_sec[sec] = {}
|
|
end
|
|
self.indx_sec[sec][id] = indx
|
|
end
|
|
|
|
function UICellContainer:RemoveIndex(id, sec, indx)
|
|
self:Print(nil, "RemoveIndex | id: %s - sec: %s - indx: %s", id, sec, indx)
|
|
if (not id) then
|
|
return
|
|
end
|
|
|
|
-- Deselect
|
|
if (self.selected == self.indx_id[id]) then
|
|
self:On_Select(false)
|
|
end
|
|
|
|
self.indx_id[id] = nil
|
|
if (not sec) then
|
|
for s,t in pairs(self.indx_sec) do
|
|
if t[id] then
|
|
sec = s
|
|
break
|
|
end
|
|
end
|
|
if (not sec) then
|
|
return
|
|
end
|
|
end
|
|
|
|
if self.indx_sec[sec] then
|
|
self.indx_sec[sec][id] = nil
|
|
|
|
if is_empty(self.indx_sec[sec]) then
|
|
self.indx_sec[sec] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:GetCell_ID(id, only_indx)
|
|
local indx = self.indx_id[id]
|
|
if only_indx then
|
|
return indx
|
|
end
|
|
return indx and self.cell[indx]
|
|
end
|
|
|
|
function UICellContainer:GetCell_SEC(sec)
|
|
local indxes = self.indx_sec[sec]
|
|
if indxes then
|
|
for id,idx in pairs(indxes) do
|
|
self:Print(nil, "GetCell_SEC | sec: %s | found cell at index: %s", sec, idx)
|
|
return idx and self.cell[idx]
|
|
end
|
|
end
|
|
|
|
self:Print(nil, "GetCell_SEC | sec: %s | no cell found", sec)
|
|
return false
|
|
end
|
|
|
|
function UICellContainer:GetCell_Selected(only_obj)
|
|
if (not self.can_select) then
|
|
return
|
|
end
|
|
|
|
local ci = self.selected and self.cell[self.selected]
|
|
if only_obj and (not self.showcase) then
|
|
return ci and ci.ID and level.object_by_id(ci.ID)
|
|
end
|
|
return (not only_obj) and ci
|
|
end
|
|
|
|
function UICellContainer:GetCell_Focused(only_cell)
|
|
if self:IsShown() and self:IsCursorOverWindow() then
|
|
for idx, ci in pairs(self.cell) do
|
|
if (self.manual or ci:IsShown()) and ci:IsCursorOverWindow() then
|
|
if only_cell then
|
|
return ci
|
|
else
|
|
return self.ID, idx, self:GetObj(idx)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:GetObj(idx)
|
|
local ci = self.cell[idx]
|
|
return ci and ci.ID and level.object_by_id(ci.ID)
|
|
end
|
|
|
|
function UICellContainer:GetID(obj, sec, create)
|
|
local id = obj and obj:id()
|
|
if (not id) then
|
|
if (not self.showcase) then
|
|
return
|
|
end
|
|
id = create and (#self.indx_id + 1) or random_key_table(self.indx_sec[sec])
|
|
end
|
|
return id
|
|
end
|
|
|
|
function UICellContainer:AddItemInCell(obj, sec, indx, area)
|
|
if (not self.cell[indx]) then
|
|
self:Print(nil, "AddItemInCell | Creating new cell | obj: %s - index: %s", obj and obj:name(), indx)
|
|
self.cell[indx] = UICellItem(self, self.st, indx)
|
|
if self.showcase then
|
|
self.cell[indx].showcase = self.manual and 2 or 1
|
|
end
|
|
end
|
|
|
|
local set = self.cell[indx]:Set(obj or sec, area)
|
|
self:Print(nil, "AddItemInCell | Set in cell (%s) | obj: %s - index: %s", set, obj and obj:name(), indx)
|
|
|
|
self:Scroll_Reinit(true)
|
|
|
|
return set
|
|
end
|
|
|
|
function UICellContainer:AddItem(obj, sec, info)
|
|
if (not sec) then
|
|
if (not obj) then
|
|
return
|
|
end
|
|
sec = obj and obj:section()
|
|
end
|
|
|
|
local id = self:GetID(obj, sec, true)
|
|
if self.indx_id[id] then
|
|
self:Print(nil, "AddItem | ID [%s] already exists", id)
|
|
return
|
|
end
|
|
|
|
local ci = self:FindSimilar(obj, sec)
|
|
if ci then
|
|
self:Print(nil, "AddItem | Found similar cell [%s]", ci.section)
|
|
if ci:AddChild( obj ) then
|
|
self:AddIndex(id, sec, ci.indx)
|
|
self:Callback( "On_CC_Add", self.ID, ci.indx, false )
|
|
return ci.indx
|
|
end
|
|
else
|
|
local area = self:FindFreeCell(obj, sec)
|
|
if area then
|
|
self:Print(nil, "AddItem | New cell [%s]", sec)
|
|
local indx = self.idxer + 1
|
|
if self:AddItemInCell(obj, sec, indx, area) then
|
|
self:AddIndex(id, sec, indx)
|
|
self.idxer = indx
|
|
if info then
|
|
ci = self.cell[indx]
|
|
ci.flags.info = info
|
|
end
|
|
|
|
self:Callback( "On_CC_Add", self.ID, indx, true )
|
|
return indx
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:AddItemManual(obj, sec, indx)
|
|
if (not self.cell[indx]) then
|
|
self:Print(nil, "AddItemManual | Creating new cell | obj: %s - index: %s", obj and obj:name() or sec, indx)
|
|
self.cell[indx] = UICellItem(self, self.st, indx, true)
|
|
if self.showcase then
|
|
self.cell[indx].showcase = self.manual and 2 or 1
|
|
end
|
|
end
|
|
|
|
if not (obj or sec) then
|
|
self.cell[indx]:Reset()
|
|
return
|
|
end
|
|
|
|
local set = self.cell[indx]:Set(obj or sec)
|
|
if set and obj then
|
|
local id = self:GetID(obj, sec)
|
|
if (not id) then
|
|
return
|
|
end
|
|
sec = sec or (obj and obj:section())
|
|
self:AddIndex(id, sec, indx)
|
|
self:Callback( "On_CC_Add", self.ID, indx, true )
|
|
self:Print(nil, "AddItemManual | Set in cell (%s) | obj: %s - index: %s", set, obj and obj:name() or sec, indx)
|
|
end
|
|
|
|
self:Scroll_Reinit(true)
|
|
|
|
return set
|
|
end
|
|
|
|
function UICellContainer:RemoveItem(obj, sec)
|
|
if (not sec) then
|
|
if (not obj) then
|
|
return
|
|
end
|
|
sec = obj and obj:section()
|
|
end
|
|
|
|
local id = self:GetID(obj, sec)
|
|
if (not id) then
|
|
return
|
|
end
|
|
|
|
local ci = self:GetCell_ID(id)
|
|
if ci then
|
|
if ci:HasChild(obj) then
|
|
self:Print(nil, "RemoveItem [%s] | Removing inner child", obj and obj:name() or sec)
|
|
ci:PopChild(obj)
|
|
self:RemoveIndex(id, sec, ci.indx)
|
|
self:Callback( "On_CC_Remove", self.ID, ci.indx, true )
|
|
|
|
elseif (id == ci.ID) or (sec and (not obj)) then
|
|
local cell_removed = ci:ResetToChild()
|
|
if cell_removed then
|
|
self:Print(nil, "RemoveItem [%s] | Removing base", obj and obj:name() or sec)
|
|
self:RemoveIndex(id, sec, ci.indx)
|
|
self:Callback( "On_CC_Remove", self.ID, ci.indx, false )
|
|
else
|
|
self:Print(nil, "RemoveItem [%s] | Removing outer child", obj and obj:name() or sec)
|
|
self:RemoveIndex(id, sec, ci.indx)
|
|
self:Callback( "On_CC_Remove", self.ID, ci.indx, true )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:RemoveItem_byID(id)
|
|
-- Used if object no longer exists (non-showcase type)
|
|
if (not id) then
|
|
return
|
|
end
|
|
|
|
local ci = self:GetCell_ID(id)
|
|
if ci then
|
|
if ci:HasChild(nil,id) then
|
|
self:Print(nil, "RemoveItem_byID [%s] | Removing inner child", id)
|
|
ci:PopChild(nil,id)
|
|
self:RemoveIndex(id, nil, ci.indx)
|
|
self:Callback( "On_CC_Remove", self.ID, ci.indx, true )
|
|
|
|
elseif (id == ci.ID) then
|
|
local cell_removed = ci:ResetToChild()
|
|
if cell_removed then
|
|
self:Print(nil, "RemoveItem_byID [%s] | Removing base", id)
|
|
self:RemoveIndex(id, nil, ci.indx)
|
|
self:Callback( "On_CC_Remove", self.ID, ci.indx, false )
|
|
else
|
|
self:Print(nil, "RemoveItem_byID [%s] | Removing outer child", id)
|
|
self:RemoveIndex(id, nil, ci.indx)
|
|
self:Callback( "On_CC_Remove", self.ID, ci.indx, true )
|
|
end
|
|
|
|
else
|
|
self:Print(nil, "RemoveItem_byID [%s] | No active cell found!", id)
|
|
self:RemoveIndex(id)
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:RemoveItemManual(indx)
|
|
local ci = self.cell[indx]
|
|
if ci then
|
|
local obj = ci.ID and self:GetObj(indx)
|
|
local sec = obj and obj:section() or ci.section
|
|
local id = self:GetID(obj, sec)
|
|
if ci.showcase ~= 0 and (not obj) then
|
|
printe("!ERROR UICellContainer:RemoveItemManual | can't get game object for [%s]", sec)
|
|
return
|
|
end
|
|
|
|
local cell_removed = ci:ResetToChild()
|
|
if cell_removed and (obj or sec) then
|
|
self:Print(nil, "RemoveItem [%s] | Removing base", obj and obj:name() or sec)
|
|
self:RemoveIndex(id, sec, indx)
|
|
self:Callback( "On_CC_Remove", self.ID, indx, false )
|
|
self:Scroll_Reinit(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:TransferItem(cont_to, obj, sec)
|
|
self:Print(nil, "TransferItem [%s]", obj and obj:name() or sec)
|
|
|
|
if not (obj or sec) then
|
|
return
|
|
end
|
|
|
|
local id = self:GetID(obj, sec)
|
|
if (not id) then
|
|
return
|
|
end
|
|
|
|
local ci_from = self:GetCell_ID(id)
|
|
if ci_from then
|
|
-- Create object in new container
|
|
local indx = cont_to:AddItem(obj, sec)
|
|
local ci_to = indx and cont_to.cell[indx]
|
|
|
|
-- Transfer trade data in trade mode
|
|
ci_to.flags = dup_table(ci_from.flags)
|
|
|
|
-- Remove object from old container
|
|
self:RemoveItem(obj, sec)
|
|
|
|
self:Callback( "On_CC_Trasfer", self.ID, cont_to.ID, ci_from.indx, ci_to.indx , obj or sec)
|
|
|
|
return ci_to
|
|
end
|
|
end
|
|
|
|
function UICellContainer:UpdateItem(obj, sec)
|
|
local id = self:GetID(obj, sec)
|
|
local ci = id and self:GetCell_ID(id)
|
|
if ci then
|
|
ci:Update() -- force it to get game object again for updated stats
|
|
end
|
|
end
|
|
|
|
function UICellContainer:FindFreeCell(obj, sec)
|
|
if (not sec) then
|
|
if (not obj) then
|
|
return false
|
|
end
|
|
sec = obj and obj:section()
|
|
end
|
|
|
|
local w = SYS_GetParam(2,sec, "inv_grid_width",1)
|
|
local h = SYS_GetParam(2,sec, "inv_grid_height",1)
|
|
|
|
-- Avoid icons that don't fit
|
|
if w > self.cols then
|
|
return false
|
|
end
|
|
|
|
-- Sorting by kind: when sorting a new kind, always start from last row taken by previous kind
|
|
if self.sort_method == "kind" then
|
|
self.rKind.current = item_order[ab_k[sec]]
|
|
if (self.rKind.last ~= self.rKind.current) then
|
|
--[[
|
|
local cnt = self.line_cnt + 1
|
|
if (not self.line[cnt]) then
|
|
self.line[cnt] = self.xml:InitStatic(self.path .. ":line", self.st)
|
|
end
|
|
|
|
local y = (self.row_end) * (self.grid_size + self.grid_line)
|
|
self.line[cnt]:SetWndPos( vector2():set(0,y - 2.5) )
|
|
self.line[cnt]:SetWndSize( vector2():set(self.prof:GetWidth(),6) )
|
|
self.line[cnt]:Show(true)
|
|
self.line_cnt = cnt
|
|
--]]
|
|
|
|
self.rKind.last = self.rKind.current
|
|
self.rKind.row = self.row_end + 1
|
|
end
|
|
end
|
|
|
|
local row_s = self.rKind.row
|
|
local rows = #self.grid
|
|
local cols = self.cols + 1 - w
|
|
self:Print(nil, "FindFreeCell for [%s] (rows: %s, cols: %s, W: %s, H: %s)", sec, rows,cols,w,h)
|
|
for r=row_s, rows do
|
|
for c=1,cols do
|
|
if self:IsFreeRoom(r,c,w,h) then
|
|
return self:TakeRoom(r,c,w,h)
|
|
end
|
|
end
|
|
end
|
|
|
|
self:Grow()
|
|
|
|
return self:FindFreeCell(obj, sec)
|
|
end
|
|
|
|
function UICellContainer:IsFreeRoom(r,c,w,h)
|
|
for row = r, r+(h-1) do
|
|
for col = c, c+(w-1) do
|
|
if (not self.grid[row]) then
|
|
self:Print(nil, "IsFreeRoom row missing: %s", row)
|
|
return false
|
|
end
|
|
if self.grid[row][col] == false then
|
|
self:Print(nil, "IsFreeRoom | row: %s - col: %s is occupied", row, col)
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
self:Print(nil, "IsFreeRoom (%s,%s,%s,%s) = %s", r,c,w,h, true)
|
|
return true
|
|
end
|
|
|
|
function UICellContainer:TakeRoom(r,c,w,h)
|
|
self:Print(nil, "TakeRoom (%s,%s,%s,%s)", r,c,w,h)
|
|
|
|
local r_end = r+(h-1)
|
|
local c_end = c+(w-1)
|
|
for row = r, r_end do -- -1 because starting row/coloumn cell should be counted
|
|
for col = c, c_end do
|
|
self.grid[row][col] = false
|
|
end
|
|
end
|
|
|
|
if (r_end > self.row_end) then
|
|
self.row_end = r_end
|
|
end
|
|
if (c_end > self.col_end) then
|
|
self.col_end = c_end
|
|
end
|
|
|
|
return { y=r , x=c , w=w , h=h } -- rows are Y, coloumns are X
|
|
end
|
|
|
|
function UICellContainer:FreeRoom(r,c,w,h)
|
|
self:Print(nil, "FreeRoom (%s,%s,%s,%s)", r,c,w,h)
|
|
|
|
for row = r, r+(h-1) do
|
|
for col = c, c+(w-1) do
|
|
self.grid[row][col] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:FindSimilar(obj, sec)
|
|
if not (obj or sec) then
|
|
printe("!ERROR UICellContainer:FindSimilar | no data recieved!")
|
|
return false
|
|
end
|
|
|
|
if self.disable_stack then
|
|
return false
|
|
end
|
|
|
|
if self.showcase or self.stack_all then
|
|
return self:GetCell_SEC(sec)
|
|
end
|
|
|
|
local sec = obj:section()
|
|
|
|
-- Ignore search if item isn't meant to stack
|
|
if SYS_GetParam(1,sec,"dont_stack") then
|
|
return false
|
|
end
|
|
|
|
-- Ignore search if multiuse item is used
|
|
local max_uses = IsItem("multiuse",sec)
|
|
if max_uses and obj:get_remaining_uses() ~= max_uses then
|
|
return false
|
|
end
|
|
|
|
-- items with no condition can stack, return a cell with same section
|
|
local clsid = obj:clsid()
|
|
local use_cond = SYS_GetParam(1,sec,"use_condition") or IsWeapon(nil,clsid) or IsOutfit(nil,clsid) or IsHeadgear(nil,clsid)
|
|
if (not use_cond) then
|
|
return self:GetCell_SEC(sec)
|
|
end
|
|
|
|
-- Ignore search if item has upgrades
|
|
if has_upgrades(obj) then
|
|
return false
|
|
end
|
|
|
|
-- items with condition, full search
|
|
for idx,ci in pairs(self.cell) do
|
|
if (ci.section == sec) then
|
|
-- full multiuse item can stack
|
|
if max_uses then
|
|
return ci
|
|
|
|
-- item with similar condition can stack
|
|
else
|
|
local cond = obj:condition()
|
|
local obj_2 = ci.ID and level.object_by_id(ci.ID)
|
|
if obj_2 and math.abs(obj_2:condition() - cond) < 0.1 then
|
|
return ci
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- no similar item found
|
|
return false
|
|
end
|
|
|
|
function UICellContainer:Grow()
|
|
local rows = #self.grid
|
|
rows = rows + 1
|
|
self.grid[rows] = {}
|
|
|
|
for i=1,self.cols do
|
|
self.grid[rows][i] = true
|
|
end
|
|
self:Print(nil, "Grow | new row: %s", rows)
|
|
end
|
|
|
|
function UICellContainer:IsTradable(obj)
|
|
local ci = obj and self:GetCell_ID(obj:id())
|
|
return ci and ci:IsShown() and (get_item_trade_status(obj, self.trade_profile) == 4)
|
|
end
|
|
|
|
function UICellContainer:GetCellCost(ci)
|
|
if not (ci and ci:IsShown() and self.trade_profile) then
|
|
return 0
|
|
end
|
|
|
|
local t_id = {}
|
|
|
|
t_id[ci.ID] = true
|
|
if ci:HasChild() then
|
|
for id,_ in pairs(ci.childs) do t_id[id] = true end
|
|
end
|
|
|
|
local tot_cost = 0
|
|
for id,_ in pairs(t_id) do
|
|
local obj = level.object_by_id(id)
|
|
if obj and (get_item_trade_status(obj, self.trade_profile) == 4) then
|
|
tot_cost = tot_cost + get_item_cost(obj, self.trade_profile)
|
|
end
|
|
end
|
|
return tot_cost
|
|
end
|
|
|
|
function UICellContainer:On_Select(idx)
|
|
|
|
-- Forced deselect
|
|
if (not self.can_select) or (idx == false) then
|
|
local ci = self.selected and self.cell[self.selected]
|
|
if ci then
|
|
ci:Highlight(false)
|
|
end
|
|
self.selected = nil
|
|
return
|
|
end
|
|
|
|
idx = idx or self.selected
|
|
|
|
-- Deselect previous cell
|
|
if self.selected and (self.selected ~= idx) then
|
|
local ci = self.cell[self.selected]
|
|
if ci then
|
|
ci:Highlight(false)
|
|
end
|
|
end
|
|
|
|
-- Select new cell
|
|
local ci = idx and self.cell[idx]
|
|
if ci then
|
|
ci:Highlight(true,"green")
|
|
self.selected = idx
|
|
end
|
|
end
|
|
|
|
function UICellContainer:On_Drag(idx, tg, set)
|
|
|
|
-- Hold icon should be declared after everything else, so it stays on top
|
|
-- Also it must be assigned on the base UI because we need x and y to start from absolute screen corner
|
|
if (not self.hold.ico) then
|
|
self.hold.ico = self.xml:InitStatic(self.path .. ":cell:pic", self.owner)
|
|
self.hold.ico:Show(false)
|
|
end
|
|
|
|
if (self.disable_drag) then
|
|
return
|
|
end
|
|
|
|
-- Drag start / Drop
|
|
if set then
|
|
self:Print(nil, "Drag | hold_idx: %s - hold_tg: %s", idx, tg)
|
|
|
|
-- Callback
|
|
if (not idx) and self.hold.idx and (self.hold.idx ~= self.hover.idx) then -- IF released mouse + drag item is captured + drag item is not hovered item
|
|
self:Callback( "On_CC_DragDrop", self.ID, self.hold.idx )
|
|
end
|
|
|
|
-- Useful to prevent some actions for owner when there's a dragged item, by checking on (self.item_in_hold)
|
|
if self.owner.item_in_hold == self.ID then
|
|
self.owner.item_in_hold = false
|
|
end
|
|
if idx then
|
|
self.owner.item_in_hold = self.ID
|
|
|
|
-- Hold the scroll and stop moving on dragging
|
|
self.scroll_pos = self.scroll:GetCurrentScrollPos()
|
|
|
|
-- No point of holding empty cells
|
|
if (not self.cell[idx]:IsShown()) then
|
|
return
|
|
end
|
|
end
|
|
|
|
self.hold.idx = idx
|
|
self.hold.tg = tg
|
|
self.hold.ico:Show(false)
|
|
return
|
|
end
|
|
|
|
-- Drag
|
|
if self.hold.idx and tg - self.hold.tg > 100 then
|
|
|
|
-- Set up drag item icon
|
|
if (not self.hold.ico:IsShown()) then
|
|
self:Print(nil, "Drag | set up icon")
|
|
local sec = self.cell[self.hold.idx].section
|
|
|
|
if sec then
|
|
self.hold.w = SYS_GetParam(2,sec, "inv_grid_width") * self.grid_size * ratio
|
|
self.hold.h = SYS_GetParam(2,sec, "inv_grid_height") * self.grid_size
|
|
|
|
self.hold.ico:InitTexture( utils_xml.get_icons_texture(sec) )
|
|
self.hold.ico:SetTextureRect(Frect():set( get_item_axis(sec, nil, true) ))
|
|
self.hold.ico:SetTextureColor( clr_list["drag"] )
|
|
self.hold.ico:SetStretchTexture(true)
|
|
self.hold.ico:SetWndSize(vector2():set(self.hold.w , self.hold.h))
|
|
self.hold.ico:Show(true)
|
|
end
|
|
end
|
|
|
|
-- Sync with cursor pos
|
|
local pos = GetCursorPosition()
|
|
self.hold.ico:SetWndPos( pos )
|
|
end
|
|
end
|
|
|
|
function UICellContainer:On_Hover(idx)
|
|
if (not idx) then
|
|
-- UnHighlight old cell
|
|
if self.hover.idx then
|
|
local ci = self.cell[self.hover.idx]
|
|
if ci then
|
|
ci:Highlight(false)
|
|
end
|
|
end
|
|
|
|
-- Unmark hovering
|
|
self.hover.idx = false
|
|
|
|
elseif self.hover.idx ~= idx then
|
|
|
|
-- UnHighlight old cell
|
|
if self.hover.idx then
|
|
local ci = self.cell[self.hover.idx]
|
|
if ci then
|
|
ci:Highlight(false)
|
|
end
|
|
end
|
|
|
|
-- Mark hovered cell
|
|
self.hover.idx = idx
|
|
|
|
-- Highlight new cell (on hover, cell must be shown)
|
|
local ci = self.cell[idx]
|
|
if ci and ci:IsShown() then
|
|
ci:Highlight(true)
|
|
end
|
|
end
|
|
|
|
-- Callback, only if mouse on bag
|
|
if self:IsCursorOverWindow() then
|
|
self:Callback( "On_CC_Hover", self.ID, self.hover.idx )
|
|
end
|
|
end
|
|
|
|
function UICellContainer:On_Mouse1(idx)
|
|
|
|
-- Anticipate double click
|
|
local tg = get_time()
|
|
|
|
if (tg - self.db.tg < 400) then
|
|
self.db.idx = idx --false
|
|
self.db.tg = tg
|
|
|
|
local db_continue = self:On_Mouse1_DB(idx)
|
|
|
|
-- when there's a value returned, allow consecutive db clicks
|
|
if (not db_continue) then
|
|
self.db.idx = false
|
|
end
|
|
|
|
-- db_continue is false if no db callback is found in owner class, so we can pass the return and treat db click as normal click
|
|
if (db_continue ~= false) then
|
|
return
|
|
end
|
|
end
|
|
|
|
self.db.idx = idx
|
|
self.db.tg = tg
|
|
self:On_Select(idx)
|
|
|
|
self:Callback( "On_CC_Mouse1", self.ID, idx )
|
|
end
|
|
|
|
function UICellContainer:On_Mouse1_DB(idx)
|
|
return self:Callback( "On_CC_Mouse1_DB", self.ID, idx ) -- Returning true means no cooldown on double clicking if you keep clicking!
|
|
end
|
|
|
|
function UICellContainer:On_Mouse2(idx)
|
|
self:On_Select(idx)
|
|
|
|
self:Callback( "On_CC_Mouse2", self.ID, idx )
|
|
end
|
|
|
|
function UICellContainer:On_Scroll()
|
|
if (self.disable_scroll) then
|
|
self:Scroll_SetPos(0)
|
|
return
|
|
end
|
|
|
|
if (not self.scroll_pos) then
|
|
self.scroll_pos = self.scroll:GetCurrentScrollPos()
|
|
return
|
|
end
|
|
|
|
-- Setting scroll pad size
|
|
if self.pd.update then
|
|
self:Scroll_Pad_Ctrl(true)
|
|
self.pd.update = false
|
|
end
|
|
|
|
-- Prevent scrolling when it's paused
|
|
if self.scroll_pause then
|
|
self:Scroll_DragDrop_Ctrl()
|
|
self:Scroll_Pad_Ctrl()
|
|
self:Scroll_SetPos()
|
|
return
|
|
end
|
|
self.pd.off = false
|
|
self.pd.hold = false
|
|
|
|
-- Prevent scrolling when holding item
|
|
if self.hold.idx or self.owner.item_in_hold then
|
|
self:Scroll_DragDrop_Ctrl()
|
|
self:Scroll_SetPos()
|
|
return
|
|
end
|
|
|
|
-- small delay
|
|
if (not self.scroll_tg) then
|
|
self.scroll_tg = get_time()
|
|
end
|
|
|
|
-- Alt Tab Scroll Issue fix by DPurple
|
|
-- get_time() may unreliable , try reset delay
|
|
if get_time() - self.scroll_tg < 0 then
|
|
self.scroll_tg = get_time()
|
|
end
|
|
|
|
if self.scroll_tg > (get_time() + 25) then
|
|
return
|
|
end
|
|
self.scroll_tg = get_time()
|
|
|
|
-- Amplify scrolling
|
|
local curr_pos = self.scroll:GetCurrentScrollPos()
|
|
if (self.scroll_pos ~= curr_pos) then
|
|
if (curr_pos > self.scroll_pos) then
|
|
self:Scroll_SetPos( self.scroll_pos + ((self.grid_size + self.grid_line) * self.scolling_power) )
|
|
else
|
|
self:Scroll_SetPos( self.scroll_pos - ((self.grid_size + self.grid_line) * self.scolling_power) )
|
|
end
|
|
--printf("curr pos: %s - scroll pos: %s", curr_pos, self.scroll_pos)
|
|
end
|
|
end
|
|
|
|
function UICellContainer:Update(item_info, no_info, hide)
|
|
|
|
self:On_Drag(false, get_time())
|
|
self:On_Select()
|
|
self:On_Scroll()
|
|
if hide then
|
|
self:On_Hover(false)
|
|
|
|
return false
|
|
end
|
|
|
|
if self:IsCursorOverWindow() then -- For performance: There's no need to iterate cells, if the container is not focused in the first place
|
|
for i=1,#self.cell do
|
|
local ci = self.cell[i]
|
|
|
|
-- Only update for hovered cell
|
|
-- Manual cells are special cases because we want to have hover interaction with them
|
|
if ci and ci:IsCursorOverWindow() and (ci.manual or ci:IsShown()) and self:IsCellVisible(ci) then
|
|
|
|
-- No info if drag is active
|
|
if no_info or self.hold.ico:IsShown() then
|
|
if item_info then
|
|
item_info:Update()
|
|
end
|
|
elseif item_info and (not self.disable_info) and ci:IsShown() then
|
|
local obj = ci.ID and level.object_by_id(ci.ID)
|
|
item_info:Update( obj, ci.section, ci.flags)
|
|
end
|
|
|
|
self:On_Hover(i)
|
|
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
self:On_Hover(false)
|
|
|
|
return false
|
|
end
|
|
|
|
function UICellContainer:OnKeyboard(dik, keyboard_action)
|
|
|
|
-- Pause scrolling when holding M1
|
|
if (dik == K_M1) then
|
|
if (keyboard_action == E_PRESS) then
|
|
self.scroll_pause = true
|
|
elseif (keyboard_action == E_RELEASE) then
|
|
self.scroll_pause = false
|
|
end
|
|
end
|
|
|
|
-- Interaction with cells
|
|
local idx = self.hover.idx
|
|
if idx then
|
|
|
|
-- Mouse 1
|
|
if (dik == K_M1) then
|
|
if (keyboard_action == E_PRESS) then
|
|
self:On_Drag(idx, get_time(), true)
|
|
|
|
elseif (keyboard_action == E_RELEASE) then
|
|
self:On_Drag(false, 0, true)
|
|
self:On_Mouse1(idx)
|
|
end
|
|
|
|
-- Mouse 2
|
|
elseif (dik == K_M2) then
|
|
if (keyboard_action == E_RELEASE) then
|
|
self:On_Mouse2(idx)
|
|
end
|
|
end
|
|
|
|
-- We disable drag on releasing regardless of highlighted cell
|
|
elseif (dik == K_M1) and (keyboard_action == E_RELEASE) then
|
|
self:On_Drag(false, 0, true)
|
|
end
|
|
|
|
-- Left shift
|
|
if (dik == K_SHFT) then
|
|
self.scolling_power = (keyboard_action == E_PRESS) and self.scolling_power_up or 1
|
|
end
|
|
end
|
|
|
|
function UICellContainer:Callback(func, ...)
|
|
-- This is needed for inventory UI to avoid endless loop for slots managements
|
|
if self.disable_callback[func] then
|
|
return
|
|
end
|
|
|
|
if self.owner[func] then
|
|
return self.owner[func](self.owner,...)
|
|
|
|
elseif (func == "On_CC_Mouse1_DB") then
|
|
return false
|
|
end
|
|
end
|
|
|
|
function UICellContainer:Reset()
|
|
self:Print(nil, "Reset")
|
|
|
|
self.hover.idx = false
|
|
for idx,ci in pairs(self.cell) do
|
|
ci:Reset()
|
|
end
|
|
for cnt, ele in pairs(self.line) do
|
|
ele:Show(false)
|
|
end
|
|
self:On_Select(false)
|
|
self.idxer = 0
|
|
self.row_end = 0
|
|
self.col_end = 0
|
|
self.scroll_pos = 0
|
|
self.rKind.last = false
|
|
self.rKind.current = false
|
|
self.rKind.row = 1
|
|
self.line_cnt = 0
|
|
empty_table(self.indx_id)
|
|
empty_table(self.indx_sec)
|
|
self.pad:Show(false)
|
|
|
|
self.selected = nil
|
|
self.hold.idx = false
|
|
self.hold.tg = 0
|
|
self.hold.w = 0
|
|
self.hold.h = 0
|
|
if self.hold.ico then
|
|
self.hold.ico:Show(false)
|
|
end
|
|
|
|
self.db.idx = false
|
|
self.db.tg = 0
|
|
|
|
-- Reset Grid
|
|
for row,v in pairs(self.grid) do
|
|
for col,state in pairs(v) do
|
|
self.grid[row][col] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
function UICellContainer:IsCellVisible(ci)
|
|
-- This is important because we don't want to interact with cells that are outside of scroll view window
|
|
|
|
local pos_start = self.scroll_pos
|
|
local pos_start_ci = ci.cell:GetWndPos().y + self.cell_vis_offset
|
|
local pos_end = pos_start + self.scroll:GetHeight()
|
|
local pos_end_ci = pos_start_ci + ci.cell:GetHeight() - (self.cell_vis_offset * 2)
|
|
|
|
--printf("IsCellVisible | start: %s - start_ci: %s - end: %s - end_ci: %s - top visible: %s - end visible: %s", pos_start, pos_start_ci, pos_end, pos_end_ci, (pos_start_ci >= pos_start) , (pos_end_ci <= pos_end))
|
|
return (pos_start_ci >= pos_start) and (pos_end_ci <= pos_end)
|
|
end
|
|
|
|
function UICellContainer:Scroll_Reinit(keep_pos)
|
|
-- It's important to reset the scroll after cell changes because we want to adapt new cells
|
|
-- TODO: to prevent spawn of items flooding in container, we need to time this in update function
|
|
|
|
-- Used when reiniting cells, to prevent unneeded scroll adjusting when there's a mass amount of cells being recreated
|
|
if self.ignore_scroll then
|
|
return
|
|
end
|
|
|
|
local cpos = (self.disable_scroll and 0) or (keep_pos and self.scroll:GetCurrentScrollPos())
|
|
|
|
self.scroll:Clear()
|
|
|
|
-- We decide container size according to the row with first unoccupied cell
|
|
if (not self.disable_scroll) then
|
|
|
|
-- Determine scroll height
|
|
local h = self:Scroll_GetHeight(1)
|
|
h = h - self.scroll:GetHeight()
|
|
h = h > 0 and h or 0
|
|
|
|
self.st:SetWndSize(vector2():set( self.scroll:GetWidth() , h ))
|
|
--printf("scroll: %s - st: %s", self.scroll:GetHeight(), self.st:GetHeight())
|
|
end
|
|
|
|
self.scroll:AddWindow(self.st, true)
|
|
self.st:SetAutoDelete(false)
|
|
|
|
self.pd.update = true
|
|
|
|
--[[
|
|
if cpos then
|
|
self.scroll:SetScrollPos(cpos)
|
|
end
|
|
--]]
|
|
self:Scroll_SetPos(cpos, true)
|
|
end
|
|
|
|
function UICellContainer:Scroll_SetPos(Y, force)
|
|
if (not Y) then
|
|
Y = self.scroll_pos or 0
|
|
end
|
|
|
|
-- Prevent scrolling if scroll area is shorter than scoll height
|
|
if (((self.grid_size + self.grid_line) * self.row_end) < self.scroll:GetHeight()) then
|
|
Y = 0
|
|
end
|
|
|
|
-- Keep scroll pos in range
|
|
if force then
|
|
-- This trick is used because for some reason the scroll doesn't have full scale on resetting, unless if we set its pos at least once
|
|
self.scroll:SetScrollPos(1)
|
|
end
|
|
|
|
Y = clamp( math.floor(Y), self.scroll:GetMinScrollPos(), self.scroll:GetMaxScrollPos())
|
|
self.scroll:SetScrollPos(Y)
|
|
self.scroll_pos = Y
|
|
|
|
-- Adjust scrolling pad
|
|
if self.pad:IsShown() then
|
|
self.pad:SetWndPos(vector2():set( self.prof:GetWidth() , Y / self.pd.power ))
|
|
end
|
|
|
|
--if (self.ID == "actor_bag") then printf("ID: %s - POS: %s - MIN: %s - MAX: %s - FROM: %s", self.ID, Y, self.scroll:GetMinScrollPos(), self.scroll:GetMaxScrollPos(), callstack(true,true)) end
|
|
end
|
|
|
|
function UICellContainer:Scroll_GetHeight(num, ele)
|
|
if ele then
|
|
return (self.scroll:GetHeight() + self.scroll:GetMaxScrollPos())
|
|
end
|
|
return (self.row_end + (num or 0)) * (self.grid_size + self.grid_line)
|
|
end
|
|
|
|
function UICellContainer:Scroll_DragDrop_Ctrl()
|
|
if self.disable_scroll_dragdrop then
|
|
return false
|
|
end
|
|
|
|
if not (self.hold.idx or self.owner.item_in_hold) then
|
|
return false
|
|
end
|
|
|
|
local dir = (self.drag_up:IsCursorOverWindow() and 1) or (self.drag_down:IsCursorOverWindow() and 2) or 0
|
|
if dir == 0 then
|
|
return false
|
|
end
|
|
|
|
if (dir == 1) and (get_time() - self.drag_area.up > self.drag_area.step) then
|
|
self.drag_area.up = get_time()
|
|
self:Scroll_SetPos( self.scroll_pos - ((self.grid_size + self.grid_line) * self.scolling_power) )
|
|
--printf("On_Scroll_DragDrop UP | old: %s - new: %s", self.scroll_pos, new_pos)
|
|
return true
|
|
|
|
elseif (dir == 2) and (get_time() - self.drag_area.down > self.drag_area.step) then
|
|
self.drag_area.down = get_time()
|
|
self:Scroll_SetPos( self.scroll_pos + ((self.grid_size + self.grid_line) * self.scolling_power) )
|
|
--printf("On_Scroll_DragDrop DOWN | old: %s - new: %s", self.scroll_pos, new_pos)
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function UICellContainer:Scroll_Pad_Ctrl(update)
|
|
|
|
-- Scroll pad state and size
|
|
if update then
|
|
local h_view = self.scroll:GetHeight()
|
|
local h_max = h_view + self.scroll:GetMaxScrollPos()
|
|
if (h_max <= h_view + 1) or (self.disable_scroll) then
|
|
self.pad:Show(false)
|
|
else
|
|
local h_scroll = (h_max - h_view)
|
|
local ratio = (h_view / h_max)
|
|
local h_pad = h_view * ratio
|
|
self.pd.power = h_scroll/(h_view - h_pad)
|
|
--printf("h_view: %s - h_scroll: %s - h_max: %s - h_pad: %s - ratio: %s - power: %s", h_view, h_scroll, h_max, h_pad, ratio, self.pd.power)
|
|
self.pad:SetWndPos(vector2():set( self.prof:GetWidth() , self.scroll_pos / self.pd.power ))
|
|
-- Edited by Sota
|
|
--self.pad:SetWndSize(vector2():set( 5 , math.floor(h_pad) ))
|
|
self.pad:SetWndSize(vector2():set( 5 * uwide_ratio , math.floor(h_pad) ))
|
|
|
|
self.pad:Show(true)
|
|
end
|
|
return
|
|
end
|
|
|
|
-- No interaction if pad isn't shown
|
|
if (not self.pad:IsShown()) then
|
|
return
|
|
end
|
|
|
|
-- No interaction if pad is not focused
|
|
if not (self.pd.hold or self.pad:IsCursorOverWindow()) then
|
|
return
|
|
end
|
|
|
|
-- Storing start pos for the first time on holding
|
|
if (not self.pd.off) then
|
|
self.pd.off = GetCursorPosition().y
|
|
self.pd.start = self.scroll_pos
|
|
self.pd.hold = true
|
|
return
|
|
end
|
|
|
|
-- Set scroll pos according to mouse pos
|
|
local offset = GetCursorPosition().y - self.pd.off
|
|
self.scroll_pos = self.pd.start + (offset * self.pd.power)
|
|
--printf("offset: %s - scroll_pos: %s", offset, self.scroll_pos)
|
|
end
|
|
|
|
function UICellContainer:GetSortMethod()
|
|
if self.sort_method == "sizekind" then
|
|
return sort_by_sizekind
|
|
elseif self.sort_method == "props" then
|
|
return sort_by_props
|
|
elseif self.sort_method == "kind" then
|
|
return sort_by_kind
|
|
end
|
|
|
|
return sort_by_sizekind
|
|
end
|
|
|
|
function UICellContainer:AdjustWnd(x, y, w, h)
|
|
local pos = x and y and vector2():set(x,y) or self.prof:GetWndPos()
|
|
self.prof:SetWndPos( pos )
|
|
|
|
self.prof:SetWndSize(vector2():set( (w or self.prof:GetWidth()) , (h or self.prof:GetHeight()) ))
|
|
utils_xml.sync_size( self.prof , self.scroll )
|
|
end
|
|
|
|
function UICellContainer:AdjustHeightToCell()
|
|
local h = self.row_end * (self.grid_size + self.grid_line)
|
|
if self.use_frame then
|
|
h = h + 30
|
|
if h < 36 then h = 36 end
|
|
self.scroll:SetWndPos(vector2():set( 15 , 15 ))
|
|
end
|
|
self.prof:SetWndSize(vector2():set( self.prof:GetWidth() , h ))
|
|
utils_xml.sync_size( self.prof , self.scroll )
|
|
end
|
|
|
|
function UICellContainer:AdjustWidthToCell()
|
|
local w = self.col_end * (self.grid_size + self.grid_line)
|
|
w = w * ratio
|
|
if self.use_frame then
|
|
w = w + 30
|
|
if w < 36 then w = 36 end
|
|
self.scroll:SetWndPos(vector2():set( 15 , 15 ))
|
|
end
|
|
self.prof:SetWndSize(vector2():set( w , self.prof:GetHeight() ))
|
|
utils_xml.sync_size( self.prof , self.scroll )
|
|
end
|
|
|
|
function UICellContainer:SetBackground(path, clr)
|
|
if (type(path) == "string") then
|
|
self.prof:InitTexture(path)
|
|
end
|
|
self.prof:SetTextureColor(clr)
|
|
end
|
|
|
|
function UICellContainer:SetGridSpecs(size, line)
|
|
self.grid_size = size or self.grid_size
|
|
self.grid_line = line or self.grid_line
|
|
self.cols = math.floor( (self.scroll:GetWidth() * (1/ratio)) / (self.grid_size + self.grid_line) )
|
|
|
|
self:Print(nil, "SetGridSpecs | size: %s - line: %s - num of colomns: %s", self.grid_size, self.grid_line, self.cols)
|
|
end
|
|
|
|
function UICellContainer:Show(state)
|
|
self.prof:Show(state)
|
|
|
|
if (not state) then
|
|
-- Hide hold icon
|
|
self.hold.idx = false
|
|
if self.hold.ico then
|
|
self.hold.ico:Show(false)
|
|
end
|
|
|
|
self.hover.idx = false
|
|
self.db.idx = false
|
|
end
|
|
end
|
|
|
|
function UICellContainer:IsShown()
|
|
return self.prof:IsShown()
|
|
end
|
|
|
|
function UICellContainer:EnableScrolling(state)
|
|
self.disable_scroll = (not state)
|
|
self.scroll:Enable(state)
|
|
end
|
|
|
|
function UICellContainer:IsCursorOverWindow()
|
|
return self.prof:IsShown() and self.prof:IsCursorOverWindow()
|
|
end
|
|
|
|
function UICellContainer:Print(mark, fmt,...)
|
|
--printf( (mark or "+") .. " UICellContainer [%s] | " .. fmt, self.ID, ...)
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------
|
|
-- Item info box
|
|
-------------------------------------------------------------------
|
|
|
|
class "UIInfoItem"
|
|
|
|
function UIInfoItem:__init(owner, delay)
|
|
self.owner = owner
|
|
self.id = nil
|
|
self.section = nil
|
|
|
|
self.can_compare = false
|
|
self.timer = 0
|
|
self.delay = delay or 700
|
|
self.ammo_parse = { [1]=true , [4] = true , [7] = true , [10] = true }
|
|
|
|
prepare_stats_table()
|
|
|
|
self:InitControls()
|
|
self:Show(false)
|
|
end
|
|
|
|
function UIInfoItem:InitControls()
|
|
--[[
|
|
self.xml = CScriptXmlInit()
|
|
local xml = self.xml
|
|
xml:ParseFile ("ui_item_info.xml")
|
|
--]]
|
|
self.dialog = XMLP:InitStatic("item_info", self.owner)
|
|
|
|
self.frame = XMLP:InitFrame("item_info:background_frame", self.dialog)
|
|
self.name = XMLP:InitTextWnd("item_info:name", self.dialog)
|
|
self.weight = XMLP:InitTextWnd("item_info:weight", self.dialog)
|
|
self.value = XMLP:InitTextWnd("item_info:cost", self.dialog)
|
|
self.note = XMLP:InitTextWnd("item_info:no_trade", self.dialog)
|
|
self.desc = XMLP:InitTextWnd("item_info:description", self.dialog)
|
|
|
|
-- Stats
|
|
self.stats_dialog = XMLP:InitStatic("item_info:stats_dialog", self.dialog)
|
|
self.stats = {}
|
|
for i=1,16 do
|
|
self.stats[i] = {}
|
|
self.stats[i].base = XMLP:InitStatic("item_info:stats_box", self.stats_dialog)
|
|
self.stats[i].icon = XMLP:InitStatic("item_info:stats_box:icon", self.stats[i].base)
|
|
self.stats[i].cap = XMLP:InitTextWnd("item_info:stats_box:cap", self.stats[i].base)
|
|
self.stats[i].bar2 = XMLP:InitProgressBar("item_info:stats_box:prog_bar", self.stats[i].base)
|
|
self.stats[i].bar1 = XMLP:InitProgressBar("item_info:stats_box:prog_bar", self.stats[i].base)
|
|
self.stats[i].txt = XMLP:InitTextWnd("item_info:stats_box:prog_txt", self.stats[i].base)
|
|
self.stats[i].comp = XMLP:InitTextWnd("item_info:stats_box:compare", self.stats[i].base)
|
|
end
|
|
|
|
-- Ammo type
|
|
self.ammo = XMLP:InitStatic("item_info:ammo_type", self.dialog)
|
|
self.ammo_cap = XMLP:InitStatic("item_info:ammo_type:cap_ammo_types", self.ammo)
|
|
self.ammo_txt = XMLP:InitTextWnd("item_info:ammo_type:cap_ammo_used_type", self.ammo)
|
|
self.ammo_ico = {}
|
|
self.ammo_ico_temp = {}
|
|
for i=1,12 do
|
|
if self.ammo_parse[i] then
|
|
self.ammo_ico[i] = XMLP:InitStatic("item_info:ammo_type:static_ammo_type" .. i, self.ammo)
|
|
self.ammo_ico_temp[i] = XMLP:InitStatic("item_info:ammo_type:static_ammo_type" .. i, self.ammo)
|
|
end
|
|
end
|
|
end
|
|
|
|
function UIInfoItem:Update(obj, sec, flags)
|
|
if not self:Pass(obj, sec) then
|
|
self:Show(false)
|
|
return
|
|
end
|
|
|
|
-- item info box is shown at cursor
|
|
sync_cursor(self.dialog, self.frame, 0, 0)
|
|
|
|
-- no need to process if it's same item
|
|
if obj then
|
|
if obj:id() == self.id then
|
|
self:Show(true)
|
|
return
|
|
end
|
|
elseif sec then
|
|
if sec == self.section then
|
|
self:Show(true)
|
|
return
|
|
end
|
|
end
|
|
|
|
-- gather basic info
|
|
sec = obj and obj:section() or sec
|
|
local typ = self:GetType(sec)
|
|
--printf("-updating | section [%s] - type: %s", sec, typ)
|
|
|
|
self.id = obj and obj:id() or nil
|
|
self.section = sec
|
|
|
|
-- Name
|
|
local name = obj and ui_item.get_obj_name(obj) or ui_item.get_sec_name(sec)
|
|
self.name:SetText( name )
|
|
|
|
-- Weight
|
|
local weight = obj and obj:weight() or ini_sys:r_float_ex(sec,"inv_weight")
|
|
self.weight:SetText( round_100(weight) .. " " .. game.translate_string("st_kg") )
|
|
|
|
-- Cost
|
|
if flags and flags.value_str and (not flags.note_str) then
|
|
self.value:SetText( flags.value_str )
|
|
self.value:Show(true)
|
|
else
|
|
self.value:Show(false)
|
|
end
|
|
|
|
-- Note
|
|
if flags and flags.note_str then
|
|
self.note:SetText( flags.note_str )
|
|
self.note:Show(true)
|
|
else
|
|
self.note:Show(false)
|
|
end
|
|
|
|
-- Description
|
|
local desc = obj and ui_item.get_obj_desc(obj) or ui_item.get_sec_desc(sec)
|
|
self.desc:SetText( desc )
|
|
self.desc:AdjustHeightToText()
|
|
|
|
-- Stop here?
|
|
if self:Sync_Finale( (not stats_table[typ]), nil, self.desc, self.frame, 10 ) then
|
|
self.stats_dialog:Show(false)
|
|
self.ammo:Show(false)
|
|
return
|
|
end
|
|
|
|
-- Stats
|
|
for i=1,#self.stats do
|
|
self.stats[i].base:Show(false)
|
|
end
|
|
|
|
-- Comparison
|
|
local obj_b
|
|
if self.can_compare and obj then
|
|
local cls = obj:clsid()
|
|
local slot = SYS_GetParam(2,sec,"slot",-1) + 1
|
|
obj_b = slot > 0 and db.actor:item_in_slot(slot)
|
|
end
|
|
|
|
local v = stats_table[typ]
|
|
local cnt, y = 0, 0
|
|
local cnt_last
|
|
for stat,gr in spairs(v,sort_by_index) do
|
|
|
|
-- get stat value
|
|
local val_a = get_stats_value(obj, sec, gr, stat)
|
|
if val_a then
|
|
if gr.show_always or ((not gr.show_always ) and val_a ~= 0) then
|
|
cnt = cnt + 1
|
|
local ele = self.stats[cnt]
|
|
|
|
-- Set up icon
|
|
local icon_p = gr.icon_p
|
|
local icon_n = (gr.icon_n ~= "") and gr.icon_n or icon_p
|
|
local icon = val_a < 0 and icon_n or icon_p
|
|
if gr.sign_inverse then
|
|
icon = val_a < 0 and icon_p or icon_n
|
|
end
|
|
ele.icon:InitTexture( icon )
|
|
|
|
-- Set up name
|
|
ele.cap:SetText( game.translate_string(gr.name) )
|
|
|
|
-- Reset
|
|
ele.bar2:Show(false)
|
|
ele.bar1:Show(false)
|
|
ele.txt:Show(false)
|
|
ele.comp:Show(false)
|
|
|
|
-- Progress bar
|
|
if gr.track then
|
|
local valbar_a = clamp((math.abs(val_a) * gr.magnitude), 0, 1)
|
|
|
|
-- Comparison item
|
|
local val_b = obj_b and get_stats_value(obj_b, obj_b:section(), gr, stat)
|
|
local valbar_b = val_b and clamp((math.abs(val_b) * gr.magnitude), 0, 1)
|
|
if valbar_b and (valbar_a ~= valbar_b) then
|
|
|
|
-- If focued item's value is bigger than slot item's value -> focued item's bar: green + 2nd layer
|
|
if valbar_a > valbar_b then
|
|
ele.bar1:SetProgressPos( valbar_b )
|
|
ele.bar1:SetColor( clr_list["info_def"] )
|
|
|
|
ele.bar2:SetProgressPos( valbar_a )
|
|
ele.bar2:SetColor( clr_list["info_p"] )
|
|
|
|
ele.comp:SetTextColor( clr_list["info_p_txt"] )
|
|
|
|
-- If focued item's value is smaller than slot item's value -> focued item's bar: red + 1nd layer
|
|
else
|
|
ele.bar1:SetProgressPos( valbar_a )
|
|
ele.bar1:SetColor( clr_list["info_def"] )
|
|
|
|
ele.bar2:SetProgressPos( valbar_b )
|
|
ele.bar2:SetColor( clr_list["info_n"] )
|
|
|
|
ele.comp:SetTextColor( clr_list["info_n_txt"] )
|
|
end
|
|
|
|
local diff_val = math.ceil( (valbar_a - valbar_b) * 100 )
|
|
ele.comp:SetText( (diff_val > 0 and "+" or "") .. diff_val .. "%" )
|
|
ele.comp:Show(true)
|
|
ele.bar1:Show(true)
|
|
ele.bar2:Show(true)
|
|
ele.bar1:ShowBackground(false)
|
|
|
|
-- No comparison
|
|
else
|
|
ele.bar1:SetProgressPos( valbar_a )
|
|
ele.bar1:SetColor( clr_list["info_def"] )
|
|
ele.bar1:Show(true)
|
|
ele.bar1:ShowBackground(true)
|
|
end
|
|
|
|
-- Text
|
|
elseif ele.txt then
|
|
local valbar_a = val_a * gr.magnitude
|
|
local unit = gr.unit and gr.unit ~= "" and game.translate_string(gr.unit) or ""
|
|
local clr = valbar_a >= 0 and clr_list["p1"] or clr_list["n1"]
|
|
valbar_a = math.ceil(valbar_a)
|
|
|
|
if gr.sign_inverse then
|
|
clr = valbar_a < 0 and clr_list["p1"] or clr_list["n1"]
|
|
--valbar_a = -1 * valbar_a -- invert sign again if needed
|
|
end
|
|
local sign = gr.sign and valbar_a > 0 and "+" or ""
|
|
|
|
-- Comparison item
|
|
local val_b = obj_b and get_stats_value(obj_b, obj_b:section(), gr, stat)
|
|
local valbar_b = val_b and val_b * gr.magnitude
|
|
if valbar_b and (valbar_a ~= valbar_b) then
|
|
local diff_val = math.ceil(valbar_a - valbar_b)
|
|
ele.comp:SetText( "(" .. (diff_val > 0 and "+" or "") .. diff_val .. ")" )
|
|
ele.comp:Show(true)
|
|
clr = (valbar_a > valbar_b) and clr_list["info_p_txt"] or clr_list["info_n_txt"]
|
|
end
|
|
|
|
if gr.sign_inverse_txt then
|
|
if valbar_a > 0 then
|
|
sign = "-"
|
|
elseif valbar_a < 0 then
|
|
valbar_a = -1 * valbar_a
|
|
sign = "+"
|
|
end
|
|
end
|
|
|
|
ele.txt:SetText( sign .. valbar_a .. " " .. unit )
|
|
ele.txt:SetTextColor( clr )
|
|
ele.txt:Show(true)
|
|
end
|
|
|
|
|
|
y = y + ele.base:GetHeight()
|
|
--printf("stat ele [%s] [%s] | cnt: %s - y: %s - value: %s", sec, stat, cnt, y, val_a)
|
|
|
|
local ele_prev = cnt_last and self.stats[cnt_last]
|
|
self:Sync_Y(ele_prev and ele_prev.base, ele.base, 0)
|
|
cnt_last = cnt
|
|
|
|
ele.base:Show(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.stats_dialog:SetWndSize(vector2():set( self.stats_dialog:GetWidth() , y + 10 ))
|
|
self.stats_dialog:Show(true)
|
|
|
|
-- Stop here?
|
|
if self:Sync_Finale( (typ ~= "weapon"), self.desc, self.stats_dialog, self.frame, 10 ) then
|
|
self.ammo:Show(false)
|
|
return
|
|
end
|
|
|
|
-- Ammo type
|
|
if (typ == "weapon") then
|
|
local ammo_list = utils_item.get_ammo(sec, self.id, nil)
|
|
local ammo_name = ini_sys:r_string_ex(ammo_list[1], "inv_name_short") or ""
|
|
self.ammo_txt:SetText( game.translate_string(ammo_name) )
|
|
for i=1,12 do
|
|
if self.ammo_ico[i] then
|
|
if ammo_list[i] and (ammo_list[i] ~= "ammo_12x70_buck_self") then
|
|
utils_xml.set_icon(ammo_list[i], nil, self.ammo_ico[i], self.ammo_ico_temp[i])
|
|
self.ammo_ico[i]:Show(true)
|
|
self.ammo_ico_temp[i]:Show(true)
|
|
else
|
|
self.ammo_ico[i]:Show(false)
|
|
self.ammo_ico_temp[i]:Show(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.ammo:Show(true)
|
|
else
|
|
self.ammo:Show(false)
|
|
end
|
|
|
|
-- Finale
|
|
self:Sync_Finale( true, self.stats_dialog, self.ammo, self.frame, 10 )
|
|
return
|
|
end
|
|
|
|
function UIInfoItem:Pass(obj, sec)
|
|
|
|
-- hide when no info is passed
|
|
if not (obj or sec) then
|
|
self:Reset()
|
|
return false
|
|
end
|
|
|
|
-- anticipate different object
|
|
if self.id then
|
|
if (not obj) then
|
|
self:Reset()
|
|
return false
|
|
else
|
|
if (obj:id() == self.id) then
|
|
return true
|
|
else
|
|
self:Reset()
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
-- anticipate different section
|
|
if self.section then
|
|
if (not sec) then
|
|
self:Reset()
|
|
return false
|
|
else
|
|
if (sec == self.section) then
|
|
return true
|
|
else
|
|
self:Reset()
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
-- delay
|
|
local tg = get_time()
|
|
if (tg < self.timer + self.delay) then
|
|
return false
|
|
end
|
|
|
|
self.timer = tg
|
|
return true
|
|
end
|
|
|
|
function UIInfoItem:GetType(sec)
|
|
if ini_sys:r_string_ex(sec, "ammo_class") and (not IsItem("fake_ammo_wpn", sec)) then
|
|
return "weapon"
|
|
elseif IsItem("outfit", sec) or IsItem("helmet", sec) then
|
|
return "outfit"
|
|
elseif IsItem("artefact", sec) then
|
|
return "artefact"
|
|
elseif IsItem("consumable", sec) then
|
|
return "booster"
|
|
elseif IsItem("backpack", sec) then
|
|
return "backpack"
|
|
end
|
|
return "none"
|
|
end
|
|
|
|
function UIInfoItem:GetUpgrades(obj)
|
|
if obj and IsWeapon(obj) and has_upgrades(obj) then
|
|
return utils_item.get_upgrades_installed(nil, obj:id())
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function UIInfoItem:Sync_Finale(cond, ele_syncer, ele_resizer, ele_adapter, offset)
|
|
|
|
-- Stage 1: syncing
|
|
-- Adjust element position (ele_resizer) to go below another (ele_syncer)
|
|
if ele_syncer then
|
|
self:Sync_Y(ele_syncer, ele_resizer, offset)
|
|
end
|
|
|
|
-- Stage 2: checking
|
|
-- if condition is true, go to stage 3 to finilize the info box
|
|
if (not cond) then
|
|
return false
|
|
end
|
|
|
|
-- Stage 3: resizng
|
|
-- Adjust elemet height (ele_adapter) to contain another (ele_resizer)
|
|
self:Sync_H(ele_resizer, ele_adapter, offset)
|
|
self:Show(true)
|
|
return true
|
|
end
|
|
|
|
function UIInfoItem:Sync_Y(parent, child, offset)
|
|
local pos_c = child:GetWndPos()
|
|
if (not parent) then
|
|
local y = 0 + (offset or 10)
|
|
child:SetWndPos(vector2():set( pos_c.x , y ))
|
|
return y
|
|
end
|
|
|
|
local pos_p = parent:GetWndPos()
|
|
local h_p = parent:GetHeight()
|
|
local y = pos_p.y + h_p + (offset or 10)
|
|
child:SetWndPos(vector2():set( pos_c.x , y ))
|
|
return y
|
|
end
|
|
|
|
function UIInfoItem:Sync_H(parent, child, offset)
|
|
local pos_p = parent:GetWndPos()
|
|
local h_p = parent:GetHeight()
|
|
local h = pos_p.y + h_p + offset
|
|
if h < 300 then h = 300 end
|
|
child:SetWndSize(vector2():set( child:GetWidth() , h ))
|
|
return h
|
|
end
|
|
|
|
function UIInfoItem:Reset_Y(ele)
|
|
ele:SetWndPos(vector2():set( ele:GetWndPos().x , 0 ))
|
|
end
|
|
|
|
function UIInfoItem:Reset()
|
|
self.id = nil
|
|
self.section = nil
|
|
self.timer = get_time()
|
|
end
|
|
|
|
function UIInfoItem:IsShown()
|
|
return self.dialog:IsShown()
|
|
end
|
|
|
|
function UIInfoItem:Show(state)
|
|
if state == false then
|
|
-- hide all extended info
|
|
self.stats_dialog:Show(false)
|
|
self.ammo:Show(false)
|
|
end
|
|
|
|
self.dialog:Show(state)
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------
|
|
-- Upgrade info box
|
|
-------------------------------------------------------------------
|
|
class "UIInfoUpgr"
|
|
|
|
function UIInfoUpgr:__init(owner, delay)
|
|
self.owner = owner
|
|
self.section = nil
|
|
|
|
self.timer = 0
|
|
self.delay = delay or 500
|
|
|
|
self:InitControls()
|
|
self:Show(false)
|
|
end
|
|
|
|
function UIInfoUpgr:InitControls()
|
|
self.dialog = XMLP:InitStatic("upgrade_info", self.owner)
|
|
self.frame = XMLP:InitFrame("upgrade_info:background_frame", self.dialog)
|
|
self.name = XMLP:InitTextWnd("upgrade_info:info_name", self.dialog)
|
|
self.cost = XMLP:InitTextWnd("upgrade_info:info_cost", self.dialog)
|
|
self.desc = XMLP:InitTextWnd("upgrade_info:info_desc", self.dialog)
|
|
self.prereq = XMLP:InitTextWnd("upgrade_info:info_prerequisites", self.dialog)
|
|
|
|
self.prop_frame = XMLP:InitStatic("upgrade_info:properties", self.dialog)
|
|
|
|
-- Added by Sota
|
|
self.upgr_line = XMLP:InitStatic("upgrade_info:properties:upgr_line", self.prop_frame)
|
|
|
|
self.prop = {}
|
|
self.prop_h = self.prop_frame:GetHeight()
|
|
local pos
|
|
for i=1,5 do
|
|
self.prop[i] = {}
|
|
self.prop[i].ico = XMLP:InitStatic("upgrade_info:properties:icon", self.prop_frame)
|
|
pos = self.prop[i].ico:GetWndPos()
|
|
self.prop[i].ico:SetWndPos(vector2():set( pos.x , pos.y + (self.prop_h * i) ))
|
|
|
|
self.prop[i].txt = XMLP:InitTextWnd("upgrade_info:properties:txt", self.prop_frame)
|
|
pos = self.prop[i].txt:GetWndPos()
|
|
self.prop[i].txt:SetWndPos(vector2():set( pos.x , pos.y + (self.prop_h * i) ))
|
|
end
|
|
end
|
|
|
|
function UIInfoUpgr:Update(upgr, prereq, installed)
|
|
if not self:Pass(upgr) then
|
|
self:Show(false)
|
|
return
|
|
end
|
|
|
|
-- info box is shown at cursor
|
|
sync_cursor(self.dialog, self.frame, 0, 0)
|
|
|
|
-- no need to process if it's same item
|
|
if (upgr and upgr == self.section) then
|
|
self:Show(true)
|
|
return
|
|
end
|
|
|
|
self.section = upgr
|
|
|
|
local sec = ini_sys:r_string_ex(upgr,"section")
|
|
|
|
local name = ini_sys:r_string_ex(upgr,"name")
|
|
self.name:SetText( game.translate_string(name) )
|
|
self.name:AdjustHeightToText()
|
|
|
|
self.cost:SetText( inventory_upgrades.get_upgrade_cost(sec) .. " RU" )
|
|
self:Sync_Y(self.name, self.cost, 10)
|
|
|
|
local desc = ini_sys:r_string_ex(upgr,"description")
|
|
self.desc:SetText( game.translate_string(desc) )
|
|
self.desc:AdjustHeightToText()
|
|
self:Sync_Y(self.cost, self.desc, 10)
|
|
|
|
self.prereq:SetText(prereq or "")
|
|
self.prereq:SetTextColor(installed and clr_list["p2"] or clr_list["n2"])
|
|
self.prereq:AdjustHeightToText()
|
|
self:Sync_Y(self.desc, self.prereq, 10)
|
|
|
|
local props = parse_list(ini_sys, upgr, "property")
|
|
for i,prop in ipairs(props) do
|
|
local icon = ini_sys:r_string_ex(prop,"icon")
|
|
self.prop[i].ico:InitTexture(icon)
|
|
self.prop[i].ico:Show(true)
|
|
|
|
local value = self:ExtractFunctor(prop, "functor", sec, prop) or ""
|
|
self.prop[i].txt:SetText(value)
|
|
self.prop[i].txt:Show(true)
|
|
|
|
--printf("$UIInfoUpgr | i: %s - prop: %s - icon: %s - value: %s", i, prop, icon, value)
|
|
end
|
|
|
|
for i=(#props + 1), 5 do
|
|
self.prop[i].ico:Show(false)
|
|
self.prop[i].txt:Show(false)
|
|
end
|
|
|
|
self:Sync_Y(self.prereq, self.prop_frame, 10)
|
|
-- Edited by Sota
|
|
--self:Sync_H(self.prop_frame, self.frame, (self.prop_h * #props) )
|
|
self:Sync_H(self.prop_frame, self.frame, (self.prop_h * #props) + 20 )
|
|
|
|
return
|
|
end
|
|
|
|
function UIInfoUpgr:Pass(sec)
|
|
|
|
-- hide when no info is passed
|
|
local tg = get_time()
|
|
if (not sec) then
|
|
self.timer = tg
|
|
self.section = nil
|
|
return false
|
|
end
|
|
|
|
-- anticipate different section
|
|
if self.section then
|
|
if (not sec) then
|
|
self:Reset()
|
|
return false
|
|
elseif sec and (sec == self.section) then
|
|
return true
|
|
end
|
|
end
|
|
|
|
-- delay
|
|
if (tg < self.timer + self.delay) then
|
|
return false
|
|
end
|
|
|
|
self.timer = tg
|
|
return true
|
|
end
|
|
|
|
function UIInfoUpgr:ExtractFunctor(sec, param, ...)
|
|
local func = ini_sys:r_string_ex(sec, param)
|
|
func = str_explode(func,"%.")
|
|
return func and _G[func[1]] and _G[func[1]][func[2]] and _G[func[1]][func[2]](...) or nil
|
|
end
|
|
|
|
function UIInfoUpgr:Sync_Y(parent, child, offset)
|
|
local pos_c = child:GetWndPos()
|
|
if (not parent) then
|
|
local y = 0 + (offset or 10)
|
|
child:SetWndPos(vector2():set( pos_c.x , y ))
|
|
return y
|
|
end
|
|
|
|
local y = parent:GetWndPos().y + parent:GetHeight() + (offset or 10)
|
|
child:SetWndPos(vector2():set( pos_c.x , y ))
|
|
return y
|
|
end
|
|
|
|
function UIInfoUpgr:Sync_H(parent, child, offset)
|
|
local h = parent:GetWndPos().y + parent:GetHeight() + offset
|
|
-- Edited by Sota
|
|
--if (h < 265) then h = 265 end
|
|
|
|
child:SetWndSize(vector2():set( child:GetWidth() , h ))
|
|
return h
|
|
end
|
|
|
|
function UIInfoUpgr:Reset()
|
|
self.section = nil
|
|
self.timer = get_time()
|
|
end
|
|
|
|
function UIInfoUpgr:IsShown()
|
|
return self.dialog:IsShown()
|
|
end
|
|
|
|
function UIInfoUpgr:Show(state)
|
|
self.dialog:Show(state)
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------
|
|
-- Properties list for item cells
|
|
-------------------------------------------------------------------
|
|
class "UICellProperties" (CUIScriptWnd)
|
|
|
|
function UICellProperties:__init(owner) super()
|
|
self.owner = owner
|
|
|
|
-- frame size limit, game will crash if the frame size is less that it's min defines. Always check for frame corners defines in textures_desc
|
|
self.W_L = 58
|
|
self.H_L = 40
|
|
self.PDW = 10
|
|
self.PDH = 10
|
|
self.action_moment = false
|
|
|
|
self:InitControls()
|
|
self:InitCallBacks()
|
|
end
|
|
|
|
function UICellProperties:__finalize()
|
|
if (self.owner) then
|
|
--self.owner.disabled = false
|
|
end
|
|
end
|
|
|
|
function UICellProperties:InitControls()
|
|
self:SetWndRect(Frect():set(0,0,1024,768))
|
|
self:SetAutoDelete(true)
|
|
|
|
-- these windows are just to get width/height from xml to be use for context item
|
|
local ctrl = CUIWindow()
|
|
ctrl:SetAutoDelete(true)
|
|
XMLP:InitWindow("properties:file_item:main",0,ctrl)
|
|
|
|
self.file_item_main_sz = vector2():set(ctrl:GetWidth(),ctrl:GetHeight())
|
|
|
|
XMLP:InitWindow("properties:file_item:fn",0,ctrl)
|
|
self.file_item_fn_sz = vector2():set(ctrl:GetWidth(),ctrl:GetHeight())
|
|
|
|
-- form background
|
|
self.form = XMLP:InitStatic("properties:form",self)
|
|
|
|
-- List Box
|
|
self.frame = XMLP:InitFrame("properties:form:list_frame",self.form)
|
|
self.highlight = XMLP:InitStatic("properties:highlight",self.form)
|
|
self.list_box = XMLP:InitListBox("properties:form:list",self.form)
|
|
|
|
|
|
self.list_box:ShowSelectedItem(true)
|
|
self:Register(self.list_box, "UICellProperties_list_view")
|
|
end
|
|
|
|
function UICellProperties:Update()
|
|
CUIScriptWnd.Update(self)
|
|
|
|
--[[
|
|
local pos = GetCursorPosition()
|
|
local rect = Frect():set(0,0,0,0)
|
|
self.form:GetAbsoluteRect(rect)
|
|
|
|
if not (utils_data.pos_in_rect(pos,rect)) then
|
|
if (self:IsShown()) then
|
|
self:OnHide()
|
|
return
|
|
end
|
|
end
|
|
if (self.owner) then
|
|
self.owner.disabled = true
|
|
end
|
|
--]]
|
|
|
|
|
|
for i=0,self.list_box:GetSize() do
|
|
local _itm = self.list_box:GetItemByIndex(i)
|
|
if _itm and _itm:IsCursorOverWindow() then
|
|
local pos = _itm:GetWndPos()
|
|
self.highlight:SetWndPos( vector2():set( pos.x + self.PDH/2 , pos.y + self.PDW ) )
|
|
self.highlight:SetWndSize(vector2():set( _itm.textControl:GetWidth() , _itm.textControl:GetHeight() ))
|
|
self.highlight:Show(true)
|
|
return
|
|
end
|
|
end
|
|
|
|
self.highlight:Show(false)
|
|
-- self:AllowMovement(ui_inventory.GUI.mode == "inventory")
|
|
end
|
|
|
|
function UICellProperties:Reset(pos_override, action_list, name_list, params_list)
|
|
|
|
self.H = 0
|
|
self.W = 0
|
|
|
|
-- Reset list
|
|
self:FillList(action_list, name_list, params_list)
|
|
self.action_moment = false
|
|
|
|
-- Cursor
|
|
local pos = GetCursorPosition() -- because ShowDialog moves mouse cursor to center
|
|
self:ShowDialog()
|
|
SetCursorPosition(pos)
|
|
|
|
sync_cursor(self.form)
|
|
--[[
|
|
pos = pos_override and vector2():set(pos_override.x,pos_override.y) or GetCursorPosition()
|
|
pos.x = pos.x - self.form:GetWidth() --/2
|
|
--pos.y = pos.y - 22
|
|
|
|
if (pos.x < 0) then
|
|
pos.x = 0
|
|
end
|
|
self.form:SetWndPos(pos)
|
|
--]]
|
|
end
|
|
|
|
function UICellProperties:FillList(action_list, name_list, params_list)
|
|
self.list_box:RemoveAll()
|
|
|
|
for i,str_id in pairs(name_list) do
|
|
self:AddItemToList(i, str_id, action_list[i], params_list[i])
|
|
end
|
|
|
|
if self.H < self.H_L then self.H = self.H_L end
|
|
if self.W < self.W_L then self.W = self.W_L end
|
|
|
|
local sz = vector2():set(self.W , self.H)
|
|
self.form:SetWndSize(sz)
|
|
self.frame:SetWndSize(sz)
|
|
self.list_box:SetWndSize(sz)
|
|
self.highlight:Show(false)
|
|
end
|
|
|
|
function UICellProperties:OnListItemClicked()
|
|
if self.list_box:GetSize()==0 then return end
|
|
|
|
local item = self.list_box:GetSelectedItem()
|
|
|
|
if not (item) then
|
|
return
|
|
end
|
|
end
|
|
|
|
function UICellProperties:OnListItemDbClicked()
|
|
if self.list_box:GetSize()==0 then return end
|
|
|
|
local item = self.list_box:GetSelectedItem()
|
|
if not (item) then
|
|
return
|
|
end
|
|
|
|
if self.owner and (item.func) then
|
|
if item.params then
|
|
self.owner[item.func](self.owner, unpack(item.params))
|
|
else
|
|
self.owner[item.func](self.owner)
|
|
end
|
|
|
|
self.action_moment = get_time()
|
|
end
|
|
|
|
if (self:IsShown()) then
|
|
self:OnHide()
|
|
end
|
|
end
|
|
|
|
function UICellProperties:InitCallBacks()
|
|
self:AddCallback("button_ok",ui_events.BUTTON_CLICKED,self.OnButton_ok,self)
|
|
self:AddCallback("UICellProperties_list_view",ui_events.LIST_ITEM_CLICKED,self.OnListItemDbClicked,self)
|
|
--self:AddCallback("UICellProperties_list_view",ui_events.WINDOW_LBUTTON_DB_CLICK,self.OnListItemDbClicked,self)
|
|
end
|
|
|
|
function UICellProperties:AddItemToList(index, str_id, func, params)
|
|
local _itm = UICellProperties_item()
|
|
_itm:SetWndSize(self.file_item_main_sz)
|
|
|
|
_itm.textControl:SetWndPos(vector2():set(0,0))
|
|
_itm.textControl:SetWndSize(self.file_item_fn_sz)
|
|
_itm.textControl:SetText(game.translate_string(str_id))
|
|
|
|
_itm.textControl:AdjustWidthToText()
|
|
local h = self.file_item_fn_sz.y
|
|
local w = math.ceil(_itm.textControl:GetWidth())
|
|
w = w + self.PDW
|
|
local sz = vector2():set( w , h )
|
|
_itm.textControl:SetWndSize(sz)
|
|
_itm:SetWndSize(sz)
|
|
|
|
if w > self.W then self.W = w + self.PDW end
|
|
if self.H == 0 then self.H = h end
|
|
self.H = self.H + h
|
|
|
|
_itm.func = func
|
|
_itm.params = params
|
|
|
|
self.list_box:AddExistingItem(_itm)
|
|
end
|
|
|
|
function UICellProperties:OnKeyboard(dik, keyboard_action)
|
|
CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
|
|
if (keyboard_action == ui_events.WINDOW_KEY_PRESSED) then
|
|
if (dik == DIK_keys.MOUSE_1) or (dik == DIK_keys.MOUSE_2) then
|
|
if (not self.form:IsCursorOverWindow()) then
|
|
if (self:IsShown()) then
|
|
self:OnHide()
|
|
end
|
|
end
|
|
|
|
elseif (dik == DIK_keys.DIK_ESCAPE) then
|
|
if (self:IsShown()) then
|
|
self:OnHide()
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function UICellProperties:OnHide()
|
|
if (self.owner) then
|
|
--self.owner.disabled = false
|
|
end
|
|
|
|
self:HideDialog()
|
|
end
|
|
|
|
----
|
|
class "UICellProperties_item" (CUIListBoxItem)
|
|
|
|
function UICellProperties_item:__init() super()
|
|
self:SetTextColor(GetARGB(255, 170, 170, 170))
|
|
self.textControl = self:GetTextItem()
|
|
self.textControl:SetFont(GetFontLetterica16Russian())
|
|
self.textControl:SetEllipsis(true)
|
|
end
|
|
|
|
function UICellProperties_item:__finalize()
|
|
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------
|
|
-- Hint window
|
|
-------------------------------------------------------------------
|
|
class "UIHint"
|
|
|
|
function UIHint:__init(owner, delay, path)
|
|
self.owner = owner
|
|
self.txt = ""
|
|
self.path = path or "hint_wnd"
|
|
|
|
self.timer = 0
|
|
self.delay = delay or 500 --[ms]
|
|
|
|
self:InitControls()
|
|
self:Show(false)
|
|
end
|
|
|
|
function UIHint:InitControls()
|
|
self.dialog = XMLP:InitFrame(self.path .. ":background",self.owner)
|
|
self.dialog_text = XMLP:InitTextWnd(self.path .. ":text",self.dialog)
|
|
end
|
|
|
|
function UIHint:Update(txt)
|
|
if not self:Pass(txt) then
|
|
self:Show(false)
|
|
return
|
|
end
|
|
|
|
-- no need to process if it's same txt
|
|
if (txt == self.txt) then
|
|
sync_cursor(self.dialog)
|
|
self:Show(true)
|
|
return
|
|
end
|
|
|
|
-- Set text
|
|
self.dialog_text:SetText(txt)
|
|
self.dialog_text:AdjustHeightToText()
|
|
|
|
-- Edited by Sota
|
|
-- Set wnd size
|
|
local w = self.dialog:GetWidth()
|
|
--w = w >= 96 and w or 96
|
|
--local h = self.dialog_text:GetHeight()+40
|
|
local h = self.dialog_text:GetHeight() + self.dialog_text:GetWndPos().y * 2
|
|
--h = h >= 96 and h or 96
|
|
self.dialog:SetWndSize(vector2():set(w,h))
|
|
|
|
FitInRect(self.dialog,Frect():set(0,0,1024,768),0,100)
|
|
|
|
-- box is shown at cursor
|
|
sync_cursor(self.dialog)
|
|
|
|
self.txt = txt
|
|
return
|
|
end
|
|
|
|
function UIHint:Pass(txt)
|
|
|
|
-- hide when no info is passed
|
|
local tg = get_time()
|
|
if not (txt and txt ~= "") then
|
|
self.timer = tg
|
|
self.txt = nil
|
|
return false
|
|
end
|
|
|
|
if txt == self.txt then
|
|
return true
|
|
end
|
|
|
|
-- delay
|
|
if (tg < self.timer + self.delay) then
|
|
return false
|
|
end
|
|
|
|
self.timer = tg
|
|
return true
|
|
end
|
|
|
|
function UIHint:Show(state)
|
|
self.dialog:Show(state)
|
|
end
|
|
|
|
|
|
|
|
------------------------------------------------------------
|
|
-- Utilities
|
|
------------------------------------------------------------
|
|
|
|
function prop_accuracry(obj,sec)
|
|
local fire_dispersion_base = utils_item.get_wpn_param(obj, sec, "fire_dispersion_base", 0)
|
|
return normalize(fire_dispersion_base, 1.5, 0)
|
|
end
|
|
|
|
function prop_handling(obj,sec)
|
|
local id = obj and obj:id()
|
|
local PDM_disp_base = utils_item.get_wpn_param(obj, sec, "PDM_disp_base", 0)
|
|
local control_inertion_factor = utils_item.get_wpn_param(obj, sec, "control_inertion_factor", 0)
|
|
return (normalize(PDM_disp_base, 2.1, 0) + normalize(control_inertion_factor, 3, 1))/2
|
|
end
|
|
|
|
function prop_damage(obj,sec)
|
|
local id = obj and obj:id()
|
|
local hit_power = utils_item.get_wpn_param(obj, sec, "hit_power", 0)
|
|
local ammo_list = utils_item.get_ammo(sec, id)
|
|
if ammo_list[1] then
|
|
local k_hit = ini_sys:r_float_ex(ammo_list[1], "k_hit") or 1
|
|
hit_power = (hit_power ~= 0) and (k_hit*hit_power) or k_hit
|
|
end
|
|
|
|
return normalize(hit_power, 0, 1.5)
|
|
end
|
|
|
|
function prop_rpm(obj,sec)
|
|
local rpm = utils_item.get_wpn_param(obj, sec, "rpm", 0)
|
|
return normalize(rpm, 0, 1000)
|
|
end
|
|
|
|
function prop_condition(obj,sec)
|
|
return obj and obj:condition() or 1
|
|
end
|
|
|
|
function get_utils_xml()
|
|
return XMLP
|
|
end
|