5312 lines
183 KiB
Plaintext
5312 lines
183 KiB
Plaintext
-- ======================================================================
|
|
--[[ Personal Adjustable Waypoint &
|
|
Pins Recording Intel, Notes, or Terrain
|
|
Yes, I see what I did there, and so do you.
|
|
-- ======================================================================
|
|
Author: Catspaw
|
|
I post gameplay video on my Youtube channel, Catspaw Adventures:
|
|
https://www.youtube.com/channel/UCtG8fiWPUZEzWlkUn60btAw
|
|
|
|
Source: https://www.moddb.com/mods/stalker-anomaly/addons/personal-adjustable-waypoint-for-anomaly-151-152-and-gamma
|
|
Version: 2.1.3
|
|
Updated: 20240330
|
|
|
|
You may alter any part of this mod and do whatever you like with it,
|
|
just give credit where due.
|
|
|
|
Right-click on any visible map point to set/move/remove a waypoint
|
|
or map pins. Map pins can be named, renamed, removed, and given
|
|
custom icons. The waypoint is tracked like a task. Semicolon (default)
|
|
toggles the current or most recent waypoint on/off.
|
|
|
|
To see map points, hold Slash (default, configurable in MCM) to
|
|
enter Cartography Mode. In this mode, all terrain smart points are
|
|
visible. Both the hold and the terrain display are options in MCM.
|
|
|
|
While in Cartography Mode, you can also Ping the map from the context
|
|
menu, creating a temporary grid of visible mapspots that you can use
|
|
for more precise placement.
|
|
|
|
Press Apostrophe (default) to drop a Quick Pin at the player's
|
|
current location.
|
|
|
|
Press Period or Comma (default) to cycle through active pins in the
|
|
current set, or hold Alt while doing this to cycle sets instead.
|
|
|
|
Credits: HarukaSai, RavenAscendant, Ghen Tuong, demonized, and
|
|
many others who've assisted in ways big and small.
|
|
|
|
-- ======================================================================
|
|
-- SHORTCUTS, FLAGS, AND SYSTEM STUFF
|
|
(Most of which you probably shouldn't muck with)
|
|
-- ===================================================================--]]
|
|
script_version = "2.1.3"
|
|
release_date = 20240330
|
|
local scriptname = "tasks_placeable_waypoints"
|
|
local logprefix = "<PAW> "
|
|
local language = "eng"
|
|
debuglogs = false -- Controls debug logging if you don't have MCM
|
|
verbose = true
|
|
-- Verbose being on won't do anything if debuglogs isn't also enabled,
|
|
-- but it will ensure that if anyone has to turn on debug logging,
|
|
-- their logs will contain the maximum amount of info automatically.
|
|
-- It's noisy and you can turn it off here if you have to.
|
|
-- ======================================================================
|
|
modxml_map_spots_paw.load_me = function() end -- forces DXML mapspots to load
|
|
-- ======================================================================
|
|
function dl(logtext,...)
|
|
-- Debug logging - to disable, set debuglogs to false
|
|
if logtext and debuglogs then
|
|
printf (logprefix..logtext,...)
|
|
end
|
|
end
|
|
|
|
function vl(logtext,...)
|
|
-- Verbose logging - to disable, set either debuglogs or verbose to false
|
|
if logtext and debuglogs and verbose then
|
|
dl("[V] "..logtext,...)
|
|
end
|
|
end
|
|
-- ======================================================================
|
|
mcm_killswitch = false
|
|
-- Enabling the killswitch will hard-cutoff any attempt
|
|
-- to load values from MCM, in case that is causing issues.
|
|
disable_mcm_updates = false
|
|
-- This flag will disable the immediate MCM updates that happen
|
|
-- when changing icons or sets in-game.
|
|
paw_enabled = true -- setting false will killswitch the entire addon
|
|
local icoset_changed = nil
|
|
started = false -- runtime flag
|
|
waypoint_active = false -- runtime flag
|
|
waypoint_canceling = false -- runtime flag
|
|
disable_load_warning = false
|
|
local load_failed = false -- runtime flag
|
|
welcome_msg_shown = false -- if you don't have MCM, setting this true will disable the welcome message
|
|
local get_game_time = game.get_game_time
|
|
local get_start_time = level.get_start_time
|
|
local ts = game.translate_string
|
|
local tm = task_manager.get_task_manager()
|
|
local psk = utils_data.parse_string_keys
|
|
local task_info = tm.task_info
|
|
local floor,ceil = math.floor,math.ceil
|
|
local pow,sqrt = math.pow,math.sqrt
|
|
-- ======================================================================
|
|
mousewheel_override = false
|
|
--[[ If set to true, mousewheel_override will skip the autodetection of
|
|
mousewheel support and force it to be on. This may have bad results
|
|
if your binaries don't actually support it.
|
|
|
|
Mousewheel support can also be forced on by setting the following
|
|
MCM config value (not exposed in the menu):
|
|
|
|
pawsys/pawbinds/mwheel_override = true
|
|
--]]
|
|
right_click_override = false
|
|
-- Similarly with right_click_override, but for the on_map_right_click callback
|
|
mwheel_enabled = false -- managed at runtime
|
|
mwheel_notify = true -- news tip on state change
|
|
mwheel_poll_interval = 50 -- interval between checks for mouse wheel input
|
|
mwheel_next_poll = time_global()
|
|
local mwheel_exe_ver = 20230701 -- mouse wheel support added to demonized binaries in this version
|
|
local rclick_exe_ver = 20230922 -- right-click map support added to demonized binaries in this version
|
|
local game_version = ts("ui_st_game_version")
|
|
local gamma_modpack = game_version:find("G.A.M.M.A.") -- GAMMA now supports both features (mwheel and rclick)
|
|
mwheel_avail = mousewheel_override or gamma_modpack or (MODDED_EXES_VERSION and (MODDED_EXES_VERSION >= mwheel_exe_ver))
|
|
right_click_avail = right_click_override or gamma_modpack or (MODDED_EXES_VERSION and (MODDED_EXES_VERSION >= rclick_exe_ver))
|
|
last_clicked_id = nil
|
|
-- ======================================================================
|
|
unsquish_ratio = 1
|
|
local DIK_name = ui_mcm and ui_mcm.dispaly_key or (function() return "" end)-- typo is in the mcm script
|
|
local default_id = 15797 -- WP defaults to Rookie Village if missing for any reason to avoid crash
|
|
local mcm_update_throttle = 3019 -- minimum time between MCM updates of icon/set data
|
|
local next_mcm_update = time_global()
|
|
local wp_proxcheck_interval = 837 -- Time between checks for waypoint proximity
|
|
local next_wp_proxcheck = time_global()
|
|
local garbcollect_interval = 4984 -- Time between pin/sz garbage collection checks
|
|
local next_gc_check = time_global()
|
|
local wp_clear_dist = 5
|
|
local widget_hide_delay = 5000
|
|
local next_pin = time_global()
|
|
local pin_delay = 1000 -- timeout to prevent dupe actions from registering
|
|
local ping_lifetime = 10000
|
|
local ping_grid_size = 10
|
|
local ping_grid_radius = 10
|
|
--local max_dynamic_faves = 5 -- not yet implemented
|
|
local current_active_set = "pins"
|
|
local active_theme = "classicauto"
|
|
local current_set_max = 1
|
|
local current_ico_max = 1
|
|
placed_waypoint = nil
|
|
last_waypoint = nil
|
|
-- ======================================================================
|
|
local toggle_bind = DIK_keys.DIK_SEMICOLON
|
|
local toggle_mod = 2
|
|
local quickpin_bind = DIK_keys.DIK_APOSTROPHE
|
|
local quickpin_mod = 0
|
|
local cart_mode_hold = DIK_keys.DIK_SLASH
|
|
local cart_mode_mod = 0
|
|
local mcm_keybinds = ui_mcm and ui_mcm.key_hold
|
|
cart_mode = false
|
|
cartography_must_hold = false
|
|
cart_shows_smarts = true
|
|
cartmode_unfade = true
|
|
tip_on_icoset_change = false
|
|
allow_non_wp_targets = false
|
|
local pin_tooltip_mode = 2
|
|
-- ======================================================================
|
|
enable_wp_proxcheck = true
|
|
show_pins = true
|
|
local script_zone_changed = false -- runtime flag
|
|
local custom_task_info = false
|
|
local icon_cycle_active = false
|
|
local set_cycle_active = false
|
|
local psw_sidebar_state = true
|
|
widget_enabled = true
|
|
widget_active = true
|
|
hide_widget = true
|
|
widget_use_custom_pos = false
|
|
widget_custom_pos = {x=491,y=670}
|
|
widget_last_used = time_global()
|
|
wp_hud_icon_enabled = true
|
|
pin_hud_icon_default = true
|
|
manual_smart_pins = false
|
|
mark_on_positive_id = true
|
|
reticle_mustzoom = true
|
|
reticle_mode = 2
|
|
autotag_mode = 0
|
|
autotag_persistence = false -- if enabled, autotags are cleared on map change or the below timeout value
|
|
autotag_lifetime = 120 * 6 -- time in ms before autotags are cleared (def 2 minutes)
|
|
autotags_time_out = autotag_lifetime > 0
|
|
clear_pin_on_death = true -- when set on a living thing, pin will be cleared if it dies
|
|
pin_near_fade_dist = 5 -- min distance within which pins will begin to fade out, set to 0 to disable
|
|
pin_far_fade_dist = 100 -- distance beyond which pins will begin to fade out, set to 0 to disable
|
|
pin_far_hide_dist = 150 -- max distance after far_fade at which pins will hide, set to 0 to disable
|
|
wp_near_fade_dist = 5 -- same but for waypoints
|
|
wp_far_fade_dist = 100 -- same but for waypoints
|
|
wp_far_hide_dist = 150 -- same but for waypoints
|
|
ret_fade_attack_time = 400
|
|
ret_fade_decay_time = 600
|
|
|
|
reticle_color = {
|
|
["a"] = 150,
|
|
["r"] = 255,
|
|
["g"] = 255,
|
|
["b"] = 255,
|
|
}
|
|
|
|
show_marker_dist = {
|
|
["pins"] = 4,
|
|
["wp"] = 4,
|
|
}
|
|
|
|
show_marker_hint = {
|
|
["pins"] = 2,
|
|
["wp"] = 0, -- not implemented yet
|
|
}
|
|
|
|
-- ======================================================================
|
|
-- STRINGS AND LTX DATA
|
|
-- ======================================================================
|
|
local cartmode = "cartmode"
|
|
local sep = "_"
|
|
local snd_path = "catspaw\\"
|
|
local snd_ping = snd_path.."paw_ping"
|
|
local snd_cycle_blip = snd_path.."paw_blip"
|
|
local snd_tag_target = snd_path.."paw_blip"
|
|
local snd_place_pin = snd_path.."paw_pin"
|
|
local snd_note = "device\\pda\\pda_note"
|
|
local use_ping_snd = true
|
|
local use_ui_snd = true
|
|
local add_mapspot_functor = scriptname..".func_add_mapspot"
|
|
local ren_mapspot_functor = scriptname..".func_ren_mapspot"
|
|
local ren_wp_functor = scriptname..".func_ren_waypoint"
|
|
local task_id = "task_placeable_waypoint"
|
|
local pawmenu_path = "ui_mcm_pawsys_pawmenu_"
|
|
local hint_path = "ui_paw_hint_"
|
|
-- Don't change any of these icon definitions. If you want to
|
|
-- override PAW's pin icons with any of yours, use MCM or
|
|
-- see below for how to add your own, it's easy.
|
|
current_body_icon = nil
|
|
body_icon_mode = "off"
|
|
patch_res = "badge"
|
|
local custom_pin_icon = false
|
|
use_custom_backpack_icon = false -- Customize the icon for player stashes
|
|
init_backpack_as_pin = true -- Player stash icons are created as pins
|
|
local default_mapspot = "paw_pin_redpush32"
|
|
local smart_terrain_icon = "paw_pin_magnifier32"
|
|
local icon_pingspot = "paw_ping_alpha50"
|
|
waypoint_mapspot = "paw_task_default"
|
|
map_pin_icon = default_mapspot
|
|
force_icon_override = nil
|
|
-- If force_icon_override is set to anything, PAW will try to use it
|
|
-- for pins instead of what it normally would.
|
|
-- This is purely a debugging tool. There are better ways to use your own
|
|
-- custom icons.
|
|
-- ======================================================================
|
|
icons_ini = ini_file_ex("scripts\\paw\\icons.ltx")
|
|
icon_sets_ini = ini_file_ex("scripts\\paw\\icon_sets.ltx")
|
|
actions_ini = ini_file_ex("scripts\\paw\\menu_actions.ltx")
|
|
task_ini = ini_file_ex("scripts\\paw\\task_config.ltx")
|
|
clsids_ini = ini_file_ex("scripts\\paw\\valid_clsids.ltx")
|
|
icon_ltx = icons_ini:collect_section("icons")
|
|
iconset_ltx = icon_sets_ini:get_sections(true)
|
|
actions_ltx = actions_ini:get_sections(true)
|
|
clsids_ltx = clsids_ini:collect_section("valid_clsids")
|
|
task_cfg = task_ini:collect_section("task_config")
|
|
custom_name = (task_cfg and task_cfg.name)
|
|
custom_desc = (task_cfg and task_cfg.desc)
|
|
icons = icon_ltx
|
|
curr_menu_options = {}
|
|
icon_sets = {}
|
|
action_codes = {}
|
|
action = {}
|
|
texture_data = {}
|
|
icon_index = {}
|
|
set_index = {}
|
|
valid_clsids = {}
|
|
map_labels = {}
|
|
waypoint_history = {} -- not implemented yet
|
|
local script_zones = {}
|
|
local pings = {}
|
|
local pawdata = {
|
|
pins = {},
|
|
--dynamic_faves = {},
|
|
curr_set_ind = 1,
|
|
curr_ico_ind = 1,
|
|
curr_set_name = "pins",
|
|
curr_ico_name = default_mapspot,
|
|
}
|
|
pawdata.smart_pins = {
|
|
["human_f"] = {
|
|
pin = "chevron_friendly",
|
|
enabled = false,
|
|
},
|
|
["human_n"] = {
|
|
pin = "chevron_neutral",
|
|
enabled = false,
|
|
},
|
|
["human_e"] = {
|
|
pin = "chevron_enemy",
|
|
enabled = true,
|
|
},
|
|
["monster"] = {
|
|
pin = "chevron_enemy",
|
|
enabled = true,
|
|
},
|
|
["stash"] = {
|
|
pin = "bwhr_loot",
|
|
enabled = false,
|
|
},
|
|
}
|
|
pawdata.npc_ident = {
|
|
delay_id = true,
|
|
id_bodies = false,
|
|
id_speed = 0.3,
|
|
lenience = 0.99,
|
|
tick_speed = 200,
|
|
progress = {},
|
|
}
|
|
pawdata.wphist = {}
|
|
waypoint_history = pawdata.wphist
|
|
npc_ident = pawdata.npc_ident
|
|
smart_pins = pawdata.smart_pins
|
|
pins = pawdata.pins
|
|
dynamic_faves = pawdata.dynamic_faves -- not implemented yet
|
|
|
|
-- ======================================================================
|
|
pda_defs = {
|
|
-- By default, all PDAs support waypointing and autotag
|
|
["device_pda_1"] = {
|
|
show_w = true,
|
|
autotag = true,
|
|
},
|
|
["device_pda_2"] = {
|
|
show_w = true,
|
|
autotag = true, },
|
|
["device_pda_3"] = {
|
|
show_w = true,
|
|
autotag = true, },
|
|
["device_pda_milspec"] = {
|
|
show_w = true,
|
|
autotag = true,
|
|
},
|
|
-- If you use an addon with an unsupported PDA section, add it here
|
|
-- ["device_pda_added_by_your_mod"] = {
|
|
-- show_w = false,
|
|
-- autotag = false,
|
|
-- },
|
|
}
|
|
|
|
|
|
local default_stash_icon_basic = "treasure"
|
|
local default_stash_icon_rare = "treasure_searched"
|
|
local default_stash_icon_isg = "treasure_unique"
|
|
local default_stash_icon_player = "paw_stash_backpack"
|
|
|
|
stash_icons = {
|
|
["basic"] = axr_main.config:r_value("mcm", "pawsys/custom_stash_icon_basic", {val=0}) or default_stash_icon_basic, -- Normal stashes
|
|
["rare"] = axr_main.config:r_value("mcm", "pawsys/custom_stash_icon_rare", {val=0}) or default_stash_icon_rare, -- Rare stashes
|
|
["isg"] = axr_main.config:r_value("mcm", "pawsys/custom_stash_icon_isg", {val=0}) or default_stash_icon_isg, -- Special (e.g. ISG) stashes
|
|
["player"] = axr_main.config:r_value("mcm", "pawsys/custom_stash_icon_player", {val=0}) or default_stash_icon_player, -- Custom player backpack stashes
|
|
}
|
|
|
|
managed_factions = {
|
|
-- editing this may cause crashes or other unexpected results
|
|
["army"] = true,
|
|
["bandit"] = true,
|
|
["csky"] = true,
|
|
["dolg"] = true,
|
|
["ecolog"] = true,
|
|
["freedom"] = true,
|
|
["killer"] = true,
|
|
["monolith"] = true,
|
|
["stalker"] = true,
|
|
["greh"] = true,
|
|
["isg"] = true,
|
|
["renegade"] = true,
|
|
}
|
|
|
|
managed_options = {
|
|
-- editing this may cause context menus to behave oddly
|
|
["mping"] = true,
|
|
["wp_set"] = true,
|
|
["wp_mov"] = true,
|
|
["wp_del"] = true,
|
|
["waypoint_rename"] = true, -- deprecated, included here so it doesn't appear if someone re-adds it
|
|
["waypoint_redesc"] = true, -- deprecated
|
|
["hud_vis_on"] = true,
|
|
["hud_vis_off"] = true,
|
|
["show_all_pins"] = true,
|
|
["hide_all_pins"] = true,
|
|
["show_label"] = true,
|
|
["hide_label"] = true,
|
|
["pn_add"] = true,
|
|
["pn_del"] = true,
|
|
["pn_ren"] = true, -- deprecated
|
|
["pn_clr"] = true,
|
|
["pn_settings"] = true,
|
|
["wp_settings"] = true,
|
|
["lock_pin"] = true,
|
|
["unlock_pin"] = true,
|
|
["convert_to_pin"] = true,
|
|
["cm_dbg"] = true,
|
|
}
|
|
|
|
hud_themes = {
|
|
["classicauto"] = {
|
|
name = "classicauto",
|
|
node = "pawhudind",
|
|
style = "full",
|
|
tex = "ui_paw_hud_indicator_classic",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=890,y=620},
|
|
w = 136,
|
|
h = 75,
|
|
pda_thm = "vertright",
|
|
},
|
|
["classic"] = {
|
|
name = "classic",
|
|
node = "pawhudind",
|
|
style = "full",
|
|
tex = "ui_paw_hud_indicator_classic",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=890,y=620},
|
|
w = 136,
|
|
h = 75,
|
|
},
|
|
["vertright"] = {
|
|
name = "vertright",
|
|
node = "pawhudind_vertright",
|
|
style = "minimal",
|
|
tex = "ui_paw_hud_indicator_vertright",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=922,y=440},
|
|
w = 100,
|
|
h = 154,
|
|
},
|
|
["vertleft"] = {
|
|
name = "vertleft",
|
|
node = "pawhudind_vertleft",
|
|
style = "minimal",
|
|
tex = "ui_paw_hud_indicator_vertleft",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=4,y=570},
|
|
w = 100,
|
|
h = 154,
|
|
},
|
|
["gamma_right"] = {
|
|
name = "gamma_right",
|
|
node = "pawhudind_gamma_right",
|
|
style = "full",
|
|
tex = "ui_paw_hud_indicator_gamma_right",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=888,y=440},
|
|
w = 130,
|
|
h = 150,
|
|
},
|
|
["gamma_left"] = {
|
|
name = "gamma_left",
|
|
node = "pawhudind_gamma_left",
|
|
style = "full",
|
|
tex = "ui_paw_hud_indicator_gamma_left",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=4,y=440},
|
|
w = 130,
|
|
h = 150,
|
|
},
|
|
["minimal_h"] = {
|
|
name = "minimal_h",
|
|
node = "pawhudind_minimal_h",
|
|
style = "minimal",
|
|
tex = "ui_paw_hud_indicator_minimal_h",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=924,y=645},
|
|
w = 94,
|
|
h = 52,
|
|
},
|
|
["minimal_v"] = {
|
|
name = "minimal_v",
|
|
node = "pawhudind_minimal_v",
|
|
style = "minimal",
|
|
tex = "ui_paw_hud_indicator_minimal_v",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=924,y=440},
|
|
w = 92,
|
|
h = 112,
|
|
},
|
|
["minicom"] = {
|
|
name = "minicom",
|
|
node = "pawhudind_minicom",
|
|
style = "compact",
|
|
tex = "ui_paw_hud_indicator_minicom",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=820,y=725},
|
|
w = 38,
|
|
h = 37,
|
|
},
|
|
["compact_noui"] = {
|
|
name = "compact_noui",
|
|
node = "pawhudind_minicom",
|
|
style = "compact",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=820,y=725},
|
|
w = 32,
|
|
h = 37,
|
|
pre_tex = "ui_paw_hud_indicator_minicom",
|
|
},
|
|
["pin_sidebar"] = {
|
|
name = "pin_sidebar",
|
|
node = "pawhudind_pin_sidebar",
|
|
style = "full",
|
|
tex = "ui_paw_dialog_sidebar",
|
|
file = "paw_ui_elements.xml",
|
|
pos = {x=0,y=0},
|
|
w = 161.25,
|
|
h = 188,
|
|
},
|
|
}
|
|
|
|
|
|
colors = {
|
|
dimmed = GetARGB(100, 255, 255, 255),
|
|
active = GetARGB(255, 255, 255, 255),
|
|
}
|
|
|
|
text_colors = {
|
|
["clr_255"] = "%" .. "%c[255,255,255,255]",
|
|
["clr_red"] = "%" .. "%c[255,255,0,0]",
|
|
["clr_orn"] = "%" .. "%c[255,255,140,0]",
|
|
["clr_grn"] = "%" .. "%c[255,0,255,0]",
|
|
["clr_blu"] = "%" .. "%c[255,0,0,255]",
|
|
["clr_lbl"] = "%" .. "%c[255,0,200,220]",
|
|
["clr_yel"] = "%" .. "%c[255,250,218,94]",
|
|
["clr_wht"] = "%" .. "%c[255,220,220,220]",
|
|
["clr_prp"] = "%" .. "%c[255,138,43,226]",
|
|
["clr_blk"] = "%" .. "%c[255,0,0,0]",
|
|
}
|
|
|
|
null_tokens = {
|
|
["clr_255"] = "",
|
|
["clr_red"] = "",
|
|
["clr_grn"] = "",
|
|
["clr_blu"] = "",
|
|
["clr_lbl"] = "",
|
|
["clr_yel"] = "",
|
|
["clr_wht"] = "",
|
|
["clr_prp"] = "",
|
|
["clr_blk"] = "",
|
|
|
|
}
|
|
|
|
local keybinds = {
|
|
["cartmode"] = {
|
|
enabled = function() return paw_enabled end,
|
|
hold = cartography_must_hold,
|
|
bind = DIK_keys.DIK_SLASH,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_cartmode",
|
|
action = function(tf)
|
|
if tf == nil then
|
|
tf = not cart_mode
|
|
end
|
|
cartography_mode(tf)
|
|
end,
|
|
},
|
|
|
|
["wp_target_obj"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_SEMICOLON,
|
|
mod = 3,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_wp_target",
|
|
action = function() wp_target_obj() end,
|
|
},
|
|
["pin_target_obj"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_APOSTROPHE,
|
|
mod = 3,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_pin_target",
|
|
action = function() pin_target_obj(nil,nil,nil,manual_smart_pins) end,
|
|
},
|
|
["quickpin"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_APOSTROPHE,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_quickpin",
|
|
action = function() drop_quick_pin() end,
|
|
},
|
|
["wptoggle"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_SEMICOLON,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_wptoggle",
|
|
action = function() toggle_waypoint() end,
|
|
},
|
|
["set_next"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_PERIOD,
|
|
mod = 3,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_set_next",
|
|
action = function() cycle_items(1,"set",tip_on_icoset_change) end,
|
|
},
|
|
["set_prev"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_COMMA,
|
|
mod = 3,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_set_prev",
|
|
action = function() cycle_items(-1,"set",tip_on_icoset_change) end,
|
|
},
|
|
["ico_next"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_PERIOD,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_ico_next",
|
|
action = function() cycle_items(1,"icon",tip_on_icoset_change) end,
|
|
},
|
|
["ico_prev"] = {
|
|
enabled = function() return paw_enabled end,
|
|
bind = DIK_keys.DIK_COMMA,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_ico_prev",
|
|
action = function() cycle_items(-1,"icon",tip_on_icoset_change) end,
|
|
},
|
|
["ico_scroll"] = {
|
|
enabled = function() return paw_enabled and mwheel_enabled end,
|
|
bind = DIK_keys.DIK_Z,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_ico_scroll",
|
|
mod = 3,
|
|
hold = true,
|
|
action = function(tf) icon_cycle(true,tf) end,
|
|
},
|
|
["set_scroll"] = {
|
|
enabled = function() return paw_enabled and mwheel_enabled end,
|
|
bind = DIK_keys.DIK_Z,
|
|
name = "ui_mcm_pawsys_pawbinds_bind_set_scroll",
|
|
mod = 2,
|
|
hold = true,
|
|
action = function(tf) set_cycle(true,tf) end,
|
|
},
|
|
}
|
|
|
|
local hover_elements = {
|
|
["btn_iprev"] = "icon",
|
|
["btn_inext"] = "icon",
|
|
["btn_sprev"] = "set",
|
|
["btn_snext"] = "set",
|
|
["logo_set"] = "set",
|
|
["box_curr"] = "icon",
|
|
["box_prev"] = "icon",
|
|
["box_next"] = "icon",
|
|
["box_text"] = "set",
|
|
["box_text2"] = "icon",
|
|
["btn_apply"] = "icon",
|
|
}
|
|
|
|
-- ======================================================================
|
|
-- GENERAL UTILITY FUNCTIONS
|
|
-- ======================================================================
|
|
|
|
function exec(str,...)
|
|
if str then
|
|
str = str_explode(str,"%.")
|
|
if str[1] and str[2] and _G[ str[1] ] and _G[ str[1] ][ str[2] ] then
|
|
_G[ str[1] ][ str[2] ](...)
|
|
else
|
|
dl("Could not exec function %s", str)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function delay_exec_of(func,secs,...)
|
|
if not func then return end
|
|
secs = secs or 0
|
|
CreateTimeEvent("pawdelay","paw"..tostring(time_global()),secs,func,...)
|
|
end
|
|
|
|
|
|
function dotip(tiptext,dur,src,beep,icon,snd)
|
|
vl("Tip call received: dur %s | src \"%s\" | beep %s\n\"%s\"",dur,src,beep,tiptext)
|
|
if tiptext == nil then return end
|
|
db.actor:give_game_news(src or "PAW System", tiptext, icon or "ui_inGame2_Mesta_evakuatsii", 0, dur or 5000)
|
|
|
|
if beep then
|
|
xr_sound.set_sound_play(AC_ID, snd or "pda_tips")
|
|
end
|
|
end
|
|
|
|
function get_time_elapsed()
|
|
return math.floor(get_game_time():diffSec(get_start_time()))
|
|
end
|
|
|
|
function round2(n)
|
|
return (math.floor(n * 100) / 100)
|
|
end
|
|
|
|
|
|
function roll(val,min,max)
|
|
if not (val and min and max) then return end
|
|
if val > max then
|
|
return min
|
|
elseif val < min then
|
|
return max
|
|
else
|
|
return val
|
|
end
|
|
end
|
|
|
|
function lerp(a, b, f)
|
|
if a and b and f then
|
|
return a + f * (b - a)
|
|
else
|
|
return a or b or 0
|
|
end
|
|
end
|
|
|
|
function paw_enabled_check()
|
|
if not paw_enabled then
|
|
actor_menu.set_msg(1,game.translate_string("st_paw_system_disabled"),5)
|
|
end
|
|
return paw_enabled
|
|
end
|
|
|
|
function valid_bind(kb)
|
|
return (kb ~= nil) and (kb ~= "") and (kb ~= "<!!!>") and (kb ~= -1)
|
|
end
|
|
|
|
|
|
function bindtext(kb,km)
|
|
local kbt = ""
|
|
local kmt = ""
|
|
local mt = ""
|
|
local vbkb = valid_bind(kb)
|
|
local vbkm = km and km > 0
|
|
if vbkb then
|
|
kbt = DIK_name(kb)
|
|
end
|
|
if vbkm then
|
|
if km and km < 29 then
|
|
km = ((km == 1) and 42) or ((km == 2) and 29) or ((km == 3) and 56)
|
|
end
|
|
if km then
|
|
kmt = DIK_name(km)
|
|
end
|
|
end
|
|
|
|
if vbkb and vbkm then
|
|
mt = "+"
|
|
elseif not (vbkb or vbkm) then
|
|
kmt = "[UNBOUND]"
|
|
mt = ""
|
|
kbt = ""
|
|
end
|
|
|
|
return string.format("%s%s%s",kmt,mt,kbt)
|
|
end
|
|
|
|
|
|
-- ======================================================================
|
|
function safeid(obj)
|
|
local id = obj and obj.id
|
|
if not id and obj then return end
|
|
if type(id) ~= "number" then id = obj:id() end
|
|
return id
|
|
end
|
|
|
|
function safename(id)
|
|
if not (id and (id > 0)) then return end
|
|
local text = ts("st_paw_unknown")
|
|
local se_obj = alife_object(id)
|
|
if not se_obj then return text end
|
|
local name = se_obj:name() or text
|
|
local cls = se_obj:clsid()
|
|
|
|
if pins[id] and not script_zones[id] then
|
|
-- If there's a pin for this ID, use its text above all else
|
|
text = pins[id].name
|
|
vl("%s (%s) is a pin: %s",name,id,text)
|
|
elseif (cls == clsid.script_zone) then
|
|
text = ts("st_paw_pin_default_name")
|
|
vl("%s (%s) is a script zone: %s",name,id,text)
|
|
elseif (cls == clsid.script_restr) then
|
|
local _,_,hint = txr_routes.get_route_info(name)
|
|
if hint then
|
|
text = hint and ts(hint) or text
|
|
else
|
|
text = ts(name)
|
|
end
|
|
vl("%s (%s) is a level transition: %s",name,id,text)
|
|
elseif (cls == clsid.smart_terrain) then
|
|
text = ts("st_"..name.."_name"):gsub("%."," -")
|
|
vl("%s (%s) is a smart terrain: %s",name,id,text)
|
|
elseif (cls == clsid.online_offline_group_s) then
|
|
local comm = se_obj.player_id
|
|
local sq = ts("st_paw_squad")
|
|
if managed_factions[comm] then
|
|
text = ts(comm)
|
|
end
|
|
text = text.." "..sq
|
|
if debuglogs then
|
|
text = text..": "..name
|
|
end
|
|
vl("%s (%s) is NPC squad with faction %s: %s",name,id,comm,text)
|
|
elseif IsInvbox(nil,cls) then
|
|
local locst = "st_"..name.."_name"
|
|
text = ts(locst)
|
|
if text == locst then
|
|
dl("No localization found for stash %s",locst)
|
|
text = ts("st_paw_unknown").." "..ts("st_paw_stash")
|
|
if debuglogs then
|
|
text = text..": "..name
|
|
end
|
|
end
|
|
vl("%s (%s) is a stash marker: %s",name,id,text)
|
|
elseif IsStalker(nil,cls) then
|
|
text = se_obj:character_name()
|
|
vl("%s (%s) is a stalker: %s",name,id,text)
|
|
elseif IsMonster(nil,cls) then
|
|
local obj = get_object_by_id(id)
|
|
local section = obj and obj:section()
|
|
if not section then
|
|
return text
|
|
end
|
|
--[[
|
|
Hack adapted from ui_enemy_health.script
|
|
This logic acts as a translation layer for
|
|
any monster kind/species that doesn't line
|
|
up with the name of its encyclopedia entry
|
|
--]]
|
|
local special_cases = {
|
|
dog = "blind_dog",
|
|
bird = "crow",
|
|
giant = "pseudogiant",
|
|
SM_KARLIK = "karlik",
|
|
SM_LURKER = "lurker",
|
|
SM_POLTER_G = "poltergeist",
|
|
SM_PYRO_G = "pyrogeist",
|
|
SM_PSEUDO_G = "pseudogeist",
|
|
SM_PSYSUCKER = "psysucker",
|
|
}
|
|
if string.find(section,'rotan') then
|
|
text = "rat"
|
|
elseif string.find(section,'psy_dog') then
|
|
text = "psydog"
|
|
else
|
|
local what = ini_sys:r_string_ex(section,"kind") or ini_sys:r_string_ex(section,"species") or nil
|
|
text = special_cases[what] or what
|
|
end
|
|
--text = string.lower(ts("encyclopedia_mutants_"..text))
|
|
text = ts("encyclopedia_mutants_"..text)
|
|
vl("%s (%s) is a creature: %s",name,id,text)
|
|
else
|
|
text = ts(name)
|
|
if text == name then
|
|
text = ts(name.."_name")
|
|
if text == name.."_name" then
|
|
text = name
|
|
dl("No localization or other name found for object %s (%s)",name,id)
|
|
end
|
|
end
|
|
end
|
|
dl("safename returns %s for %s",text,name)
|
|
return text
|
|
end
|
|
|
|
|
|
function valid_pda(feature)
|
|
feature = feature or "show_w"
|
|
local dev = db.actor and db.actor:item_in_slot(8)
|
|
local sec = dev and dev:section()
|
|
if not sec then return false end
|
|
if dev and pda_defs[sec] then
|
|
if pda_defs[sec][feature] then return true end
|
|
elseif item_device.device_npc_pda[sec] then
|
|
local text = ts("st_paw_npc_pda_equipped")
|
|
dotip(text)
|
|
else
|
|
dl("WARNING: Equipped PDA %s not found in pda_defs - if this is a valid player PDA, add to that table to enable support",sec)
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
function blacklisted_object(id)
|
|
if not (id and (id > 0)) then return true end
|
|
|
|
local se_obj = alife_object(id)
|
|
|
|
if not se_obj then return true end
|
|
|
|
local cls = se_obj:clsid()
|
|
if (cls == clsid.poltergeist_s) or
|
|
(cls == clsid.psy_dog_phantom_s) then
|
|
return true end
|
|
|
|
end
|
|
|
|
function valid_waypoint_target(se_obj)
|
|
if not se_obj then return end
|
|
if blacklisted_object(se_obj.id) then return end
|
|
-- can add other smart types to this logic later if needed
|
|
local clsid = se_obj:clsid()
|
|
local valid = (valid_clsids[clsid] ~= nil) or
|
|
IsStalker(se_obj) or
|
|
IsMonster(se_obj) or
|
|
isLc(se_obj)
|
|
return valid
|
|
end
|
|
|
|
function feature_valid_in_mode(mode)
|
|
-- -1: debug mode only
|
|
-- 0: disabled
|
|
-- 1: enabled in normal view only
|
|
-- 2: enabled in cartography mode only
|
|
-- 4: enabled in both
|
|
return ((mode < 0) and debuglogs) or
|
|
((mode == 1) and not cart_mode) or
|
|
((mode >= 2) and cart_mode) or
|
|
(mode >= 4)
|
|
end
|
|
|
|
|
|
function play_sound_for_actor(effect)
|
|
local snd = xr_sound.get_safe_sound_object(effect)
|
|
snd:play(db.actor, 0, sound_object.s2d)
|
|
end
|
|
|
|
function play_ui_sound(effect)
|
|
if effect and use_ui_snd then
|
|
play_sound_for_actor(effect)
|
|
end
|
|
end
|
|
|
|
function add_mapspot(text,id,icon)
|
|
if not id then return end
|
|
icon = icon or default_mapspot
|
|
text = text or get_tooltip_for_pin(id) or ""
|
|
vl("Adding mapspot %s for id %s with icon %s",text,id,icon)
|
|
level.map_add_object_spot(id,icon,text)
|
|
if not pins[id] then return end
|
|
|
|
local pin = pins[id]
|
|
if pin.custom_colors and pin.colors then
|
|
local clr = pin.colors
|
|
local spot = level.map_get_object_spot_static(id,icon)
|
|
spot:SetTextureColor(GetARGB(clr.a, clr.r, clr.g, clr.b))
|
|
end
|
|
if pin.hud then
|
|
show_hud_pin(id)
|
|
end
|
|
if pin.show_label then
|
|
show_pin_label(id,true)
|
|
end
|
|
return true
|
|
end
|
|
|
|
|
|
function remove_mapspot(id,icon)
|
|
if not (id and icon) then return end
|
|
vl("Trying to remove mapspot for id %s with icon %s",id,icon)
|
|
|
|
local pin = pins[id]
|
|
if pin and pin.show_label then
|
|
show_pin_label(id,false,true)
|
|
end
|
|
if pin and pin.hud then
|
|
hide_hud_pin(id)
|
|
end
|
|
level.map_remove_object_spot(id,icon)
|
|
level.map_remove_object_spot(id,icon) -- this operation sometimes doesn't work the first time
|
|
return true
|
|
end
|
|
|
|
|
|
function change_mapspot(text,id,icon,old_icon)
|
|
if not id then return end
|
|
text = text or get_tooltip_for_pin(id)
|
|
icon = icon or (pins and pins[id] and pins[id].icon) or default_mapspot
|
|
old_icon = old_icon or icon
|
|
vl("Trying to change mapspot with id %s from icon %s to icon %s with text %s",id,old_icon,icon,text)
|
|
remove_mapspot(id,old_icon)
|
|
return add_mapspot(text,id,icon)
|
|
end
|
|
|
|
function get_tooltip_for_pin(id)
|
|
local pin = pins and pins[id]
|
|
local text = ""
|
|
if pin then
|
|
local mode = pin.tooltip or pin_tooltip_mode
|
|
if mode > 1 then
|
|
text = pin.text or pin.name or ts("st_paw_pin_default_name")
|
|
elseif mode > 0 then
|
|
text = pin.name or ts("st_paw_pin_default_name")
|
|
end
|
|
vl("get_tooltip_for_pin(%s): tooltip mode %s\n* Returning hint: \"%s\"",id,mode,text)
|
|
return text
|
|
end
|
|
end
|
|
|
|
function has_mapspot(id,icon)
|
|
return level.map_has_object_spot(id,icon) == 1
|
|
end
|
|
|
|
function get_mapspot(id,icon)
|
|
local found
|
|
if icon then
|
|
return has_mapspot(id,icon) and icon
|
|
else
|
|
for k,v in pairs(stash_icons) do
|
|
local has_spot = has_mapspot(id,v)
|
|
--printf("id %s has mapspot %s: %s",id,v,has_spot)
|
|
if has_spot then
|
|
found = v
|
|
--printf("found %s",found)
|
|
--return v
|
|
|
|
end
|
|
end
|
|
end
|
|
return found
|
|
end
|
|
|
|
|
|
function set_mapspot_colors(id,icon,a,r,g,b)
|
|
if not (id and icon and a and r and g and b) then return end
|
|
local pin = pins[id]
|
|
if pin and pin.colors then
|
|
local clr = pin.colors
|
|
local spot = level.map_get_object_spot_static(id,icon)
|
|
if spot then spot:SetTextureColor(GetARGB(clr.a, clr.r, clr.g, clr.b)) end
|
|
end
|
|
end
|
|
|
|
|
|
function remove_stash_mapspots(id)
|
|
level.map_remove_object_spot(id,"treasure")
|
|
level.map_remove_object_spot(id,"treasure")
|
|
for _,mapspot in pairs(stash_icons) do
|
|
dl("Attempting to remove stash mapspot \"%s\" for ID %s",mapspot,id)
|
|
level.map_remove_object_spot(id,mapspot)
|
|
level.map_remove_object_spot(id,mapspot)
|
|
end
|
|
end
|
|
|
|
|
|
function func_ren_waypoint(text,args)
|
|
if text == "" then text = nil end
|
|
local field = args.field
|
|
if field == "name" then
|
|
custom_name = text
|
|
elseif field == "desc" then
|
|
custom_desc = text
|
|
end
|
|
end
|
|
|
|
|
|
function pins_exist()
|
|
return not is_empty(pins)
|
|
end
|
|
|
|
function pin_exists(id)
|
|
return pins[id] and true or false
|
|
end
|
|
|
|
|
|
function can_convert_to_pin(id)
|
|
if not (id and (id > 0) and (id < 65535)) then return end
|
|
|
|
local se_obj = alife_object(id)
|
|
if not se_obj then return end
|
|
|
|
local cls = se_obj:clsid()
|
|
local is_stash = IsInvbox(nil,cls)
|
|
local mapspot = get_mapspot(id)
|
|
local is_pin = pin_exists(id)
|
|
local can_convert = mapspot and is_stash and not is_pin
|
|
vl("can_convert_to_pin(%s): is_stash: %s | is a pin: %s | mapspot: %s | can_convert = %s",id,is_stash,is_pin,mapspot,can_convert)
|
|
|
|
return can_convert
|
|
end
|
|
|
|
|
|
function cancel_task()
|
|
local id = placed_waypoint and placed_waypoint.id
|
|
tm.task_info[task_id] = nil
|
|
if id then
|
|
remove_mapspot(id, waypoint_mapspot)
|
|
set_pingspot_persistence(id,false)
|
|
end
|
|
waypoint_active = false
|
|
placed_waypoint = nil
|
|
dl("Waypoint task cancellation complete for %s",id)
|
|
waypoint_canceling = false
|
|
return true
|
|
end
|
|
|
|
|
|
function end_waypoint_task()
|
|
waypoint_canceling = true
|
|
return cancel_task()
|
|
end
|
|
|
|
|
|
function set_current_waypoint(se_obj)
|
|
if not se_obj then return end
|
|
local id = se_obj.id
|
|
set_pingspot_persistence(id)
|
|
if waypoint_active then
|
|
last_waypoint = placed_waypoint
|
|
end
|
|
placed_waypoint = {
|
|
id = id,
|
|
name = safename(id),
|
|
}
|
|
waypoint_active = true
|
|
waypoint_canceling = false
|
|
end
|
|
|
|
function valid_travel_target(id)
|
|
-- To enable interaction with the Fair Fast Travel
|
|
-- system addon, allowing fast travel to pins, but
|
|
-- only those that we know are within the playable
|
|
-- area--ones spawned at a spot where the player was
|
|
-- standing at the time.
|
|
local pin = pins and id and pins[id]
|
|
local valid = pin and pin.quick
|
|
vl("valid_travel_target | id %s is pin: %s | is quick pin %s",id,pin,valid)
|
|
return valid
|
|
end
|
|
|
|
function init_new_pin(id,name,text,icon)
|
|
if id and not pins[id] then
|
|
icon = icon or default_mapspot
|
|
set_pingspot_persistence(id)
|
|
pins[id] = {
|
|
id = id,
|
|
name = name or ts("st_paw_pin_default_name"),
|
|
text = text,
|
|
icon = icon,
|
|
hud = false
|
|
}
|
|
--rotate_dynamic_favorites(icon)
|
|
vl("New pin initialized: %s (%s) | %s | %s",pins[id].name,id,icon,text)
|
|
end
|
|
end
|
|
|
|
|
|
function register_script_zone(...)
|
|
local se_obj = alife_create("script_zone",...)
|
|
if not se_obj then return end
|
|
local id = se_obj.id
|
|
local now = time_global()
|
|
script_zones[id] = {
|
|
id = se_obj.id,
|
|
pos = se_obj.position,
|
|
created = now,
|
|
cleanup = now + ping_lifetime,
|
|
}
|
|
script_zone_changed = true
|
|
vl("Script zone %s spawned for mapspot",id)
|
|
return se_obj
|
|
end
|
|
|
|
|
|
function deregister_script_zone(id)
|
|
if not id then return end
|
|
local se_obj = alife_object(id)
|
|
if not se_obj then return end
|
|
alife_release(se_obj)
|
|
script_zones[id] = nil
|
|
script_zone_changed = true
|
|
vl("Script zone %s released",id)
|
|
end
|
|
|
|
|
|
function generate_scripted_mapspot_at(pos,lv,gv)
|
|
if not (pos and lv and gv) then return end
|
|
local sz = register_script_zone(pos,gv,lv)
|
|
if not sz then return end
|
|
return sz.id
|
|
end
|
|
|
|
|
|
function generate_scripted_mapspot_on(obj)
|
|
if not (obj and obj.id) then return end
|
|
local sz = register_script_zone(obj)
|
|
if not sz then return end
|
|
return sz.id
|
|
end
|
|
|
|
|
|
function spawn_pingspot(pid,pos,lv,gv)
|
|
if not (pid and pos and lv and gv) then return end
|
|
local sz = register_script_zone(pos,gv,lv)
|
|
if not sz then return end
|
|
|
|
local text = ts("st_paw_pingspot")
|
|
local id = sz.id
|
|
pings[id] = script_zones[id]
|
|
pings[id].pid = pid
|
|
add_mapspot(text,id,icon_pingspot)
|
|
-- vl("Spawned temporary pingspot at %s,%s with id %s",pos.x,pos.z,id)
|
|
return id
|
|
end
|
|
|
|
|
|
function despawn_pingspot(id)
|
|
-- vl("despawn_pingspot(%s): deregistering script zone and nulling ping record",id)
|
|
deregister_script_zone(id)
|
|
pings[id] = nil
|
|
end
|
|
|
|
|
|
function script_zone_cleanup()
|
|
local now = get_time_elapsed()
|
|
for k,v in pairs(script_zones) do
|
|
if v.cleanup and (v.cleanup < now) then
|
|
deregister_script_zone(k)
|
|
end
|
|
end
|
|
script_zone_changed = false
|
|
dl("script_zone_cleanup completed")
|
|
return true
|
|
end
|
|
|
|
function temp_pin_cleanup(wipe_all)
|
|
local now = get_time_elapsed()
|
|
for k,v in pairs(pins) do
|
|
if v.cleanup then
|
|
local expired = autotags_time_out and (v.cleanup < now)
|
|
if expired or wipe_all then
|
|
do_paw_action("pn_del",nil,nil,{syscall=true,id=k})
|
|
end
|
|
end
|
|
end
|
|
dl("temp_pin_cleanup completed")
|
|
return true
|
|
end
|
|
|
|
function set_pin_persistence(id,onoff,lifetime)
|
|
if not (id and (id > 0)) then return end
|
|
if not pins[id] then return end
|
|
if onoff or (onoff == nil) then
|
|
pins[id].cleanup = nil
|
|
dl("Pin %s given persistence, it will not be subject to cleanup",id)
|
|
else
|
|
local now = get_time_elapsed()
|
|
pins[id].cleanup = now + (lifetime or autotag_lifetime or 0)
|
|
dl("Pin %s flagged as temporary, it will be subject to cleanup at %s",id,pins[id].cleanup)
|
|
script_zone_changed = true
|
|
end
|
|
return true
|
|
end
|
|
|
|
function set_pingspot_persistence(id,onoff)
|
|
if not (id and script_zones[id]) then return end
|
|
if onoff or (onoff == nil) then
|
|
pings[id] = nil
|
|
script_zones[id].cleanup = nil
|
|
dl("Temporary pingspot %s given persistence, it will not be subject to cleanup",id)
|
|
else
|
|
script_zones[id].cleanup = get_time_elapsed()
|
|
dl("Persistent pingspot %s flagged as unused, it will be subject to cleanup",id)
|
|
script_zone_changed = true
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ping_area_around(obj)
|
|
if not obj then return end
|
|
local now = time_global()
|
|
local pid = tostring(now)
|
|
local span = ping_grid_radius or 10 -- radius of grid in squares
|
|
local grid = ping_grid_size or 10 -- dimension of grid squares in game units
|
|
local rad = span * grid -- actual ping radius in game units
|
|
local anch_id = obj.id
|
|
local anch_pos = obj.position
|
|
local ax = anch_pos.x
|
|
local ay = anch_pos.y
|
|
local az = anch_pos.z
|
|
local gv = obj.m_game_vertex_id
|
|
local lv = game_graph():vertex(gv):level_id()
|
|
|
|
for z = (az-(span*grid)),(az+(span*grid)),grid do
|
|
for x = (ax-(span*grid)),(ax+(span*grid)),grid do
|
|
local pos = vector():set(x,ay,z)
|
|
if distance_2d(pos,anch_pos) <= (rad + 1) then
|
|
spawn_pingspot(pid,pos,gv,lv)
|
|
end
|
|
end
|
|
end
|
|
|
|
if use_ping_snd and snd_ping then play_ui_sound(snd_ping) end
|
|
|
|
CreateTimeEvent("paw_ping_cleanup","ping_"..pid,11,tasks_placeable_waypoints.ping_cleanup,pid)
|
|
end
|
|
|
|
|
|
function init_mapspot_label_wnd(mapspot_text,id,icon,anchor)
|
|
vl("init_mapspot_label_wnd(%s,%s,%s)",mapspot_text,id,icon)
|
|
mapspot_text = mapspot_text or ""
|
|
local anchor = anchor or level.map_get_object_spot_static(id,icon)
|
|
local xml = CScriptXmlInit()
|
|
local xmlroot = "paw_ui_wnd_box"
|
|
local frm = xmlroot..":frm_"
|
|
xml:ParseFile("paw_ui_elements.xml")
|
|
|
|
local cap = {}
|
|
cap.id = id
|
|
cap.box = xml:InitStatic(xmlroot,anchor)
|
|
local tokens = 0
|
|
|
|
if string.find(mapspot_text,"$") then
|
|
local levelname = ts(level.name())
|
|
local se_obj = alife_object(id)
|
|
local pos = se_obj and se_obj.position
|
|
local coord_x,coord_y,coord_z,coords
|
|
if pos then
|
|
coord_x = string.format("%.2f",pos.x)
|
|
coord_y = string.format("%.2f",pos.y)
|
|
coord_z = string.format("%.2f",pos.z)
|
|
--coords = string.format("XYZ %s, %s, %s",coord_x,coord_y,coord_z)
|
|
end
|
|
local token_subs = {
|
|
["obj_id"] = id,
|
|
["name"] = safename(id),
|
|
--["level"] = levelname,-- currently wrong
|
|
--["coords"] = coords, -- XYZ coordinates formatted as above
|
|
["coord_x"] = coord_x, -- X coordinate to 2 decimal places
|
|
["coord_y"] = coord_y, -- Y coordinate to 2 decimal places
|
|
["coord_z"] = coord_z, -- Z coordinate to 2 decimal places
|
|
}
|
|
mapspot_text = psk(mapspot_text,token_subs)
|
|
_,tokens = mapspot_text:gsub("%$","%$")
|
|
plaintext = psk(mapspot_text,null_tokens)
|
|
mapspot_text = psk(mapspot_text,text_colors)
|
|
end
|
|
|
|
local token_adj = tokens * 17
|
|
_, nlcnt = mapspot_text:gsub("\\n", "\\n")
|
|
local w = clamp(#mapspot_text * 6,15,200)
|
|
local h = ((floor(clamp((#mapspot_text - token_adj) / 35,1,3)) + nlcnt) * 15) + 4
|
|
cap.box:SetWndPos(vector2():set(15,-h))
|
|
|
|
cap.drop = xml:InitStatic(xmlroot..":min_full",cap.box)
|
|
cap.drop:SetWndSize(vector2():set(w,h))
|
|
|
|
cap.text_sh = xml:InitStatic(xmlroot..":content:text_sh",cap.drop)
|
|
cap.text_sh:SetWndSize(vector2():set(w,h))
|
|
cap.text_sh:TextControl():SetText(plaintext)
|
|
cap.text_sh:TextControl():SetTextColor(GetARGB(220,0,0,0))
|
|
|
|
cap.text = xml:InitStatic(xmlroot..":content:text",cap.drop)
|
|
cap.text:SetWndSize(vector2():set(w,h))
|
|
cap.text:TextControl():SetText(mapspot_text)
|
|
cap.text:TextControl():SetTextColor(GetARGB(220,220,220,220))
|
|
|
|
cap.BL = xml:InitStatic(frm.."BL_extend",cap.drop)
|
|
cap.BP = xml:InitStatic(frm.."BP",cap.drop)
|
|
cap.BL:SetWndPos(vector2():set(0,h - 7))
|
|
cap.BP:SetWndPos(vector2():set(0,h - 7))
|
|
cap.BM = xml:InitStatic(frm.."BM_extend",cap.BP)
|
|
local bmh = cap.BM:GetHeight()
|
|
cap.BM:SetWndSize(vector2():set(w,bmh))
|
|
cap.Show = (
|
|
function(tf)
|
|
pins[cap.id].show_label = tf
|
|
cap.box:Show(tf)
|
|
end
|
|
)
|
|
return cap
|
|
end
|
|
|
|
|
|
function show_pin_label(id,onoff,destroy)
|
|
vl("show_pin_label(%s,%s,%s)",id,onoff,destroy)
|
|
if not (id and pins[id]) then return end
|
|
onoff = onoff and true or false
|
|
|
|
if not map_labels[id] then
|
|
--printf("pin label container doesn't exist yet")
|
|
local icon = pins[id].icon
|
|
local text = pins[id].text or pins[id].name
|
|
if not (icon and text) then return end
|
|
map_labels[id] = init_mapspot_label_wnd(text,id,icon)
|
|
end
|
|
map_labels[id].box:Show(onoff)
|
|
pins[id].show_label = onoff
|
|
if not destroy then return end
|
|
dl("Destroying map label for id %s",id)
|
|
map_labels[id] = nil
|
|
return onoff
|
|
end
|
|
|
|
|
|
function do_paw_action(act,se_obj,acode,args)
|
|
args = args or {}
|
|
local syscall = args.syscall and true or false
|
|
if (not syscall) and not (paw_enabled and act) then return end
|
|
acode = acode or act
|
|
local id,name
|
|
if se_obj then
|
|
id = se_obj.id
|
|
name = safename(id)
|
|
elseif args and args.id then
|
|
id = args.id
|
|
se_obj = alife_object(id) or se_obj
|
|
name = safename(id)
|
|
end
|
|
|
|
local ac = action_codes[acode]
|
|
|
|
dl("Received paw action call \"%s\" on target %s (id %s)",act,name,id)
|
|
|
|
if act == "wp_set" then
|
|
if not se_obj then
|
|
dl("do_paw_action called with action %s but no valid se_obj!",act)
|
|
return end
|
|
set_current_waypoint(se_obj)
|
|
tm:give_task("task_placeable_waypoint")
|
|
waypoint_active = true
|
|
elseif act == "wp_mov" then
|
|
if not se_obj then
|
|
dl("do_paw_action called with action %s but no valid se_obj!",act)
|
|
return end
|
|
if tm.task_info[task_id] then
|
|
local id = se_obj.id
|
|
local task = tm.task_info[task_id]
|
|
local atsk = db.actor:get_task(task_id, true)
|
|
task.target = id
|
|
task.current_target = id
|
|
atsk:change_map_location(task.spot, id)
|
|
level.map_add_object_spot(id, waypoint_mapspot, "")
|
|
set_current_waypoint(se_obj)
|
|
xr_sound.set_sound_play(AC_ID, "pda_tips")
|
|
else
|
|
dl("task_info[task_id] is nil!")
|
|
end
|
|
waypoint_active = true
|
|
elseif act == "wp_del" then
|
|
end_waypoint_task()
|
|
last_waypoint = nil
|
|
elseif act == "pn_add" then
|
|
dl("Received call to add new pin to map for %s (%s)",name,id)
|
|
local icon = icons[ac.icon] or map_pin_icon
|
|
local text = ts("st_paw_pin_default_name")
|
|
if not script_zones[id] then
|
|
text = name
|
|
end
|
|
init_new_pin(id,name,text,icon)
|
|
add_mapspot(text,id,icon)
|
|
open_pin_settings(id)
|
|
elseif act == "pn_settings" then
|
|
if not (id and pins[id]) then return end
|
|
dl("Received call to open settings for pin %s (%s)",name,id)
|
|
open_pin_settings(id)
|
|
elseif act == "wp_settings" then
|
|
dl("Received call to open waypoint settings")
|
|
open_waypoint_settings()
|
|
elseif act == "pn_del" then
|
|
if not (id and pins[id]) then return end
|
|
if syscall or not pins[id].locked then
|
|
local icon = pins[id] and pins[id].icon
|
|
show_pin_label(id,false,true)
|
|
if hud_pin_objs[id] then
|
|
vl("Removing pin %s from HUD",id)
|
|
get_hud():RemoveDialogToRender(hud_pin_objs[id])
|
|
hud_pin_objs[id] = nil
|
|
end
|
|
vl("Pin %s (%s) deleted",pins[id].name,id)
|
|
pins[id] = nil
|
|
if icon then remove_mapspot(id,icon) end
|
|
end
|
|
elseif act == "lock_pin" then
|
|
if not (id and pins[id]) then return end
|
|
pins[id].locked = true
|
|
elseif act == "unlock_pin" then
|
|
if not (id and pins[id]) then return end
|
|
pins[id].locked = false
|
|
elseif act == "convert_to_pin" then
|
|
local mapspot = get_mapspot(id)
|
|
if can_convert_to_pin(id) then
|
|
if not texture_data[mapspot] then
|
|
get_mapspot_data(mapspot)
|
|
end
|
|
remove_stash_mapspots(id)
|
|
local hint = safename(id)
|
|
init_new_pin(id,name,hint,mapspot)
|
|
add_mapspot(hint,id,mapspot)
|
|
open_pin_settings(id)
|
|
end
|
|
elseif act == "pn_clr" then
|
|
local wipe_all = args and args.wipe_all
|
|
if not is_empty(hud_pin_objs) then
|
|
for k,v in pairs(hud_pin_objs) do
|
|
if wipe_all or not (pins[k] and pins[k].locked) then
|
|
vl("Hiding HUD pin for %s",k)
|
|
get_hud():RemoveDialogToRender(hud_pin_objs[k])
|
|
hud_pin_objs[k] = nil
|
|
end
|
|
end
|
|
end
|
|
for k,v in pairs(pins) do
|
|
if wipe_all or not v.locked then
|
|
local icon = v.icon
|
|
remove_mapspot(k,icon)
|
|
pins[k] = nil
|
|
end
|
|
end
|
|
elseif act == "mping" then
|
|
ping_area_around(se_obj)
|
|
elseif act == "hud_vis_on" then
|
|
if not (id and pins[id]) then return end
|
|
if syscall or not pins[id].locked then
|
|
pins[id].hud = true
|
|
show_hud_pin(id)
|
|
end
|
|
elseif act == "hud_vis_off" then
|
|
if not (id and pins[id]) then return end
|
|
if syscall or not pins[id].locked then
|
|
pins[id].hud = false
|
|
hide_hud_pin(id)
|
|
end
|
|
elseif act == "show_pins" then
|
|
show_all_pins(true)
|
|
elseif act == "hide_pins" then
|
|
show_all_pins(false)
|
|
elseif act == "show_label" then
|
|
if not (id and pins[id]) then return end
|
|
show_pin_label(id,true)
|
|
elseif act == "hide_label" then
|
|
if not (id and pins[id]) then return end
|
|
show_pin_label(id,false)
|
|
elseif act == "cm_dbg" then
|
|
local cls = se_obj and se_obj:clsid() or "empty"
|
|
property_ui:AddItem("[PAW Debug] Mapspot for %s (id %s) has clsid %s)",name,id,cls)
|
|
else
|
|
dl("invalid action %s passed to do_paw_action",act)
|
|
end
|
|
return true
|
|
end
|
|
|
|
|
|
function add_context_option(property_ui,act,maptbl)
|
|
local ac = action_codes[act]
|
|
vl("add_context_option \"%s\" | cart_mode is %s",act,cart_mode)
|
|
if ac and ac.enable then
|
|
--printf("action %s is enabled",act)
|
|
if type(ac.mode) ~= "number" then
|
|
dl("WARNING: mode (%s) for action %s was not a number, resetting to 0",ac.mode,act)
|
|
ac.mode = 0
|
|
end
|
|
-- -1: debug mode only
|
|
-- 0: disabled
|
|
-- 1: enabled in normal view only
|
|
-- 2: enabled in cartography mode only
|
|
-- 4: enabled in both
|
|
--[[
|
|
if ((ac.mode < 0) and debuglogs) or
|
|
(ac.mode == 1 and not cart_mode) or
|
|
((ac.mode >= 2) and cart_mode) or
|
|
(ac.mode >= 4) then
|
|
-]]
|
|
if feature_valid_in_mode(ac.mode) then
|
|
local text = ts(ac.text)
|
|
vl("add_context_option(%s): Adding context option %s",act,text)
|
|
property_ui:AddItem(text)
|
|
curr_menu_options[text] = maptbl
|
|
end
|
|
else
|
|
vl("Action %s is missing or not enabled, ignoring",act)
|
|
end
|
|
end
|
|
|
|
function nearest_smart_to_actor()
|
|
vl("nearest_smart_to_actor")
|
|
|
|
local levelid = alife():level_id()
|
|
local smart_nearest,dist_nearest,name_nearest,result
|
|
for name,smart in pairs(SIMBOARD.smarts_by_names) do
|
|
if levelid == game_graph():vertex(smart.m_game_vertex_id):level_id() then
|
|
-- vl("%s is same map as actor",name)
|
|
local dist = smart.position:distance_to(db.actor:position())
|
|
if (SIMBOARD.smarts[smart.id]) and (not smart_nearest or (dist < dist_nearest)) then
|
|
vl("%s (%s) is nearest so far at %s",name,smart.id,dist)
|
|
smart_nearest = smart
|
|
dist_nearest = dist
|
|
name_nearest = name
|
|
end
|
|
end
|
|
end
|
|
|
|
if not smart_nearest then
|
|
dl("!ERROR! No nearby smarts found to actor, this shouldn't be possible")
|
|
return {id=0,name="oops"} end
|
|
|
|
result = {
|
|
smart = smart_nearest,
|
|
id = smart_nearest.id or 0,
|
|
dist = dist_nearest or 0,
|
|
name = name_nearest or "oops",
|
|
pos = smart_nearest.position, -- not used yet
|
|
}
|
|
vl("nearest_smart: %s at %s",name_nearest,dist_nearest)
|
|
return result
|
|
end
|
|
|
|
|
|
function show_smarts(onoff)
|
|
vl("show_smarts: %s",onoff)
|
|
local toggle = onoff or false
|
|
local levelid = alife():level_id()
|
|
local smart_nearest,dist_nearest,name_nearest,result
|
|
for name,smart in pairs(SIMBOARD.smarts_by_names) do
|
|
if (SIMBOARD.smarts[smart.id]) then
|
|
local text = name
|
|
local id = smart.id
|
|
local icon = smart_terrain_icon
|
|
if toggle then
|
|
-- vl("Adding temporary smart %s (%s) with icon %s",text,id,icon)
|
|
level.map_add_object_spot(id,icon,text)
|
|
else
|
|
-- vl("Removing temporary smart %s (%s)",text,id)
|
|
level.map_remove_object_spot(id,icon)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function wp_target_obj()
|
|
dl("wp_target_obj called")
|
|
local obj = level.get_target_obj()
|
|
local id = obj and obj:id()
|
|
vl("ID returned by level.get_target_obj is %s | obj exists: %s",id,obj ~= nil)
|
|
if id and (id > 0) then
|
|
local se_obj = alife_object(id)
|
|
if not (se_obj and (allow_non_wp_targets or valid_waypoint_target(se_obj))) then return end
|
|
|
|
if placed_waypoint then
|
|
if id == placed_waypoint.id then
|
|
vl("Waypoint is currently active on %s (%s), disabling",se_obj:name(),id)
|
|
--do_paw_action("wp_del",se_obj)
|
|
toggle_waypoint()
|
|
else
|
|
vl("Waypoint is currently active, moving to %s (%s)",se_obj:name(),id)
|
|
do_paw_action("wp_mov",se_obj)
|
|
end
|
|
else
|
|
vl("No current waypoint, setting to target object %s (%s)",se_obj:name(),id)
|
|
do_paw_action("wp_set",se_obj)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function get_smart_target_type(obj)
|
|
--printf("get_smart_target_type(%s)",obj and obj:name())
|
|
local target_type
|
|
|
|
if obj then
|
|
if IsStalker(obj) then
|
|
local acomm = get_actor_true_community()
|
|
local comm = obj:character_community() or "stalker"
|
|
local is_enemy = game_relations.is_factions_enemies(acomm,comm)
|
|
--printf("Targeted object %s (%s) is stalker | actor comm %s | target comm %s | is_enemy %s",obj:character_name(),obj:id(),acomm,comm,is_enemy)
|
|
if comm == acomm then
|
|
target_type = "human_f"
|
|
elseif is_enemy then
|
|
target_type = "human_e"
|
|
else
|
|
target_type = "human_n"
|
|
end
|
|
elseif IsMonster(obj) then
|
|
target_type = "monster"
|
|
elseif IsInvbox(obj) then
|
|
target_type = "stash"
|
|
end
|
|
end
|
|
|
|
return target_type
|
|
end
|
|
|
|
function get_smart_icon_for_obj(obj,mapspot)
|
|
local mapspot = mapspot or map_pin_icon
|
|
local target_type = get_smart_target_type(obj)
|
|
local target = target_type and smart_pins[target_type]
|
|
mapspot = (target and icons[target.pin]) or mapspot
|
|
|
|
vl("get_smart_icon_for_obj %s: best icon for %s was %s",obj and obj:character_name(),target_type,mapspot)
|
|
return mapspot
|
|
end
|
|
|
|
|
|
function pin_target_obj(mapspot,notip,silent,smart)
|
|
vl("pin_target_obj: mapspot %s | notip %s | silent %s | smart %s",mapspot,notip,silent,smart)
|
|
local obj = level.get_target_obj()
|
|
local id = obj and obj:id()
|
|
if id and (id > 0) then
|
|
if blacklisted_object(id) then return end
|
|
if smart then
|
|
mapspot = get_smart_icon_for_obj(obj)
|
|
vl("pin_target_obj: pin %s is smart, assigned mapspot %s",id,mapspot)
|
|
end
|
|
local se_obj = alife_object(id)
|
|
if not (se_obj and (allow_non_wp_targets or valid_waypoint_target(se_obj))) then return end
|
|
local name = safename(id)
|
|
if pins[id] then
|
|
if not pins[id].locked then
|
|
local hint = pins[id].text or pins[id].name or ts("st_paw_pin_default_name")
|
|
local text = string.format(ts("st_paw_pin_removed_from_target"),name,hint)
|
|
text = psk(text,text_colors)
|
|
|
|
do_paw_action("pn_del",se_obj)
|
|
dotip(text,5,nil,false)
|
|
end
|
|
else
|
|
local hint = name or ts("st_paw_pin_default_name")
|
|
drop_quick_pin(id,hint,mapspot,true,true)
|
|
if pin_hud_icon_default and pins[id] then
|
|
pins[id].hud = true
|
|
show_hud_pin(id)
|
|
end
|
|
if not silent then
|
|
play_ui_sound(snd_tag_target)
|
|
end
|
|
if not notip then
|
|
local icon = ts("ui_mcm_lst_"..(mapspot or pawdata.curr_ico_name))
|
|
local nxtb = keybinds["ico_next"].text
|
|
local prvb = keybinds["ico_prev"].text
|
|
local text = string.format(ts("st_paw_pin_added_to_target"),name,icon,nxtb,prvb)
|
|
text = psk(text,text_colors)
|
|
dotip(text,5,nil,false)
|
|
end
|
|
end
|
|
end
|
|
return id
|
|
end
|
|
|
|
|
|
function create_smart_pin(notip,silent)
|
|
--local mapspot = get_smart_icon_for_obj(obj)
|
|
return pin_target_obj(nil,notip,silent,true)
|
|
end
|
|
|
|
function autotag_target(notip,silent)
|
|
--if not valid_pda("autotag") then return end
|
|
|
|
local id = create_smart_pin(true)
|
|
set_pingspot_persistence(id,autotag_persistence)
|
|
set_pin_persistence(id,autotag_persistence)
|
|
return id
|
|
end
|
|
|
|
function drop_quick_pin(id,force_text,force_pin,no_tip,no_fast_travel)
|
|
if not paw_enabled_check() then return end
|
|
if next_pin > time_global() then return end
|
|
next_pin = time_global() + pin_delay
|
|
|
|
if not id then
|
|
id = generate_scripted_mapspot_on(db.actor)
|
|
end
|
|
|
|
local se_obj = alife_object(id)
|
|
if not se_obj then return end
|
|
|
|
local name = se_obj:name() or "none"
|
|
local icon = force_pin or map_pin_icon
|
|
local mapspot_text = force_text or ts("st_paw_pin_quick_name")
|
|
local tip_text = ts("st_paw_pin_dropped")
|
|
init_new_pin(id,name,mapspot_text,icon)
|
|
pins[id].quick = not no_fast_travel
|
|
dl("calling add_mapspot with %s | %s | %s",mapspot_text,id,icon)
|
|
play_ui_sound(snd_place_pin)
|
|
add_mapspot(mapspot_text,id,icon)
|
|
if not no_tip then dotip(tip_text,10000) end
|
|
end
|
|
|
|
|
|
function toggle_waypoint(force)
|
|
dl("toggle_waypoint action called")
|
|
if (force ~= nil) then
|
|
waypoint_active = not force
|
|
end
|
|
if not waypoint_active then
|
|
if last_waypoint then
|
|
placed_waypoint = last_waypoint
|
|
local se_obj = alife_object(placed_waypoint.id)
|
|
if not se_obj then return end
|
|
do_paw_action("wp_set",se_obj)
|
|
else
|
|
dotip("st_paw_no_last_wp")
|
|
end
|
|
else
|
|
last_waypoint = placed_waypoint
|
|
end_waypoint_task()
|
|
end
|
|
end
|
|
|
|
|
|
function cartography_mode(onoff)
|
|
if (onoff == nil) then
|
|
cart_mode = not cart_mode
|
|
else
|
|
cart_mode = onoff or false
|
|
end
|
|
vl ("Setting cart_mode to %s and calling show_smarts to toggle",cart_mode)
|
|
show_smarts(cart_shows_smarts and cart_mode)
|
|
end
|
|
|
|
|
|
function get_context_menu_options(property_ui,id,maptbl)
|
|
empty_table(curr_menu_options)
|
|
maptbl = maptbl or {}
|
|
if not id then
|
|
id = maptbl.object_id
|
|
end
|
|
if not paw_enabled then return end
|
|
local se_obj = id and (id > 0) and alife_object(id)
|
|
if not se_obj then return end
|
|
|
|
local name = se_obj:name() or "undefined"
|
|
local clsid = se_obj:clsid() or "unknown"
|
|
local id = se_obj.id
|
|
local pin = id and pins[id]
|
|
local pinset = false
|
|
vl("get_context_menu_options: %s (%s) | cls %s",name,id,clsid)
|
|
|
|
add_context_option(property_ui,"mping",maptbl)
|
|
if id and valid_waypoint_target(se_obj) then
|
|
if pins[id] then
|
|
vl("Pin exists")
|
|
|
|
add_context_option(property_ui,"pn_settings",maptbl)
|
|
pinset = true
|
|
if pin.locked then
|
|
add_context_option(property_ui,"unlock_pin",maptbl)
|
|
else
|
|
add_context_option(property_ui,"pn_del",maptbl)
|
|
if pins[id].hud then
|
|
add_context_option(property_ui,"hud_vis_off",maptbl)
|
|
else
|
|
add_context_option(property_ui,"hud_vis_on",maptbl)
|
|
end
|
|
if pins[id].show_label then
|
|
add_context_option(property_ui,"hide_label",maptbl)
|
|
else
|
|
add_context_option(property_ui,"show_label",maptbl)
|
|
end
|
|
add_context_option(property_ui,"lock_pin",maptbl)
|
|
end
|
|
else
|
|
vl("No pin")
|
|
if can_convert_to_pin(id) then
|
|
add_context_option(property_ui,"convert_to_pin",maptbl)
|
|
else
|
|
add_context_option(property_ui,"pn_add",maptbl)
|
|
end
|
|
end
|
|
|
|
local name = se_obj:name()
|
|
if placed_waypoint == nil then
|
|
vl("No waypoint")
|
|
add_context_option(property_ui,"wp_set",maptbl)
|
|
else
|
|
local wid = placed_waypoint.id or 0
|
|
local sid = se_obj.id or 0
|
|
|
|
if not pinset then
|
|
-- If already showing the pin settings option, don't also clutter the menu with waypoint settings
|
|
add_context_option(property_ui,"wp_settings",maptbl)
|
|
end
|
|
if wid ~= sid then
|
|
vl("Waypoint exists elsewhere")
|
|
add_context_option(property_ui,"wp_mov",maptbl)
|
|
else
|
|
vl("Waypoint exists here")
|
|
end
|
|
add_context_option(property_ui,"wp_del",maptbl)
|
|
end
|
|
end
|
|
|
|
if pins_exist() then
|
|
if show_pins then
|
|
add_context_option(property_ui,"hide_all_pins",maptbl)
|
|
else
|
|
add_context_option(property_ui,"show_all_pins",maptbl)
|
|
end
|
|
end
|
|
|
|
if not (pin and pin.locked) then
|
|
add_context_option(property_ui,"pn_clr",maptbl)
|
|
for k,v in pairs(action_codes) do
|
|
local can_add = true
|
|
if v.act == "pn_add" then
|
|
can_add = (pins[id] == nil)
|
|
end
|
|
local mode = tonumber(v.mode) or 0
|
|
if can_add and v.enable and (mode > 0) and not managed_options[k] then
|
|
add_context_option(property_ui,k,id,maptbl)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function execute_context_menu_option(property_ui,id,level_name,prop)
|
|
vl("passed id : %s",id)
|
|
id = last_clicked_id
|
|
last_clicked_id = nil
|
|
vl("execute_context_menu_option called for id %s\n| prop: %s\n| action %s",id,prop,action[prop])
|
|
if not (paw_enabled and id and valid_pda("show_w")) then return end
|
|
if not (id and (id > 0)) then return end
|
|
local se_obj = alife_object(id)
|
|
if not se_obj then return end
|
|
local ac = action[prop]
|
|
if ac then
|
|
local act = action_codes[ac].act
|
|
do_paw_action(act,se_obj,ac)
|
|
end
|
|
end
|
|
|
|
|
|
function faction_body_icon(comm)
|
|
vl("faction_body_icon(%s) called",comm)
|
|
local icon = nil
|
|
if comm and managed_factions[comm] then
|
|
local bi = body_icon_mode or "badge"
|
|
icon = "paw_"..patch_res..sep..comm
|
|
vl("faction_body_icon generated from quality %s for faction %s: %s",patch_res,comm,icon)
|
|
else
|
|
vl("not a valid human faction, returning %s from bodies set",current_body_icon)
|
|
end
|
|
return icon or current_body_icon
|
|
end
|
|
|
|
function local_set_name(setname)
|
|
return ts(setname or icon_sets[pawdata.curr_set_name].name)
|
|
end
|
|
|
|
function local_icon_name(iconame)
|
|
return ts(iconame or "ui_mcm_lst_"..pawdata.curr_ico_name)
|
|
end
|
|
|
|
function icon_for_pin(pin_name)
|
|
if icons and pin_name then return icons[pin_name] end
|
|
end
|
|
|
|
|
|
function pin_for_icon(icon)
|
|
if icon and texture_data and texture_data[icon] then return texture_data[icon].id end
|
|
end
|
|
|
|
|
|
function texture_for_icon(icon)
|
|
--printf("texture_for_icon(%s) called",icon)
|
|
local tex = texture_data and texture_data[icon] and texture_data[icon].t
|
|
--vl("texture_for_icon(%s) returned %s",icon,tex)
|
|
return tex
|
|
end
|
|
|
|
function texture_for_set(setname)
|
|
if not setname then return end
|
|
local setdata = icon_sets[setname]
|
|
if not (setdata and setdata.active_icon) then
|
|
dl("WARNING: No active icon found for %s",setname)
|
|
return end
|
|
--vl("active_icon for %s: %s",setname,setdata.active_icon)
|
|
local td = texture_data[setdata.active_icon]
|
|
--vl("texture exists for %s: %s",setdata.active_icon,td ~= nil)
|
|
local tex = td.t
|
|
vl("texture_for_set(%s) returned %s",setname,tex)
|
|
return tex
|
|
end
|
|
|
|
function get_current_texture(set_changed)
|
|
return set_changed and texture_for_set(pawdata.curr_set_name) or texture_for_icon(pawdata.curr_ico_name)
|
|
end
|
|
|
|
function get_mapspot_data(spot)
|
|
local attr_tex = "texture"
|
|
local attr_minimap = "mini_map"
|
|
local attr_levelmap = "level_map"
|
|
|
|
xml:ParseFile("map_spots.xml")
|
|
xml:NavigateToRoot()
|
|
th = xml:ReadAttribute(spot,0,"height")
|
|
tw = xml:ReadAttribute(spot,0,"width")
|
|
xml:NavigateToNode(spot,0)
|
|
vl("trying to find texture data for %s",spot)
|
|
if xml:NodeExist(attr_tex,0) then
|
|
tex = xml:ReadValue(attr_tex,0)
|
|
vl("texture node found with value %s",tex)
|
|
else
|
|
local spotnode = ""
|
|
local typ = ""
|
|
if xml:NodeExist(attr_minimap) then
|
|
spotnode = xml:ReadAttribute(attr_minimap,0,"spot")
|
|
typ = attr_minimap
|
|
end
|
|
if xml:NodeExist(attr_levelmap) then
|
|
spotnode = xml:ReadAttribute(attr_levelmap,0,"spot")
|
|
typ = attr_levelmap
|
|
end
|
|
if spotnode ~= "" then
|
|
xml:NavigateToRoot()
|
|
th = xml:ReadAttribute(spotnode,0,"height")
|
|
tw = xml:ReadAttribute(spotnode,0,"width")
|
|
vl("ReadAttribute for %s: h %s w %s",spot,th,tw)
|
|
xml:NavigateToNode(spotnode,0)
|
|
tex = xml:ReadValue(attr_tex,0)
|
|
vl("%s node found: %s",typ,spotnode)
|
|
end
|
|
end
|
|
texture_data[spot] = {
|
|
id = k,
|
|
t = tex,
|
|
h = th,
|
|
w = tw,
|
|
}
|
|
local ind = #icon_index + 1
|
|
icon_index[ind] = {
|
|
id = k,
|
|
icon = spot,
|
|
data = texture_data[spot],
|
|
}
|
|
vl("Texture for %s: %s (%sx%s)",spot,tex,tw,th)
|
|
return texture_data[spot],ind
|
|
end
|
|
|
|
function set_or_icon(str)
|
|
return str and ((str ~= "set") and (str ~= "icon"))
|
|
end
|
|
|
|
function set_icon_index(set)
|
|
vl("set_icon_index called for set %s",set)
|
|
local ii = set_index[set].ii
|
|
return ii
|
|
end
|
|
|
|
function set_icon_index_rev(set)
|
|
vl("set_icon_index_rev called for set %s",set)
|
|
local ri = set_index[set].ri
|
|
return ri
|
|
end
|
|
|
|
function set2ind(skey)
|
|
local ind = nil
|
|
vl("set2ind called for set %s, %s sets listed",skey,#set_index)
|
|
for i=1,#set_index,1 do
|
|
local k = set_index[i].id
|
|
if k == skey then
|
|
ind = i
|
|
end
|
|
end
|
|
vl("set2ind(%s) returned %s",skey,ind)
|
|
return ind
|
|
end
|
|
|
|
|
|
function curr_set_i()
|
|
return pawdata.curr_set_ind
|
|
end
|
|
|
|
function next_set_i()
|
|
return roll(curr_set_i() + 1, 1, #set_index)
|
|
end
|
|
|
|
function prev_set_i()
|
|
return roll(curr_set_i() - 1, 1, #set_index)
|
|
end
|
|
|
|
|
|
function curr_ico_i()
|
|
--printf("curr_ico_i returns %s",pawdata.curr_ico_ind)
|
|
return pawdata.curr_ico_ind
|
|
end
|
|
|
|
function next_ico_i()
|
|
local c_ind = curr_ico_i()
|
|
local setdata = icon_sets[pawdata.curr_set_name]
|
|
return roll(c_ind + 1, 1, #setdata.ii)
|
|
end
|
|
|
|
function prev_ico_i()
|
|
local c_ind = curr_ico_i()
|
|
local setdata = icon_sets[pawdata.curr_set_name]
|
|
return roll(c_ind - 1, 1, #setdata.ii)
|
|
end
|
|
|
|
function root_patch_name(patch)
|
|
--printf("root_patch_name called with mapspot %s",patch)
|
|
local name = patch
|
|
local pos_paw = string.find(name,"paw_badge_")
|
|
local pos_qlt = string.find(name,"hr_")
|
|
if pos_paw and pos_qlt then
|
|
name = "paw_badge_"..string.sub(patch,pos_qlt+3)
|
|
vl("root_patch_name strips quality string from %s to get %s",patch,name)
|
|
else
|
|
vl("root_patch_name returning %s as-is",patch)
|
|
end
|
|
return name
|
|
end
|
|
|
|
function active_set(newset)
|
|
vl("active_set(%s) called",newset)
|
|
if newset and type(newset) == "number" then
|
|
pawdata.curr_set_ind = clamp(newset,1,#set_index)
|
|
pawdata.curr_set_name = set_index[pawdata.curr_set_ind].id
|
|
pawdata.curr_set_data = icon_sets[pawdata.curr_set_name]
|
|
current_active_set = pawdata.curr_set_name
|
|
local setdata = pawdata.curr_set_data
|
|
pawdata.curr_ico_name = setdata.active_icon
|
|
pawdata.curr_ico_ind = setdata.ri[root_patch_name(pawdata.curr_ico_name)]
|
|
map_pin_icon = pawdata.curr_ico_name
|
|
vl("active set is now %s (%s), current icon %s (%s)",pawdata.curr_set_name,pawdata.curr_set_ind,pawdata.curr_ico_name,pawdata.curr_ico_ind)
|
|
end
|
|
return pawdata.curr_set_name
|
|
end
|
|
|
|
function get_next_icon()
|
|
local setdata = pawdata.curr_set_data
|
|
return setdata.ii[next_ico_i()]
|
|
end
|
|
|
|
function get_prev_icon()
|
|
local setdata = pawdata.curr_set_data
|
|
return setdata.ii[prev_ico_i()]
|
|
end
|
|
|
|
function get_active_icon(newico)
|
|
if newico and type(newico) == "number" then
|
|
vl("Setting new icon to index %s",newico)
|
|
local setdata = pawdata.curr_set_data
|
|
pawdata.curr_ico_ind = clamp(newico,1,setdata.inum)
|
|
pawdata.curr_ico_name = setdata.ii[pawdata.curr_ico_ind]
|
|
setdata.active_icon = pawdata.curr_ico_name
|
|
map_pin_icon = pawdata.curr_ico_name
|
|
end
|
|
return pawdata.curr_ico_name
|
|
end
|
|
|
|
function notify_icon_change(newset)
|
|
local setdata = pawdata.curr_set_data
|
|
local icon = setdata.active_icon
|
|
local td = texture_data[icon]
|
|
local tex = td.t
|
|
local tiptext = ts("st_paw_change_icon").." "..ts("ui_mcm_lst_"..icon)
|
|
|
|
if newset then
|
|
local name = ts(setdata.name)
|
|
local settext = string.format(ts("st_paw_change_set"),name)
|
|
tiptext = settext .. tiptext
|
|
end
|
|
dotip(tiptext,2,nil,false,tex)
|
|
end
|
|
|
|
|
|
|
|
function cycle_icons(cycle_dir,dotip)
|
|
--printf("cycle_icons: curr_set: %s (%s)",pawdata.curr_set_name,pawdata.curr_set_ind)
|
|
if cycle_dir and type(cycle_dir) ~= "number" then return end
|
|
local setdata = pawdata.curr_set_data
|
|
local next_ind = roll(pawdata.curr_ico_ind + cycle_dir,1,setdata.inum)
|
|
get_active_icon(next_ind)
|
|
play_ui_sound(snd_cycle_blip)
|
|
if dotip then notify_icon_change() end
|
|
end
|
|
|
|
function cycle_sets(cycle_dir,dotip)
|
|
if cycle_dir and type(cycle_dir) ~= "number" then return end
|
|
local next_ind = roll(pawdata.curr_set_ind + cycle_dir,1,#set_index)
|
|
active_set(next_ind)
|
|
play_ui_sound(snd_cycle_blip)
|
|
if dotip then notify_icon_change(true) end
|
|
end
|
|
|
|
function icon_cycle(change,val)
|
|
if not mwheel_enabled then return end
|
|
if change then
|
|
icon_cycle_active = val
|
|
if not mwheel_notify then return icon_cycle_active end
|
|
if icon_cycle_active then
|
|
dotip(ts("st_paw_cycling_icons"))
|
|
else
|
|
dotip(ts("st_paw_mwheel_normal"))
|
|
end
|
|
end
|
|
return icon_cycle_active
|
|
end
|
|
|
|
function set_cycle(change,val)
|
|
if not mwheel_enabled then return end
|
|
if change then
|
|
set_cycle_active = val
|
|
if not mwheel_notify then return icon_cycle_active end
|
|
if set_cycle_active then
|
|
dotip(ts("st_paw_cycling_sets"))
|
|
else
|
|
dotip(ts("st_paw_mwheel_normal"))
|
|
end
|
|
end
|
|
return set_cycle_active
|
|
end
|
|
|
|
function cycle_items(cycle_dir,item_type,dotip)
|
|
if (item_type == nil) then
|
|
if icon_cycle() then
|
|
item_type = "icon"
|
|
elseif set_cycle() then
|
|
item_type = "set"
|
|
end
|
|
end
|
|
if not icoset_changed then icoset_changed = {} end
|
|
if item_type == "icon" then
|
|
icoset_changed.i = true
|
|
vl("cycling icons: %s",cycle_dir)
|
|
cycle_icons(cycle_dir,dotip)
|
|
elseif item_type == "set" then
|
|
icoset_changed.s = true
|
|
vl("cycling sets: %s",cycle_dir)
|
|
cycle_sets(cycle_dir,dotip)
|
|
end
|
|
end
|
|
|
|
|
|
function show_all_pins(onoff)
|
|
show_pins = onoff
|
|
if onoff then
|
|
vl("Showing all recorded pins")
|
|
for id,pin in pairs(pins) do
|
|
local icon = pin.icon
|
|
local mapspot_text = get_tooltip_for_pin(id)
|
|
vl("calling add_mapspot with %s | %s | %s",mapspot_text,id,icon)
|
|
add_mapspot(mapspot_text,id,icon)
|
|
|
|
end
|
|
else
|
|
vl("Hiding stored pins from map")
|
|
for id,pin in pairs(pins) do
|
|
remove_mapspot(id,pin.icon)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function load_mcm(pawpath,default)
|
|
local val = ui_mcm and ui_mcm.get("pawsys/"..pawpath)
|
|
if val ~= nil then
|
|
return val
|
|
else
|
|
return default
|
|
end
|
|
end
|
|
|
|
function marker_hint_shown(wpin)
|
|
local mode = show_marker_hint and tonumber(show_marker_hint[wpin])
|
|
local shown = feature_valid_in_mode(mode)
|
|
return shown
|
|
end
|
|
|
|
|
|
function marker_dist_shown(wpin)
|
|
local mode = show_marker_dist and tonumber(show_marker_dist[wpin])
|
|
local shown = feature_valid_in_mode(mode)
|
|
return shown
|
|
end
|
|
|
|
|
|
function mcm_reload_general_settings()
|
|
if not ui_mcm then return end
|
|
local old_paw_en = paw_enabled
|
|
paw_enabled = load_mcm("pawgen/enabled",paw_enabled)
|
|
|
|
if paw_enabled and not old_paw_en then
|
|
on_game_start()
|
|
dl("PAW was disabled and now is not, re-registering actor_on_update")
|
|
elseif not paw_enabled then
|
|
if old_paw_en then
|
|
unregister_all_callbacks()
|
|
end
|
|
printf(logprefix.."Personal Adjustable Waypoint has been disabled, aborting all further action!")
|
|
return false end
|
|
|
|
disable_load_warning = load_mcm("pawgen/disable_load_warning",disable_load_warning)
|
|
wp_hud_icon_enabled = load_mcm("pawgen/wp_hud_icon_enabled",wp_hud_icon_enabled)
|
|
if wp_hud_icon_enabled then
|
|
show_marker_dist["wp"] = tonumber(load_mcm("pawgen/show_dist_wp",show_marker_dist["wp"]))
|
|
show_hud_waypoint()
|
|
else
|
|
hide_hud_waypoint()
|
|
end
|
|
show_marker_dist["pins"] = tonumber(load_mcm("pawgen/show_dist_pins",show_marker_dist["pins"]))
|
|
show_marker_hint["pins"] = tonumber(load_mcm("pawgen/show_hint_pins",show_marker_hint["pins"]))
|
|
pin_near_fade_dist = tonumber(load_mcm("pawgen/pin_near_fade_dist",pin_near_fade_dist))
|
|
pin_far_fade_dist = tonumber(load_mcm("pawgen/pin_far_fade_dist",pin_far_fade_dist))
|
|
pin_far_hide_dist = tonumber(load_mcm("pawgen/pin_far_hide_dist",pin_far_hide_dist))
|
|
wp_near_fade_dist = tonumber(load_mcm("pawgen/wp_near_fade_dist",wp_near_fade_dist))
|
|
wp_far_fade_dist = tonumber(load_mcm("pawgen/wp_far_fade_dist",wp_far_fade_dist))
|
|
wp_far_hide_dist = tonumber(load_mcm("pawgen/wp_far_hide_dist",wp_far_hide_dist))
|
|
wp_clear_dist = tonumber(load_mcm("pawgen/wp_clear_dist",wp_clear_dist))
|
|
tip_on_icoset_change = load_mcm("pawgen/tip_on_icoset_change",tip_on_icoset_change)
|
|
welcome_msg_shown = load_mcm("pawgen/welcome_msg_shown",welcome_msg_shown)
|
|
enable_wp_proxcheck = wp_clear_dist and wp_clear_dist > 0
|
|
mcm_update_throttle = load_mcm("pawgen/mcm_update_throttle",mcm_update_throttle)
|
|
mwheel_poll_interval = load_mcm("pawgen/mwheel_poll_interval",mwheel_poll_interval)
|
|
-- These last two options are not in the MCM menu, but can be manually set as overrides
|
|
return true
|
|
end
|
|
|
|
function mcm_reload_keybind_table()
|
|
if not ui_mcm then return end
|
|
for k,v in pairs(keybinds) do
|
|
local kb = load_mcm("pawbinds/bind_"..k)
|
|
local km = load_mcm("pawbinds/modk_"..k)
|
|
local vbkb = valid_bind(kb)
|
|
local vbkm = valid_bind(km)
|
|
if vbkb then
|
|
keybinds[k].bind = kb
|
|
end
|
|
if vbkm then
|
|
keybinds[k].mod = km
|
|
end
|
|
keybinds[k].text = bindtext(kb,km)
|
|
end
|
|
end
|
|
|
|
function mcm_reload_keybind_settings()
|
|
cartography_must_hold = not load_mcm("pawbinds/cartmode_toggle",cartography_must_hold)
|
|
keybinds[cartmode].hold = cartography_must_hold
|
|
cart_shows_smarts = load_mcm("pawbinds/cart_shows_smarts",cart_shows_smarts)
|
|
mwheel_notify = load_mcm("pawbinds/mwheel_notify")
|
|
cartmode_unfade = load_mcm("pawbinds/cartmode_unfade",cartmode_unfade)
|
|
local tmp
|
|
|
|
tmp = ui_mcm.get("pawsys/pawbinds/mwheel_override")
|
|
if tmp ~= nil then
|
|
dl("MCM override found for mwheel_avail (old = %s | new = %s)",mwheel_avail,tmp)
|
|
mwheel_override = tmp
|
|
if mwheel_override then
|
|
mwheel_avail = true
|
|
end
|
|
end
|
|
|
|
tmp = ui_mcm.get("pawsys/pawbinds/mwheel_enabled")
|
|
if tmp and type(tmp) == "number" then
|
|
tmp = (tmp ~= 0)
|
|
end
|
|
mwheel_enabled = tmp and mwheel_avail
|
|
|
|
tmp = ui_mcm.get("pawsys/pawbinds/right_click_override")
|
|
-- if set to true, will force on_map_right_click support on
|
|
if tmp ~= nil then
|
|
dl("MCM override found for right_click_avail (old = %s | new = %s)",right_click_avail,tmp)
|
|
right_click_override = tmp
|
|
if right_click_override then
|
|
right_click_avail = true
|
|
RegisterScriptCallback("on_map_right_click",on_map_right_click)
|
|
end
|
|
end
|
|
|
|
tmp = ui_mcm.get("pawsys/pawgen/disable_mcmups")
|
|
if tmp ~= nil then
|
|
dl("MCM override found for disable_mcm_updates (old = %s | new = %s)",disable_mcm_updates,tmp)
|
|
disable_mcm_updates = tmp
|
|
end
|
|
|
|
tmp = load_mcm("pawgen/pingsound")
|
|
if tmp ~= nil then
|
|
use_ping_snd = tmp
|
|
end
|
|
end
|
|
|
|
function mcm_reload_pin_settings()
|
|
patch_res = ui_mcm.get("pawsys/pawpins/patch_res") or "badge"
|
|
local bi = ui_mcm.get("pawsys/pawpins/milpda_body_icon")
|
|
local pig = ui_mcm.get("pawsys/pawpins/pin_icon_group")
|
|
--local mp = ui_mcm.get("pawsys/pawpins/poi_icon_"..(pig or ""))
|
|
local cbi = ui_mcm.get("pawsys/pawpins/poi_icon_bodies")
|
|
|
|
for k,v in pairs(icons) do
|
|
if managed_factions[k] then
|
|
local newbadge = "paw_"..patch_res..sep..k
|
|
vl("MCM: icon for %s was %s, is now %s",k,v,newbadge)
|
|
icons[k] = newbadge
|
|
end
|
|
end
|
|
|
|
load_active_icoset_data()
|
|
local icon = pig and icon_sets[pig] and icon_sets[pig].active_icon or default_mapspot
|
|
icon_sets["bodies"].active_icon = icons[cbi]
|
|
dl("MCM: body icon mode %s | paw icon %s",bi,cbi)
|
|
map_pin_icon = icon
|
|
current_active_set = pig
|
|
|
|
dl("MCM: icon %s | icon set: %s",icon,pig)
|
|
--[[
|
|
use_custom_backpack_icon = load_mcm("pawpins/use_custom_backpack_icon",use_custom_backpack_icon)
|
|
if use_custom_backpack_icon then
|
|
local psicon = stash_icons["player"]
|
|
local newicon = ui_mcm.get("pawsys/pawpins/custom_backpack_icon")
|
|
if newicon ~= nil then
|
|
stash_icons["player"] = icons[newicon]
|
|
end
|
|
dl("MCM: Overriding player stash icon with custom value: %s",stash_icons["player"])
|
|
end
|
|
--]]
|
|
local cp = ui_mcm.get("pawsys/pawpins/use_custom_pin_icon") or false
|
|
if cp then
|
|
custom_pin_icon = true
|
|
map_pin_icon = ui_mcm.get("pawsys/pawpins/custom_pin_icon") or map_pin_icon
|
|
dl("MCM: Overriding default icon with custom value: %s",map_pin_icon)
|
|
else
|
|
custom_pin_icon = false
|
|
end
|
|
if force_icon_override then
|
|
dl("MCM: Script hardcoded to override map_pin_icon with %s",force_icon_override)
|
|
map_pin_icon = force_icon_override
|
|
default_mapspot = force_icon_override
|
|
end
|
|
|
|
if (bi and ish_kill_tracker) then
|
|
body_icon_mode = bi
|
|
current_body_icon = icons[cbi] or default_mapspot
|
|
ish_kill_tracker.use_paw_icon = (bi == "set") or (bi == "fac")
|
|
end
|
|
widget_enabled = load_mcm("pawhud/widget_enable",widget_enabled)
|
|
active_theme = load_mcm("pawhud/active_theme",active_theme)
|
|
if not hud_themes[active_theme] then active_theme = "classicauto" end
|
|
widget_custom_pos = {
|
|
x = load_mcm("pawhud/pos_x"),
|
|
y = load_mcm("pawhud/pos_y")
|
|
}
|
|
widget_use_custom_pos = load_mcm("pawhud/custompos")
|
|
widget_hide_delay = (tonumber(load_mcm("pawhud/autohide",widget_hide_delay)) * 1000)
|
|
use_ui_snd = load_mcm("pawhud/hudsound")
|
|
|
|
--[[
|
|
local mdf = clamp(tonumber(ui_mcm.get("pawsys/pawpins/fave_recent")),0,10)
|
|
if mdf and (mdf ~= max_dynamic_faves) then
|
|
local old_mdf = max_dynamic_faves
|
|
max_dynamic_faves = mdf
|
|
dl("new max_dynamic_faves: %s (was %s)",mdf,old_mdf)
|
|
if dynamic_faves and (not is_empty(dynamic_faves)) and
|
|
(max_dynamic_faves > 0) then
|
|
local df = {}
|
|
for i = 1,max_dynamic_faves do
|
|
if dynamic_faves[i] then
|
|
vl("dynamic_fave[%s]: %s",i,dynamic_faves[i])
|
|
df[i] = dynamic_faves[i]
|
|
end
|
|
end
|
|
dynamic_faves = df
|
|
end
|
|
end
|
|
--]]
|
|
end
|
|
|
|
function mcm_reload_reticle_settings()
|
|
if ui_mcm then
|
|
mark_on_positive_id = load_mcm("pawret/enable_autotag",mark_on_positive_id)
|
|
autotag_persistence = load_mcm("pawret/autotag_persistence",autotag_persistence)
|
|
autotag_lifetime = load_mcm("pawret/autotag_lifetime",(autotag_lifetime / 6)) * 6
|
|
autotags_time_out = (autotag_lifetime or 0) > 0
|
|
pin_hud_icon_default = load_mcm("pawret/pin_auto_visible",pin_hud_icon_default)
|
|
manual_smart_pins = load_mcm("pawret/manual_smart_pins",manual_smart_pins)
|
|
reticle_mode = load_mcm("pawret/reticle_mode",reticle_mode)
|
|
autotag_mode = load_mcm("pawret/reticle_mode",autotag_mode)
|
|
reticle_mustzoom = load_mcm("pawret/reticle_mustzoom",reticle_mustzoom)
|
|
reticle_color.a = load_mcm("pawret/reticle_alpha",reticle_color.a)
|
|
ret_fade_attack_time = load_mcm("pawret/ret_fade_attack_time",ret_fade_attack_time)
|
|
ret_fade_decay_time = load_mcm("pawret/ret_fade_decay_time",ret_fade_decay_time)
|
|
vl("Autotag settings: mode %s | mustzoom %s | manual %s",autotag_mode,reticle_mustzoom,manual_smart_pins)
|
|
for k,v in pairs(smart_pins) do
|
|
smart_pins[k].pin = load_mcm("pawret/"..k,v.pin)
|
|
smart_pins[k].enabled = load_mcm("pawret/"..k.."_enable",v.enabled)
|
|
end
|
|
-- Load Crook's facid settings, if present
|
|
local did = ui_mcm.get("targetID/timeID")
|
|
if did ~= nil then
|
|
npc_ident.delay_id = did
|
|
end
|
|
did = ui_mcm.get("targetID/deadID")
|
|
if did ~= nil then
|
|
npc_ident.id_bodies = did
|
|
end
|
|
npc_ident.id_speed = tonumber(ui_mcm.get("targetID/speedID")) or 0.3
|
|
npc_ident.lenience = tonumber(ui_mcm.get("targetID/targL")) or 0.99
|
|
end
|
|
end
|
|
|
|
|
|
function on_option_change()
|
|
|
|
-- Sync all MCM values and propagate changes
|
|
language = ui_options.curr_localization()
|
|
if ui_mcm and not mcm_killswitch then
|
|
debuglogs = load_mcm("pawgen/debuglogs",debuglogs)
|
|
catsy_paw_mcm.debuglogs = debuglogs
|
|
dl("Setting for debuglogs loaded from MCM: %s",debuglogs)
|
|
|
|
if load_mcm("pawgen/wipe_all") then
|
|
ui_mcm.set("pawsys/pawgen/wipe_all",false)
|
|
dl("MCM: Wiping all pin data per player request")
|
|
local hudpins = hud_pin_objs
|
|
for k,v in pairs(hudpins) do
|
|
hide_hud_pin(k)
|
|
end
|
|
hud_pin_objs = {}
|
|
for k,v in pairs(map_labels) do
|
|
map_labels[k].box:Show(false)
|
|
end
|
|
map_labels = {}
|
|
local args = {wipe_all=true,syscall=true}
|
|
do_paw_action("pn_clr",nil,nil,args)
|
|
end
|
|
|
|
mcm_reload_general_settings()
|
|
if not paw_enabled then
|
|
printf(logprefix.."Personal Adjustable Waypoint has been disabled, aborting all further action!")
|
|
return end
|
|
|
|
mcm_reload_keybind_table()
|
|
mcm_reload_keybind_settings()
|
|
mcm_reload_pin_settings()
|
|
mcm_reload_reticle_settings()
|
|
|
|
for k,v in pairs(action_codes) do
|
|
local m = load_mcm("pawmenu/"..k)
|
|
if m ~= nil then
|
|
action_codes[k].mode = tonumber(m) or 0
|
|
vl("MCM: Loading action code mode %s for %s",m,k)
|
|
else
|
|
vl("MCM: No value found for %s, leaving unchanged",k)
|
|
end
|
|
end
|
|
ui_mcm.set("pawsys/pawgen/mcm_ver",script_version)
|
|
end
|
|
|
|
if ish_kill_tracker and item_milpda then ish_kill_tracker.on_option_change() end
|
|
active_set(icon_sets[current_active_set].i)
|
|
if db.actor and get_hud() then
|
|
unsquish_ratio = (device().height / device().width) / (768 / 1024)
|
|
reset_indicator()
|
|
end
|
|
end
|
|
|
|
|
|
function load_active_icoset_data()
|
|
if not ui_mcm then return end
|
|
vl("Loading MCM values for sets and icons")
|
|
local path = "pawsys/pawpins/poi_icon_"
|
|
for k,v in pairs(icon_sets) do
|
|
local val = ui_mcm.get(path..k)
|
|
local icon = icons[val]
|
|
--printf("loading "..path..k..": %s | icons %s | icons[%s]: %s",val,icons,val,icons[val])
|
|
vl("Loading active icon for %s: %s = %s",k,val,icon)
|
|
icon_sets[k].default = val
|
|
icon_sets[k].active_icon = icon
|
|
end
|
|
local setname = ui_mcm.get("pawsys/pawpins/pin_icon_group")
|
|
if set_index[setname] then
|
|
active_set(set_index[setname])
|
|
end
|
|
end
|
|
|
|
function update_mcm_icoset_data()
|
|
if not ui_mcm then return end
|
|
if icoset_changed then
|
|
vl("Updating MCM settings after set/icon change",icoset_changed)
|
|
local curr_set = pawdata.curr_set_name
|
|
if icoset_changed and icoset_changed.s then
|
|
ui_mcm.set("pawsys/pawpins/pin_icon_group",curr_set)
|
|
end
|
|
local path = "pawsys/pawpins/poi_icon_"..curr_set
|
|
local active_pin = pin_for_icon(icon_sets[curr_set].active_icon)
|
|
ui_mcm.set(path,active_pin)
|
|
end
|
|
icoset_changed = nil
|
|
end
|
|
|
|
function check_waypoint_proximity(id)
|
|
local se_obj = id and alife_object(id)
|
|
if (not se_obj) or not (se_obj and se_obj.online) then return end
|
|
local szpos = se_obj.position
|
|
local dist = szpos:distance_to(db.actor:position()) or 0
|
|
if dist <= wp_clear_dist then
|
|
toggle_waypoint(false)
|
|
end
|
|
end
|
|
|
|
function tick()
|
|
if not paw_enabled then
|
|
UnregisterScriptCallback("actor_on_update",actor_on_update)
|
|
return
|
|
end
|
|
local now = time_global()
|
|
if enable_wp_proxcheck and waypoint_active and (next_wp_proxcheck <= now) then
|
|
next_wp_proxcheck = now + wp_proxcheck_interval
|
|
check_waypoint_proximity(placed_waypoint and placed_waypoint.id)
|
|
end
|
|
if (next_gc_check <= now) then
|
|
next_gc_check = now + garbcollect_interval
|
|
if script_zone_changed then
|
|
script_zone_cleanup()
|
|
end
|
|
temp_pin_cleanup()
|
|
end
|
|
if disable_mcm_updates then return end
|
|
if (next_mcm_update > now) or not icoset_changed then return end
|
|
next_mcm_update = now + mcm_update_throttle
|
|
update_mcm_icoset_data()
|
|
end
|
|
|
|
function paw_welcome_message()
|
|
if welcome_msg_shown then return true end
|
|
vl("Welcome message not shown yet, displaying to player")
|
|
welcome_msg_shown = true
|
|
if ui_mcm then
|
|
ui_mcm.set("pawsys/pawgen/welcome_msg_shown",true)
|
|
end
|
|
local player_name = alife():actor():character_name()
|
|
local kb = keybinds
|
|
toggle_bind = kb["wptoggle"].bind
|
|
toggle_mod = kb["wptoggle"].mod
|
|
quickpin_bind = kb["quickpin"].bind
|
|
quickpin_mod = kb["quickpin"].mod
|
|
cart_mode_hold = kb["cartmode"].bind
|
|
cart_mode_mod = kb["cartmode"].mod
|
|
local toggle_btxt = bindtext(toggle_bind,toggle_mod)
|
|
local quickpin_btxt = bindtext(quickpin_bind,quickpin_mod)
|
|
local cartmode_btxt = bindtext(cart_mode_hold,cart_mode_mod)
|
|
local welcome_msg = string.format(ts("st_pawsys_welcome_msg"),toggle_btxt,quickpin_btxt,cartmode_btxt,player_name)
|
|
welcome_msg = psk(welcome_msg,text_colors)
|
|
dotip(welcome_msg,10000)
|
|
return true
|
|
end
|
|
-- ======================================================================
|
|
-- UI ELEMENTS
|
|
-- ======================================================================
|
|
function setwndpos(wnd,x,y)
|
|
if not (wnd and x and y) then return end
|
|
wnd:SetWndPos(vector2():set(x,y))
|
|
end
|
|
-- ======================================================================
|
|
--[[ TEXT INPUT WINDOW
|
|
Originally adapted from parts of the vanilla backpack stash script
|
|
|
|
A more generic, parameterized version used to ship with PAW as its
|
|
own mod (ui_get_input.script)
|
|
-- ====================================================================]]
|
|
|
|
GUI_WP = nil
|
|
|
|
function open_waypoint_settings()
|
|
dl("open_waypoint_settings called")
|
|
tex = texdef or tex_defs
|
|
args = args or {}
|
|
|
|
if not GUI_WP then GUI_WP = UIWPSettings() end
|
|
|
|
if GUI_WP and not GUI_WP:IsShown() then
|
|
GUI_WP:ShowDialog(true)
|
|
Register_UI("UIWPSettings","open_waypoint_settings")
|
|
end
|
|
end
|
|
|
|
local function destroy_wp_window()
|
|
if GUI_WP then
|
|
GUI_WP:HideDialog()
|
|
GUI_WP = nil
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
|
|
class "UIWPSettings" (CUIScriptWnd)
|
|
|
|
function UIWPSettings:__init() super()
|
|
vl("UIWPSettings:__init:\nTitle: %s\nIcon: %s\nExisting text: %s",title_txt,icon_tex,prepop)
|
|
self.init_time = tostring(get_time_elapsed())
|
|
self.init_wp = placed_waypoint
|
|
self.init_state = waypoint_active
|
|
self.def_wpname = custom_name or ts("st_paw_placed_waypoint")..(": "..placed_waypoint.name or "")
|
|
self.def_wpdesc = custom_desc or ts("st_paw_proceed")
|
|
self.pin_text = title_txt
|
|
self.icon_tex = "ui_inGame2_PDA_icon_Secondary_mission"
|
|
self.prepop = prepop
|
|
self.func = func
|
|
self.args = args
|
|
self.cap = {}
|
|
|
|
self:InitControls()
|
|
self:InitCallBacks()
|
|
|
|
self.control_hints = {
|
|
["btn_wpreset"] = true,
|
|
}
|
|
self.hint_wnd = utils_ui.UIHint(self)
|
|
end
|
|
|
|
function UIWPSettings:__finalize()
|
|
end
|
|
|
|
function UIWPSettings:InitControls()
|
|
self:SetWndRect(Frect():set(0,0,1024,768))
|
|
self:SetAutoDelete(true)
|
|
|
|
local xml = CScriptXmlInit()
|
|
local file = "paw_input_window.xml"
|
|
local root = "wp_dialog"
|
|
local rootand = root..":"
|
|
local tbar = rootand.."titlebar"
|
|
local paw = tbar..":paw"
|
|
local text = tbar..":text"
|
|
local icon = tbar..":icon"
|
|
local reset = rootand.."btn_wpreset"
|
|
local cancel = rootand.."btn_cancel"
|
|
local input_n = rootand.."input_name"
|
|
local input_d = rootand.."input_desc"
|
|
local btn_ok = rootand.."btn_ok"
|
|
local caption = rootand.."caption"
|
|
|
|
xml:ParseFile (file)
|
|
|
|
self.dialog = xml:InitStatic(root, self)
|
|
local bg_top = xml:InitStatic(rootand.."bg_top",self.dialog)
|
|
local bg_btm = xml:InitStatic(rootand.."bg_btm",self.dialog)
|
|
self.bg_wpdesc = xml:InitStatic(rootand.."bg_desc",self.dialog)
|
|
|
|
self.wpname = xml:InitEditBox(input_n,self.dialog)
|
|
self:Register(self.wpname,"fld_input_name")
|
|
self.wpname:SetText(self.def_wpname)
|
|
self.wpname:SetWndSize(vector2():set(220,30))
|
|
|
|
--self.descbg = xml:InitStatic(input_d,self.dialog)
|
|
--self.descbg:InitTexture("ui_paw_dialog_large_text_field")
|
|
self.wpdesc = xml:InitEditBox(input_d, self.bg_wpdesc)
|
|
self:Register(self.wpdesc,"fld_input_desc")
|
|
self.wpdesc:SetText(self.def_wpdesc)
|
|
--self.descbg:SetWndSize(vector2():set(171,188))
|
|
self.wpdesc:SetWndSize(vector2():set(220,30))
|
|
|
|
self.tbar = xml:InitStatic(tbar,self.dialog)
|
|
local paw = xml:InitTextWnd(paw,self.tbar)
|
|
paw:SetText("PAW".." "..script_version)
|
|
paw:SetFont(GetFontSmall())
|
|
|
|
|
|
self.icon = xml:InitStatic(icon, self.tbar)
|
|
if self.icon_tex then
|
|
self.icon:InitTexture(self.icon_tex)
|
|
else
|
|
dl("Empty icon texture passed to input window")
|
|
end
|
|
|
|
|
|
self.titletxt = xml:InitTextWnd(text, self.tbar)
|
|
self.titletxt:SetText(ts("ui_mcm_pawsys_pawmenu_wp_settings"))
|
|
self.titletxt:SetFont(GetFontDI())
|
|
|
|
self.targetname = xml:InitStatic(rootand.."target",self.dialog)
|
|
|
|
self.tartxt = ts("st_paw_target")..": "
|
|
self.tarclr = "$clr_wht"
|
|
if placed_waypoint and placed_waypoint.id then
|
|
self.tarclr = "$clr_yel"
|
|
local tartxt = self.tartxt..self.tarclr..safename(placed_waypoint.id)
|
|
self.tartxt = psk(tartxt,text_colors)
|
|
self.targetname:TextControl():SetText(self.tartxt)
|
|
else
|
|
self.targetname:TextControl():SetText(ts("st_paw_none"))
|
|
end
|
|
|
|
local function setup_checkbox(setting,pos_x,pos_y,captext,default)
|
|
local checkopt = "check_"..setting
|
|
vl("Initializing checkbox %s (%s) at %s,%s | %s",checkopt,setting,pos_x,pos_y,captext)
|
|
self[checkopt] = xml:InitCheck(rootand.."check",self.dialog)
|
|
self:Register(self[checkopt], checkopt..self.init_time)
|
|
self[checkopt]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
self[checkopt]:SetCheck(default)
|
|
|
|
if captext then
|
|
self.cap[checkopt] = xml:InitTextWnd(caption,self[checkopt])
|
|
self.cap[checkopt]:SetWndPos(vector2():set(30,8))
|
|
self.cap[checkopt]:SetText(captext)
|
|
self.cap[checkopt]:SetVTextAlignment(1)
|
|
end
|
|
end
|
|
|
|
function setup_button(button,pos_x,pos_y,xmlnode)
|
|
local buttonx = "btn_"..button
|
|
vl("Initializing button %s (%s) at %s,%s",buttonx,button,pos_x,pos_y)
|
|
self[buttonx] = xml:Init3tButton(xmlnode,self.dialog)
|
|
self:Register(self[buttonx],buttonx)
|
|
self[buttonx]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
end
|
|
|
|
setup_checkbox( "wpactive", 15, 152, ts("st_paw_wp_active"), waypoint_active )
|
|
setup_checkbox( "wphud", 15, 178, ts("ui_mcm_pawsys_pawgen_wp_hud_icon_enabled"), wp_hud_icon_enabled )
|
|
self.check_wpactive:SetCheck(self.init_state)
|
|
self.check_wphud:SetCheck(wp_hud_icon_enabled)
|
|
|
|
setwndpos( paw, 215, 26 )
|
|
setwndpos( self.titletxt, 7, 7 )
|
|
|
|
setwndpos( self.icon, 17, 121 )
|
|
setwndpos( self.targetname, 50, 130 )
|
|
|
|
setwndpos( self.wpname, 25, 38 )
|
|
--setwndpos( self.descbg, 25, 90 )
|
|
setwndpos( self.wpdesc, 25, 4 )
|
|
setup_button( "wpreset", 20, 210, reset )
|
|
setup_button( "ok", 112, 210, btn_ok )
|
|
setup_button( "cancel", 183, 210, cancel )
|
|
|
|
|
|
end
|
|
|
|
|
|
function UIWPSettings:InitCallBacks()
|
|
self:AddCallback("btn_wpreset", ui_events.BUTTON_CLICKED, self.Reset, self)
|
|
self:AddCallback("btn_ok", ui_events.BUTTON_CLICKED, self.OnAccept, self)
|
|
self:AddCallback("btn_cancel", ui_events.BUTTON_CLICKED, self.Close, self)
|
|
end
|
|
|
|
|
|
function UIWPSettings:ShowHint(hint)
|
|
if hint then
|
|
hint = psk(hint,text_colors)
|
|
--vl("* [%s] Showing hint_wnd text: %s",time_global(),hint)
|
|
end
|
|
self.hint_wnd:Update(hint)
|
|
end
|
|
|
|
|
|
function UIWPSettings:Reset()
|
|
dl("Restoring default waypoint settings")
|
|
--self.icon_tex = "ui_inGame2_PDA_icon_Secondary_mission"
|
|
--self.icon:InitTexture(self.icon_tex)
|
|
custom_name = nil
|
|
custom_desc = nil
|
|
self.wpname:SetText(self.def_wpname)
|
|
self.wpdesc:SetText(self.def_wpdesc)
|
|
|
|
wp_hud_icon_enabled = true
|
|
self.check_wphud:SetCheck(true)
|
|
end
|
|
|
|
|
|
function UIWPSettings:Update()
|
|
CUIScriptWnd.Update(self)
|
|
self.hint = nil
|
|
for ctrl,enable in pairs(self.control_hints) do
|
|
if enable and self[ctrl] and self[ctrl]:IsCursorOverWindow() then
|
|
local st_hint = hint_path..ctrl.."_desc"
|
|
local hint = ts(st_hint)
|
|
self.hint = hint
|
|
--vl("Showing hint for %s: %s\n\"%s\"",ctrl,st_hint,hint)
|
|
end
|
|
end
|
|
self:ShowHint(self.hint)
|
|
end
|
|
|
|
|
|
function UIWPSettings:OnAccept()
|
|
local new_wpname = self.wpname:GetText()
|
|
if new_wpname ~= self.def_wpname then
|
|
custom_name = new_wpname
|
|
end
|
|
|
|
local new_wpdesc = self.wpdesc:GetText()
|
|
if new_wpdesc ~= self.def_wpdesc then
|
|
custom_desc = new_wpdesc
|
|
end
|
|
|
|
local new_wpstate = self.check_wpactive:GetCheck()
|
|
if self.init_state ~= new_wpstate then
|
|
toggle_waypoint()
|
|
end
|
|
|
|
local new_hudstate = self.check_wphud:GetCheck()
|
|
if new_hudstate and not wp_hud_icon_enabled then
|
|
wp_hud_icon_enabled = true
|
|
show_hud_waypoint()
|
|
elseif wp_hud_icon_enabled and not new_hudstate then
|
|
wp_hud_icon_enabled = false
|
|
hide_hud_waypoint()
|
|
end
|
|
|
|
dl("UIWPSettings:OnAccept | custom_name: %s | custom_desc: %s",custom_name,custom_desc)
|
|
self:Close()
|
|
end
|
|
|
|
|
|
function UIWPSettings:OnKeyboard(dik, keyboard_action)
|
|
local res = CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
|
|
if (res == false) then
|
|
local bind = dik_to_bind(dik)
|
|
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
|
|
if dik == DIK_keys.DIK_ESCAPE then
|
|
self:Close()
|
|
end
|
|
end
|
|
end
|
|
return res
|
|
end
|
|
|
|
|
|
function UIWPSettings:Close()
|
|
self:HideDialog()
|
|
Unregister_UI("UIWPSettings")
|
|
destroy_wp_window()
|
|
end
|
|
|
|
|
|
-- ======================================================================
|
|
--[[ PIN SETTINGS WINDOW
|
|
-- ====================================================================]]
|
|
|
|
GUI_PinOpts = nil
|
|
|
|
|
|
function pin_window_is_open()
|
|
return GUI_PinOpts and GUI_PinOpts:IsShown()
|
|
end
|
|
|
|
function open_pin_settings(id,args)
|
|
if not GUI_PinOpts then
|
|
GUI_PinOpts = UIPinSettingsWnd(id,args)
|
|
end
|
|
|
|
if GUI_PinOpts and not GUI_PinOpts:IsShown() then
|
|
GUI_PinOpts:Reset(id)
|
|
GUI_PinOpts:ShowDialog(true)
|
|
Register_UI("UIPinSettingsWnd","pin_settings")
|
|
end
|
|
end
|
|
|
|
function destroy_pin_window()
|
|
GUI_PinOpts = nil
|
|
end
|
|
|
|
-- ======================================================================
|
|
|
|
class "UIPinSettingsWnd" (CUIScriptWnd)
|
|
|
|
function UIPinSettingsWnd:__init(id,args) super()
|
|
vl("UIPinSettingsWnd:__init(%s,args passed: %s",id,args ~= nil)
|
|
if not ((id and id > 0) and pins[id]) then return end
|
|
if debuglogs and verbose then
|
|
local pin = pins[id]
|
|
printf(logprefix.."Initializing settings window for pin %s:\nName: %s\nLocked: %s | Show on HUD %s | Show Label %s | Custom ARGB: %s",
|
|
id, pin.name, pin.lock, pin.hud, pin.show_label, pin.custom_colors
|
|
)
|
|
if pins[id].custom_colors and pins[id].colors then
|
|
local colors = pins[id].colors
|
|
--printf(logprefix.."A: %s | R: %s | G: %s | B: %s",colors.a,colors.r,colors.g,colors.b)
|
|
end
|
|
end
|
|
self.init_time = tostring(get_time_elapsed())
|
|
self.next_update = time_global()
|
|
self.icon_refresh = true
|
|
--self:BackupTempSettings()
|
|
self:Reset(id,args)
|
|
self:InitControls()
|
|
self:HijackWidget()
|
|
self:RefreshIcon()
|
|
self.hint_wnd = utils_ui.UIHint(self)
|
|
self:AllowMovement(true)
|
|
end
|
|
|
|
function UIPinSettingsWnd:__finalize()
|
|
end
|
|
|
|
|
|
function UIPinSettingsWnd:BackupTempSettings(restore)
|
|
if not self.backups then
|
|
self.backups = {}
|
|
end
|
|
if restore then
|
|
dl("UIPinSettingsWnd | restoring old settings:\nwidget_enabled = %s\nwidget_hide_delay = %s | active_theme = %s",widget_enable,widget_hide_delay,active_theme)
|
|
widget_enabled = self.backups.enable
|
|
active_theme = self.backups.active or active_theme
|
|
widget_hide_delay = self.backups.autohide or widget_hide_delay
|
|
widget_use_custom_pos = self.backups.use_cust_pos or widget_use_custom_pos
|
|
widget_custom_pos = self.backups.cust_pos or widget_custom_pos
|
|
|
|
self.backups = {}
|
|
else
|
|
dl("UIPinSettingsWnd | storing current settings:\nwidget_enabled = %s\nwidget_hide_delay = %s | active_theme = %s",widget_enable,widget_hide_delay,active_theme)
|
|
self.backups = {
|
|
enabled = widget_enabled,
|
|
autohide = widget_hide_delay,
|
|
active = active_theme,
|
|
use_cust_pos= widget_use_custom_pos,
|
|
cust_pos = widget_custom_pos,
|
|
}
|
|
active_theme = "pin_sidebar"
|
|
widget_hide_delay = 0
|
|
widget_use_custom_pos = true
|
|
end
|
|
end
|
|
|
|
function UIPinSettingsWnd:HijackWidget()
|
|
reset_indicator(true,self.dialog)
|
|
end
|
|
|
|
function UIPinSettingsWnd:InitControls()
|
|
self:SetWndRect(Frect():set(0,0,1024,768))
|
|
self:SetAutoDelete(true)
|
|
self.empty = "ui_paw_emptytex"
|
|
self.cap = {}
|
|
local pin = self.pin or self.pin_id and pins[self.pin_id]
|
|
|
|
self.control_hints = {
|
|
["check_hud"] = true,
|
|
["check_text"] = true,
|
|
["check_lock"] = true,
|
|
["check_argb"] = true,
|
|
["input"] = true,
|
|
["input_a"] = true,
|
|
["input_r"] = true,
|
|
["input_g"] = true,
|
|
["input_b"] = true,
|
|
["btn_sidebar"] = true,
|
|
["btn_ok"] = true,
|
|
["btn_cancel"] = true,
|
|
["btn_delete"] = true,
|
|
["btn_sound"] = true,
|
|
}
|
|
|
|
local clrtxt ={
|
|
a = ts("st_paw_argb_a"),
|
|
r = ts("st_paw_argb_r"),
|
|
g = ts("st_paw_argb_g"),
|
|
b = ts("st_paw_argb_b")
|
|
}
|
|
|
|
local xml = CScriptXmlInit()
|
|
local xmlfile = "paw_input_window.xml"
|
|
local xmlroot = "pin_dialog"
|
|
local root = xmlroot..":"
|
|
local tbar = root.."titlebar"
|
|
local icon = root.."icon"
|
|
local paw = tbar..":paw"
|
|
local icopanel = icon.."_panel"
|
|
local icoframe = icon.."_frame"
|
|
local icowater = icon.."_watermark"
|
|
local caption = root.."caption"
|
|
local bg = root.."bg_settings"
|
|
local dialog = root.."pin_settings"
|
|
local chrome = root.."chrome"
|
|
local input = root.."input_name"
|
|
local input_a = root.."input_a"
|
|
local input_r = root.."input_r"
|
|
local input_g = root.."input_g"
|
|
local input_b = root.."input_b"
|
|
local btn_ok = root.."btn_ok"
|
|
local cancel = root.."btn_cancel"
|
|
local delete = root.."btn_delete"
|
|
local check = root.."check"
|
|
local listbox = root.."listbox"
|
|
local opt_icon = root.."opt_icon"
|
|
local opt_cap = opt_icon..":caption"
|
|
local sidebar = root.."sidebar"
|
|
local sb_btn = root.."btn_sidebar"
|
|
local btn_sound = root.."btn_sound"
|
|
local head_txt = self.title
|
|
local lock_txt = ts("ui_mcm_pawsys_pawmenu_lock_pin")
|
|
local label_txt = ts("ui_mcm_pawsys_pawmenu_show_label")
|
|
local hud_txt = ts("ui_mcm_pawsys_pawmenu_hud_vis_on")
|
|
local argb_txt = ts("ui_paw_use_custom_color")
|
|
local mstt_txt = ts("ui_paw_mapspot_tooltip_mode")
|
|
local set_curr = ts("ui_mcm_lst_pawsys_pg_"..pawdata.curr_set_name)
|
|
local ico_curr = ts("ui_mcm_lst_"..pawdata.curr_ico_name)
|
|
|
|
xml:ParseFile (xmlfile)
|
|
|
|
--================================================================--
|
|
--Title bar
|
|
if not self.dialog then
|
|
self.dialog = xml:InitStatic(dialog, self)
|
|
self.dialog:SetWndSize(vector2():set(400,300))
|
|
self.dialog:SetWndPos(vector2():set(392,200))
|
|
|
|
self.chrome = xml:InitStatic(chrome, self.dialog)
|
|
self.chrome:InitTexture("ui_paw_dialog_classic_chrome")
|
|
local titletab_sh = xml:InitStatic(caption, self.chrome)
|
|
local titletab = xml:InitStatic(caption, self.chrome)
|
|
titletab_sh:TextControl():SetText(head_txt)
|
|
titletab_sh:TextControl():SetFont(GetFontDI())
|
|
titletab_sh:TextControl():SetTextColor( GetARGB(255,0,0,0) )
|
|
titletab_sh:SetWndPos(vector2():set(18,9))
|
|
titletab_sh:InitTexture("ui_paw_fade_cap_bg_full")
|
|
titletab:TextControl():SetText(head_txt)
|
|
titletab:TextControl():SetFont(GetFontDI())
|
|
titletab:SetWndPos(vector2():set(19,9))
|
|
|
|
self.tbar = xml:InitStatic(tbar,self.dialog)
|
|
local paw = xml:InitTextWnd(paw,self.tbar)
|
|
paw:SetText("PAW".." "..script_version)
|
|
paw:SetFont(GetFontSmall())
|
|
paw:SetWndPos(vector2():set(195,34))
|
|
|
|
psw_sidebar_state = false
|
|
show_indicator(false)
|
|
end
|
|
|
|
--================================================================--
|
|
-- Rename/relabel input box
|
|
vl("Setting up name input box")
|
|
self.input = xml:InitEditBox(input,self.dialog)
|
|
self:Register(self.input,"fld_input"..self.init_time)
|
|
self.input:SetWndSize(vector2():set(190,30))
|
|
self.input:SetWndPos(vector2():set(8,7))
|
|
vl("Setting name input field to %s",self.pin_text)
|
|
self.input:SetText(self.pin_text)
|
|
|
|
--==== Icon and Set area initialization ==========================--
|
|
-- Icon display
|
|
if not self.icon_display_panel then
|
|
self.icon_display_panel = xml:InitStatic(icopanel, self.dialog)
|
|
self.icon_panel = xml:InitStatic(icowater, self.icon_display_panel)
|
|
unsquish_aspect(self.icon_panel)
|
|
local icoframe = xml:InitStatic(icoframe, self.icon_display_panel)
|
|
unsquish_aspect(icoframe)
|
|
self.icon = xml:InitStatic(icon, self.icon_display_panel)
|
|
unsquish_aspect(self.icon)
|
|
local w = self.icon:GetWidth()
|
|
self.icon:SetWndPos(vector2():set(11.75,16))
|
|
end
|
|
self:RefreshIcon(self.icon_tex)
|
|
self.argb_controls = xml:InitStatic(root.."argb_chrome",self.dialog)
|
|
--================================================================--
|
|
|
|
local function setup_argb_control(color,pos_x,pos_y)
|
|
local inputx = "input_"..color
|
|
vl("Initializing ARGB control %s for color %s at %s,%s",inputx,color,pos_x,pos_y)
|
|
local xsh = color.."_sh"
|
|
local xtx = color.."_tx"
|
|
local xmlnode = root..":"..inputx
|
|
self.argb_box = {}
|
|
self.argb_box[color] = xml:InitStatic(xmlnode,self.argb_controls)
|
|
self.argb_box[color]:SetWndSize(vector2():set(65,31))
|
|
unsquish_aspect(self.argb_box[color])
|
|
self.argb_box[color]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
self.argb_box[color]:InitTexture("ui_paw_dialog_argb_single")
|
|
|
|
self[inputx] = xml:InitEditBox(xmlnode,self.argb_box[color])
|
|
self:Register(self[inputx],"fld_input_"..color..self.init_time)
|
|
--printf("Original method - %s | color: %s | self.colors[%s]",inputx,color,color,self.colors[color])
|
|
|
|
self.cap[color] = xml:InitStatic(opt_icon,self.argb_box[color])
|
|
self.cap[color]:InitTexture("ui_icons_paw_argb_"..color)
|
|
unsquish_aspect(self.cap[color])
|
|
--self.cap[xsh] = xml:InitStatic(opt_cap.."_sh",self.cap[color])
|
|
--self.cap[xsh]:TextControl():SetTextColor( GetARGB(255,0,0,0) )
|
|
--self.cap[xtx] = xml:InitStatic(opt_cap,self.cap[color])
|
|
self:SetARGBVal(color,self.colors[color])
|
|
self[inputx]:SetWndPos(vector2():set(18.5,2.5))
|
|
|
|
local boxframe = xml:InitStatic(xmlnode,self.argb_box[color])
|
|
boxframe:SetWndSize(vector2():set(65,31))
|
|
unsquish_aspect(boxframe)
|
|
--boxframe:SetWndPos(vector2():set(pos_x,pos_y))
|
|
boxframe:InitTexture("ui_paw_dialog_argb_single_nobg")
|
|
end
|
|
|
|
local function setup_checkbox(setting,pos_x,pos_y,captext)
|
|
local checkopt = "check_"..setting
|
|
vl("Initializing checkbox %s (%s) at %s,%s | %s",checkopt,setting,pos_x,pos_y,captext)
|
|
self[checkopt] = xml:InitCheck(check,self.dialog)
|
|
self:Register(self[checkopt], checkopt..self.init_time)
|
|
self[checkopt]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
if captext then
|
|
self.cap[checkopt] = xml:InitTextWnd(caption,self[checkopt])
|
|
self.cap[checkopt]:SetWndPos(vector2():set(30,8))
|
|
self.cap[checkopt]:SetText(captext)
|
|
self.cap[checkopt]:SetVTextAlignment(1)
|
|
end
|
|
end
|
|
|
|
|
|
function setup_button(button,pos_x,pos_y,xmlnode)
|
|
local buttonx = "btn_"..button
|
|
vl("Initializing button %s (%s) at %s,%s",buttonx,button,pos_x,pos_y)
|
|
self[buttonx] = xml:Init3tButton(xmlnode,self.dialog)
|
|
self:Register(self[buttonx],buttonx)
|
|
self[buttonx]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
end
|
|
|
|
--[[
|
|
-- not ready yet
|
|
|
|
function setup_listbox(setting,pos_x,pos_y,captext,opts)
|
|
local num_opts = #opts or 0
|
|
if num_opts < 1 then
|
|
vl("Unable to initialize list %s, no opts passed",setting)
|
|
return
|
|
end
|
|
|
|
local listopt = "lst_"..setting
|
|
vl("Initializing list %s at %s,%s with %s options",listopt,pos_x,pos_y,num_opts)
|
|
|
|
self[listopt] = xml:InitComboBox(listbox,self.dialog)
|
|
self[listopt]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
if captext then
|
|
self.cap[listopt] = xml:InitTextWnd(caption,self[listopt])
|
|
self.cap[listopt]:SetWndPos(vector2():set(0,-10))
|
|
self.cap[listopt]:SetText(captext)
|
|
self.cap[listopt]:SetVTextAlignment(1)
|
|
end
|
|
|
|
local def = pin.tooltip or pin_tooltip_mode
|
|
local opt,tsopt
|
|
for i=1,num_opts do
|
|
tsopt = opts[i][2]
|
|
tsopt = tsopt and "ui_mcm_lst_pawsys_"..tsopt
|
|
opt = ts(tsopt)
|
|
vl("+ Adding list option %s: %s (%s)\n+- %s",i,opts[i][2],opts[i][1],opt)
|
|
self[listopt]:AddItem(opt,i)
|
|
if opts[i][1] == def then
|
|
vl("* +- %s is default value",def)
|
|
self[listopt]:enable_id(def)
|
|
self[listopt]:SetText(opt)
|
|
end
|
|
self:Register(self[listopt],listopt)
|
|
end
|
|
end
|
|
--]]
|
|
--================================================================--
|
|
-- Setup and place all elements
|
|
--========================= X ===== Y ============================--
|
|
|
|
setup_argb_control( "a", 25, 13 )
|
|
setup_argb_control( "r", 75, 13 )
|
|
setup_argb_control( "g", 125, 13 )
|
|
setup_argb_control( "b", 180, 13 )
|
|
|
|
--[[
|
|
-- not ready yet
|
|
setup_listbox("tooltip", 5, 70, mstt_txt,
|
|
{
|
|
{2, "msttmode_text"},
|
|
{1, "msttmode_obj"},
|
|
{0, "cmenu_off"},
|
|
}
|
|
)
|
|
--]]
|
|
|
|
setup_checkbox( "hud", 5, 85, hud_txt )
|
|
setup_checkbox( "text", 5, 110, label_txt )
|
|
setup_checkbox( "lock", 5, 135, lock_txt )
|
|
setup_checkbox( "argb", 5, 160, argb_txt )
|
|
|
|
self:RefreshChecks()
|
|
|
|
setup_button( "sidebar", 230, -10, sb_btn )
|
|
setup_button( "delete", 5.5, 245.5, delete )
|
|
setup_button( "ok", 95, 245.5, btn_ok )
|
|
setup_button( "cancel", 154, 245.5, cancel )
|
|
setup_button( "sound", 235.5, 267.5, btn_sound)
|
|
|
|
--================================================================--
|
|
|
|
widget_custom_pos = { x= 141, y= 46 }
|
|
|
|
self.icon_display_panel:SetWndPos(vector2():set(150,77))
|
|
self.argb_controls:SetWndPos(vector2():set( -5.5, 192))
|
|
|
|
self:InitCallBacks()
|
|
self.init_done = true
|
|
|
|
--self.input:CaptureFocus(true)
|
|
end
|
|
|
|
function UIPinSettingsWnd:InitCallBacks()
|
|
vl("UIPinSettingsWnd registering callbacks")
|
|
self:AddCallback("btn_ok", ui_events.BUTTON_CLICKED, self.OnAccept, self)
|
|
self:AddCallback("btn_cancel", ui_events.BUTTON_CLICKED, self.Close, self)
|
|
self:AddCallback("btn_delete", ui_events.BUTTON_CLICKED, self.DeletePin, self)
|
|
self:AddCallback("btn_sidebar", ui_events.BUTTON_CLICKED, self.ToggleSidebar, self)
|
|
self:AddCallback("btn_sound", ui_events.BUTTON_CLICKED, self.ToggleSound, self)
|
|
end
|
|
|
|
function UIPinSettingsWnd:GetAnchorStatic()
|
|
if self.dialog then
|
|
return self.dialog
|
|
else
|
|
dl("ERROR self.dialog was nil!")
|
|
end
|
|
end
|
|
|
|
|
|
function UIPinSettingsWnd:ApplyIconToPin(icon)
|
|
icon = icon or pawdata.curr_ico_name
|
|
pins[self.pin_id].text = pins[self.pin_id].text or pins[self.pin_id].name
|
|
local text = get_tooltip_for_pin(self.pin_id)
|
|
local old_icon = pins[self.pin_id].icon
|
|
pins[self.pin_id].icon = icon
|
|
change_mapspot(text,self.pin_id,icon,old_icon)
|
|
self.new_icon = nil
|
|
self.icon_refresh = true
|
|
self:RefreshIcon()
|
|
end
|
|
|
|
function UIPinSettingsWnd:SetARGBVal(color,val)
|
|
local inputx = "input_"..color
|
|
--printf("SetARGB method - inputx: %s | color: %s | val %s",inputx,color,val)
|
|
if color and val and self[inputx] then
|
|
--printf("Current color for %s is %s, setting to value %s",color,self[inputx]:GetText(),val)
|
|
self[inputx]:SetText(val)
|
|
end
|
|
end
|
|
|
|
function UIPinSettingsWnd:RefreshIcon(texture)
|
|
if not (texture or self.icon_refresh) then return end
|
|
if not self.icon then return end
|
|
vl("UIPinSettingsWnd:RefreshIcon(%s) %s",texture,self.icon_refresh and "| self.icon_refresh flagged" or "",self.icon_refresh)
|
|
|
|
self.icon_curr = pins[self.pin_id].icon or self.icon_curr
|
|
texture = texture or texture_for_icon(self.icon_curr)
|
|
if texture then
|
|
self.icon:InitTexture(texture)
|
|
self.icon:SetTextureColor(GetARGB(self.colors.a,self.colors.r,self.colors.g,self.colors.b))
|
|
self.icon_refresh = false
|
|
return true
|
|
else
|
|
dl("No texture found by UIPinSettingsWnd:RefreshIcon!")
|
|
return
|
|
end
|
|
end
|
|
|
|
function UIPinSettingsWnd:SetSoundIcon()
|
|
if self.btn_sound then
|
|
local bstate = use_ui_snd and "on" or "off"
|
|
self.btn_sound:InitTexture("ui_paw_btn_sound"..bstate)
|
|
end
|
|
end
|
|
|
|
function UIPinSettingsWnd:ToggleSound()
|
|
use_ui_snd = not use_ui_snd
|
|
vl("Toggling UI sfx to %s",use_ui_snd)
|
|
self:SetSoundIcon()
|
|
end
|
|
|
|
|
|
function UIPinSettingsWnd:ToggleSidebar()
|
|
psw_sidebar_state = not psw_sidebar_state
|
|
vl("Toggling sidebar widget to %s",psw_sidebar_state)
|
|
GUI_PinInd:ShowDialog(psw_sidebar_state)
|
|
if psw_sidebar_state then
|
|
self.btn_sidebar:InitTexture("ui_paw_btn_close_sidebar")
|
|
else
|
|
self.btn_sidebar:InitTexture("ui_paw_btn_open_sidebar")
|
|
end
|
|
--self.icoset_controls:Show(psw_sidebar_state)
|
|
play_ui_sound(snd_cycle_blip)
|
|
end
|
|
|
|
--[[
|
|
function UIPinSettingsWnd:Callback_Input(color)
|
|
vl("UIPinSettingsWnd:Callback_Input for color %s",color)
|
|
-- largely lifted from MCM
|
|
local is_color = self.colors[color] and true or false
|
|
local value = ctrl:GetText()
|
|
local default = self.default_all
|
|
local min = 0
|
|
local max = 255
|
|
local ctrl = is_color and "input" or "input_"..color
|
|
|
|
if not (value and value ~= "") then
|
|
value = default
|
|
elseif is_color then
|
|
value = tonumber(value)
|
|
if (not value) then
|
|
ctrl:SetText(default)
|
|
return
|
|
end
|
|
value = clamp(value, min, max)
|
|
end
|
|
printf("Input callback got value %s",value)
|
|
if value ~= ctrl:GetText() then
|
|
self.cust_argb = true
|
|
end
|
|
ctrl:SetText(value)
|
|
self.colors[color] = value
|
|
local a = self.colors.a
|
|
local r = self.colors.r
|
|
local g = self.colors.g
|
|
local b = self.colors.b
|
|
dl("Setting custom ARGB of %s|%s|%s|%s for %s",a,r,g,b)
|
|
self.icon:SetTextureColor(GetARGB(a,r,g,b))
|
|
end
|
|
--]]
|
|
|
|
function UIPinSettingsWnd:RefreshChecks()
|
|
if self.check_text then
|
|
self.check_text:SetCheck(self.show_label)
|
|
--vl("check_text after refresh: %s",self.check_text:GetCheck())
|
|
end
|
|
if self.check_hud then
|
|
self.check_hud:SetCheck(self.show_hud)
|
|
--vl("check_hud after refresh: %s",self.check_hud:GetCheck())
|
|
end
|
|
if self.check_lock then
|
|
self.check_lock:SetCheck(self.locked)
|
|
--vl("check_lock after refresh: %s",self.check_lock:GetCheck())
|
|
end
|
|
if self.check_argb then
|
|
self.check_argb:SetCheck(self.cust_argb)
|
|
--vl("check_argb after refresh: %s",self.check_argb:GetCheck())
|
|
end
|
|
self:SetSoundIcon()
|
|
end
|
|
|
|
function UIPinSettingsWnd:Reset(id,args)
|
|
self.new_icon = nil
|
|
self.args = args
|
|
if args and args.wipe then
|
|
self.icon_changed = false
|
|
self.set_changed = false
|
|
|
|
self.cust_argb = nil
|
|
self.title = nil
|
|
self.pin_id = nil
|
|
self.pin = nil
|
|
self.locked = nil
|
|
self.show_hud = nil
|
|
self.show_label = nil
|
|
self.pin_text = nil
|
|
self.init_time = nil
|
|
self.icon_tex = nil
|
|
self.colors = nil
|
|
self.tooltip = nil
|
|
self.icon:InitTexture(self.empty)
|
|
return
|
|
end
|
|
|
|
self.title = args and args.title or ts("ui_mcm_pawsys_pawmenu_pn_settings")
|
|
self.pin_id = id
|
|
self.pin = pins[self.pin_id]
|
|
self.cust_argb = self.pin.custom_colors
|
|
self.locked = self.pin.locked
|
|
self.show_hud = self.pin.hud
|
|
self.show_label = self.pin.show_label
|
|
self.tooltip = self.pin.tooltip
|
|
self.pin_text = self.pin.text or self.pin.name
|
|
self.init_time = tostring(get_time_elapsed())
|
|
self.icon_tex = texture_for_icon(self.pin.icon)
|
|
self.colors = self.pin.colors
|
|
if not self.colors then
|
|
vl("no stored colors in pin %s, defaulting ARGB to 255",id)
|
|
self.colors = {
|
|
a = 255,
|
|
r = 255,
|
|
g = 255,
|
|
b = 255
|
|
}
|
|
end
|
|
for k,v in pairs(self.colors) do
|
|
self:SetARGBVal(k,v)
|
|
end
|
|
self:RefreshChecks()
|
|
if self.input then
|
|
self.input:SetText(self.pin_text)
|
|
end
|
|
self:RefreshIcon()
|
|
end
|
|
|
|
|
|
function UIPinSettingsWnd:Update()
|
|
--printf("PAW: psw_sidebar_state: %s | widget_active: %s",psw_sidebar_state,widget_active)
|
|
if not self.init_done then return end
|
|
if time_global() < self.next_update then return end
|
|
self.next_update = time_global() + 10
|
|
|
|
CUIScriptWnd.Update(self)
|
|
|
|
self.hint = nil
|
|
for ctrl,enable in pairs(self.control_hints) do
|
|
if enable and self[ctrl] and self[ctrl]:IsCursorOverWindow() then
|
|
local st_hint = hint_path..ctrl.."_desc"
|
|
local hint = ts(st_hint)
|
|
self.hint = hint
|
|
--vl("Showing hint for %s: %s\n\"%s\"",ctrl,st_hint,hint)
|
|
end
|
|
end
|
|
self:ShowHint(self.hint)
|
|
|
|
-- locking
|
|
|
|
self.cust_argb = self.check_argb:GetCheck()
|
|
self.argb_controls:Show(self.cust_argb)
|
|
|
|
self.last_lock = self.locked
|
|
self.locked = self.check_lock:GetCheck()
|
|
if self.locked ~= self.last_lock then
|
|
self.last_lock = self.locked
|
|
self.btn_delete:Enable(not self.locked)
|
|
self.check_text:Enable(not self.locked)
|
|
self.check_hud:Enable(not self.locked)
|
|
self.check_argb:Enable(not self.locked)
|
|
--self.input_a:Enable(self.cust_argb and not self.locked)
|
|
--self.input_r:Enable(self.cust_argb and not self.locked)
|
|
--self.input_g:Enable(self.cust_argb and not self.locked)
|
|
--self.input_b:Enable(self.cust_argb and not self.locked)
|
|
self.input_a:Enable(not self.locked)
|
|
self.input_r:Enable(not self.locked)
|
|
self.input_g:Enable(not self.locked)
|
|
self.input_b:Enable(not self.locked)
|
|
self.input:Enable(not self.locked)
|
|
if GUI_PinInd then
|
|
GUI_PinInd.btn_apply:Enable(not self.locked)
|
|
end
|
|
end
|
|
local text = self.input:GetText()
|
|
|
|
local a,r,g,b = clamp(tonumber(self.input_a:GetText()) or 255,0,255),
|
|
clamp(tonumber(self.input_r:GetText()) or 255,0,255),
|
|
clamp(tonumber(self.input_g:GetText()) or 255,0,255),
|
|
clamp(tonumber(self.input_b:GetText()) or 255,0,255)
|
|
|
|
if not self.colors then
|
|
self.colors = {}
|
|
end
|
|
|
|
for c,v in pairs({["a"]=a,["r"]=r,["g"]=g,["b"]=b}) do
|
|
if self.colors[c] ~= v then
|
|
self.cust_argb = true
|
|
end
|
|
self.colors[c] = v
|
|
end
|
|
--self.hint_wnd:Update()
|
|
self:RefreshIcon()
|
|
end
|
|
|
|
|
|
function UIPinSettingsWnd:OnAccept()
|
|
local id = self.pin_id
|
|
dl("UIPinSettingsWnd:OnAccept - applying changes to Pin %s",id)
|
|
|
|
--local old_tooltip = get_tooltip_for_pin(id)
|
|
--pins[id].tooltip = self["lst_tooltip"] and self["lst_tooltip"]:CurrentID() or pin_tooltip_mode
|
|
--printf("Tooltip mode: %s",pins[id].tooltip)
|
|
local new_text = self.input:GetText()
|
|
local old_text = pins[id].text or pins[id].name
|
|
pins[id].text = new_text
|
|
--local hint_is_new = pins[id].tooltip ~= old_tooltip
|
|
local has_new_text = old_text ~= new_text
|
|
|
|
if has_new_text then --or self.new_icon then --or hint_is_new then
|
|
--local old_icon = pins[id].icon
|
|
--pins[id].icon = self.new_icon or pins[id].icon
|
|
local mapspot_text = get_tooltip_for_pin(id)
|
|
--dl("UIPinSettingsWnd:OnAccept: Pin %s has new icon or hint, calling change_mapspot\n* Icon: %s\n* Hint: %s",self.pin_id,pins[id].icon,mapspot_text)
|
|
--change_mapspot(mapspot_text,id,pins[id].icon,old_icon)
|
|
dl("UIPinSettingsWnd:OnAccept: Pin %s has new icon or hint, calling level.map_change_spot_hint",self.pin_id,pins[id].icon,mapspot_text)
|
|
level.map_change_spot_hint(id,pins[id].icon,mapspot_text)
|
|
end
|
|
|
|
pins[id].custom_colors = self.cust_argb
|
|
if self.cust_argb then
|
|
local a,r,g,b = clamp(tonumber(self.input_a:GetText()) or 255,0,255),
|
|
clamp(tonumber(self.input_r:GetText()) or 255,0,255),
|
|
clamp(tonumber(self.input_g:GetText()) or 255,0,255),
|
|
clamp(tonumber(self.input_b:GetText()) or 255,0,255)
|
|
|
|
if not pins[id].colors then
|
|
pins[id].colors = {}
|
|
end
|
|
pins[id].colors.a = a
|
|
pins[id].colors.r = r
|
|
pins[id].colors.g = g
|
|
pins[id].colors.b = b
|
|
set_mapspot_colors(id,pins[id].icon,a,r,g,b)
|
|
vl("UIPinSettingsWnd:OnAccept: ARGB is %s|%s|%s|%s",a,r,g,b)
|
|
end
|
|
|
|
self.show_label = self.check_text:GetCheck()
|
|
if map_labels[id] and new_name then
|
|
show_pin_label(id,false,true)
|
|
end
|
|
show_pin_label(id,self.show_label)
|
|
|
|
vl("UIPinSettingsWnd:OnAccept: show_label is %s",self.show_label)
|
|
|
|
pins[id].hud = self.check_hud:GetCheck()
|
|
if pins[id].hud then
|
|
show_hud_pin(id)
|
|
else
|
|
hide_hud_pin(id)
|
|
end
|
|
vl("UIPinSettingsWnd:OnAccept: show_hud is %s",pins[id].hud)
|
|
|
|
pins[id].locked = self.check_lock:GetCheck()
|
|
vl("UIPinSettingsWnd:OnAccept: locked is %s",pins[id].locked)
|
|
play_ui_sound(snd_place_pin)
|
|
self:Close()
|
|
end
|
|
|
|
function UIPinSettingsWnd:ShowHint(hint)
|
|
if hint then
|
|
hint = psk(hint,text_colors)
|
|
--vl("* [%s] Showing hint_wnd text: %s",time_global(),hint)
|
|
end
|
|
self.hint_wnd:Update(hint)
|
|
end
|
|
|
|
function UIPinSettingsWnd:OnKeyboard(dik, keyboard_action)
|
|
local res = CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
|
|
if (res == false) then
|
|
local bind = dik_to_bind(dik)
|
|
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
|
|
if dik == DIK_keys.DIK_ESCAPE then
|
|
self:Close()
|
|
end
|
|
end
|
|
end
|
|
return res
|
|
end
|
|
|
|
|
|
function UIPinSettingsWnd:DeletePin()
|
|
do_paw_action("pn_del",nil,nil,{syscall=true,id=self.pin_id})
|
|
self:Close()
|
|
end
|
|
|
|
function UIPinSettingsWnd:Close()
|
|
self:HideDialog()
|
|
self:Show(false)
|
|
Unregister_UI("UIPinSettingsWnd")
|
|
if GUI_PinInd then
|
|
GUI_PinInd:SettingsMode(false)
|
|
end
|
|
reset_indicator()
|
|
destroy_pin_window()
|
|
end
|
|
|
|
-- ======================================================================
|
|
--[[ ICON AND SET HUD INDICATOR
|
|
See the hud_themes table and PAW's MCM menu for more info
|
|
-- ====================================================================]]
|
|
|
|
|
|
GUI_PinInd = nil
|
|
|
|
class "UIPAWIndicator" (CUIScriptWnd)
|
|
|
|
function UIPAWIndicator:__init(settings_mode,anchor) super()
|
|
vl("PAW init called, active theme is %s | widget_active %s | widget_enabled %s | settingsmode %s",active_theme,widget_active,widget_enabled,settingsmode)
|
|
self.anchor = anchor
|
|
if settings_mode then
|
|
self:SettingsMode(true)
|
|
end
|
|
if not widget_enabled then return end
|
|
|
|
self.theme = hud_themes[active_theme]
|
|
self:InitControls()
|
|
self:DrawIndicator(self.theme)
|
|
self:InitCallBacks()
|
|
get_hud():AddDialogToRender(self)
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:__finalize()
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:InitControls()
|
|
self.pda_active = item_device.is_pda_active()
|
|
self.icon_curr = get_active_icon()
|
|
self.set_curr = pawdata.curr_set_name
|
|
|
|
vl("UIPAWIndicator:InitControls: active icon is %s",self.icon_curr)
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:GetAnchorStatic()
|
|
if self.dialog then
|
|
dl("Passing widget handler back to calling func")
|
|
return self.dialog
|
|
else
|
|
dl("ERROR self.dialog was nil!")
|
|
end
|
|
end
|
|
|
|
function UIPAWIndicator:BackupRestoreSettings(restore)
|
|
if not self.backups then
|
|
self.backups = {}
|
|
end
|
|
if restore then
|
|
local pos = self.backups.cust_pos
|
|
dl("UIPinSettingsWnd | restoring old settings:\nwidget_enabled = %s\nwidget_hide_delay = %s | active_theme = %s | cust pos = %s,%s",widget_enable,widget_hide_delay,active_theme,pos.x,pos.y)
|
|
widget_enabled = self.backups.enable
|
|
active_theme = self.backups.active
|
|
widget_hide_delay = self.backups.autohide
|
|
widget_use_custom_pos = self.backups.use_cust_pos
|
|
widget_custom_pos = self.backups.cust_pos
|
|
self.anchor = self
|
|
self.backups = {}
|
|
else
|
|
local pos = widget_custom_pos
|
|
dl("UIPinSettingsWnd | storing current settings:\nwidget_enabled = %s\nwidget_hide_delay = %s | active_theme = %s | cust pos = %s,%s",widget_enable,widget_hide_delay,active_theme,pos.x,pos.y)
|
|
self.backups = {
|
|
enabled = widget_enabled,
|
|
autohide = widget_hide_delay,
|
|
active = active_theme,
|
|
use_cust_pos= widget_use_custom_pos,
|
|
cust_pos = widget_custom_pos,
|
|
}
|
|
end
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:SettingsMode(onoff)
|
|
self.settings_mode = onoff and true or false
|
|
if onoff then
|
|
self:BackupRestoreSettings()
|
|
active_theme = "pin_sidebar"
|
|
widget_hide_delay = 0
|
|
widget_use_custom_pos = true
|
|
widget_enabled = true
|
|
else
|
|
self:BackupRestoreSettings(true)
|
|
end
|
|
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:Reset(theme)
|
|
vl("UIPAWIndicator:Reset called with theme %s",theme and theme.name)
|
|
if not theme then theme = self.theme end
|
|
self.dialog:Show(false)
|
|
self.dialog = nil
|
|
self:InitControls()
|
|
self:DrawIndicator(theme)
|
|
end
|
|
|
|
function UIPAWIndicator:Destroy()
|
|
get_hud():RemoveDialogToRender(self)
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:SetTheme(theme_name)
|
|
vl("UIPAWIndicator:SetTheme called with theme_name %s",theme_name)
|
|
local theme = hud_themes and hud_themes[theme_name]
|
|
if theme then
|
|
self.dialog:Show(false)
|
|
active_theme = theme_name or active_theme
|
|
self.theme = hud_themes[active_theme]
|
|
self:Reset(theme)
|
|
end
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:actor_on_net_destroy()
|
|
get_hud():RemoveDialogToRender(self)
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:IconPrev()
|
|
--printf("UIPAWIndicator:IconPrev fired")
|
|
cycle_icons(-1,false)
|
|
end
|
|
|
|
function UIPAWIndicator:IconNext()
|
|
--printf("UIPAWIndicator:IconNext fired")
|
|
cycle_icons(1,false)
|
|
end
|
|
|
|
function UIPAWIndicator:SetPrev()
|
|
--printf("UIPAWIndicator:SetPrev fired")
|
|
cycle_sets(-1,false)
|
|
end
|
|
|
|
function UIPAWIndicator:SetNext()
|
|
--printf("UIPAWIndicator:SetNext fired")
|
|
cycle_sets(1,false)
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:InitIcosetControls()
|
|
local xml = CScriptXmlInit()
|
|
xml:ParseFile("paw_ui_elements.xml")
|
|
local icoset_c = "icoset_controls"
|
|
local icoset = icoset_c..":"
|
|
local btn_iprev = icoset.."btn_ico_prev"
|
|
local btn_inext = icoset.."btn_ico_next"
|
|
local btn_sprev = icoset.."btn_set_prev"
|
|
local btn_snext = icoset.."btn_set_next"
|
|
local btn_apply = icoset.."btn_apply"
|
|
|
|
self.icoset_controls = xml:InitStatic(icoset_c, self.dialog)
|
|
self.icon_controls = xml:InitStatic(icoset_c, self.icoset_controls)
|
|
self.set_controls = xml:InitStatic(icoset_c, self.icoset_controls)
|
|
|
|
--printf("icon name: %s | set name: %s",local_icon_name(),local_set_name())
|
|
function setup_icoset_ctrl(icoset_arg, pos_x, pos_y)
|
|
local btnx_ = "btn_"
|
|
local stub = string.sub(icoset_arg,1,3)
|
|
local abbr = string.sub(icoset_arg,1,1)
|
|
local mwi = "mwi_"
|
|
local button_prev = btnx_..abbr.."prev"
|
|
local button_next = btnx_..abbr.."next"
|
|
local node_prev = icoset..btnx_..stub.."_prev"
|
|
local node_next = icoset..btnx_..stub.."_next"
|
|
local icoset_ctrl = icoset_arg.."_controls"
|
|
local logo = "logo_"..icoset_arg
|
|
--local text_cap = (abbr == "s") and
|
|
-- local_set_name() or local_icon_name()
|
|
|
|
--printf("setup_icoset_ctrl(%s,%s,%s) for %s\nstub = %s\nabbr = %s\nbutton_prev = %s\nbutton_next = %s\nnode_prev = %s\nnode_next = %s\nicoset_ctrl = %s\n",icoset_arg, pos_x, pos_y,text_cap,stub,abbr,button_prev,button_next,node_prev,node_next,icoset_ctrl)
|
|
|
|
self[button_prev] = xml:Init3tButton(node_prev, self[icoset_ctrl])
|
|
self:Register(self[button_prev],button_prev)
|
|
|
|
self[logo] = xml:InitStatic(icoset..logo, self[icoset_ctrl])
|
|
unsquish_aspect(self[logo])
|
|
|
|
self[button_next] = xml:Init3tButton(node_next, self[icoset_ctrl])
|
|
self:Register(self[button_next],button_next)
|
|
|
|
self[mwi..icoset_arg] = xml:InitStatic("mwheel_ind",self.dialog)
|
|
--self.cap[icoset_arg] = xml:InitStatic(caption,self[button_prev])
|
|
--self.cap[icoset_arg]:TextControl():SetText(text_cap)
|
|
self[icoset_ctrl]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
end
|
|
|
|
function setup_button(button,pos_x,pos_y,xmlnode)
|
|
local buttonx = "btn_"..button
|
|
vl("Initializing button %s (%s) at %s,%s",buttonx,button,pos_x,pos_y)
|
|
self[buttonx] = xml:Init3tButton(xmlnode, self.icoset_controls)
|
|
self:Register(self[buttonx],buttonx)
|
|
self[buttonx]:SetWndPos(vector2():set(pos_x,pos_y))
|
|
end
|
|
|
|
setup_icoset_ctrl( "icon", 92, 34 )
|
|
setup_icoset_ctrl( "set", 109.5, 118 )
|
|
setup_button( "apply", 82.5, 64, btn_apply )
|
|
setwndpos( self.mwi_icon, 145, 8 )
|
|
setwndpos( self.mwi_set, 104, 131 )
|
|
|
|
--================================================================--
|
|
|
|
self.icoset_controls:Show(self.settings_mode)
|
|
end
|
|
|
|
function UIPAWIndicator:ApplyIconToPin()
|
|
GUI_PinOpts:ApplyIconToPin()
|
|
end
|
|
|
|
function UIPAWIndicator:InitCallBacks()
|
|
vl("UIPAWIndicator registering callbacks")
|
|
RegisterScriptCallback("actor_on_net_destroy", self)
|
|
self:AddCallback("btn_apply", ui_events.BUTTON_CLICKED, self.ApplyIconToPin, self)
|
|
self:AddCallback("btn_iprev", ui_events.BUTTON_CLICKED, self.IconPrev, self)
|
|
self:AddCallback("btn_inext", ui_events.BUTTON_CLICKED, self.IconNext, self)
|
|
self:AddCallback("btn_sprev", ui_events.BUTTON_CLICKED, self.SetPrev, self)
|
|
self:AddCallback("btn_snext", ui_events.BUTTON_CLICKED, self.SetNext, self)
|
|
end
|
|
|
|
function UIPAWIndicator:DrawIndicator(theme)
|
|
vl("UIPAWIndicator:DrawIndicator called with theme %s | self %s",theme and theme.name,self.theme)
|
|
local pos = theme.pos
|
|
if widget_use_custom_pos then pos = widget_custom_pos end
|
|
local xml = CScriptXmlInit()
|
|
xml:ParseFile(theme.file)
|
|
|
|
--self.dialog = xml:InitStatic(theme.node, self.anchor or self)
|
|
local anchor = self.anchor or self--GUI_PinOpts and GUI_PinOpts.dialog
|
|
self.dialog = xml:InitStatic(theme.node, anchor)
|
|
self.dialog:SetWndPos(vector2():set(pos.x,pos.y))
|
|
if theme.tex then
|
|
self.dialog:InitTexture(theme.tex)
|
|
end
|
|
self.box_curr = xml:InitStatic(theme.node..":curr", self.dialog)
|
|
self.box_curr:InitTexture(texture_for_icon(self.icon_curr))
|
|
|
|
if theme.style ~= "compact" then
|
|
self.box_prev = xml:InitStatic(theme.node..":prev", self.dialog)
|
|
self.box_prev:InitTexture(texture_for_icon(get_prev_icon()))
|
|
|
|
self.box_next = xml:InitStatic(theme.node..":next", self.dialog)
|
|
self.box_next:InitTexture(texture_for_icon(get_next_icon()))
|
|
|
|
self.box_head = xml:InitStatic(theme.node..":head",self.dialog)
|
|
self.box_text = xml:InitTextWnd(theme.node..":head",self.box_head)
|
|
self.box_prev:SetTextureColor(colors.dimmed)
|
|
self.box_next:SetTextureColor(colors.dimmed)
|
|
end
|
|
if theme.style == "full" then
|
|
self.box_text:SetText(ts("ui_mcm_lst_pawsys_pg_"..self.set_curr))
|
|
self.box_head2 = xml:InitStatic(theme.node..":head2",self.dialog)
|
|
self.box_text2 = xml:InitTextWnd(theme.node..":head2",self.box_head2)
|
|
self.box_text2:SetText(ts("ui_mcm_lst_"..self.icon_curr))
|
|
if self.settings_mode then
|
|
self.box_text:SetWndPos(vector2():set(0,0))
|
|
self.box_text:SetTextAlignment(1)
|
|
self.box_text2:SetWndPos(vector2():set(0,0))
|
|
self.box_text2:SetTextAlignment(1)
|
|
self:InitIcosetControls()
|
|
end
|
|
|
|
elseif theme.style == "minimal" then
|
|
self.box_text:SetText(ts("ui_mcm_lst_"..self.icon_curr))
|
|
end
|
|
|
|
vl("UIPAWIndicator:DrawIndicator completed")
|
|
end
|
|
|
|
|
|
function UIPAWIndicator:Update(force)
|
|
if self.killswitch then return end
|
|
|
|
CUIScriptWnd.Update(self)
|
|
self.dialog:Show(false)
|
|
|
|
if not ((widget_enabled and main_hud_shown()) or pin_window_is_open()) then return end
|
|
|
|
local theme = self.theme
|
|
local pda_changed = false
|
|
|
|
if not pin_window_is_open() then
|
|
if self.pda_active ~= item_device.is_pda_active() then
|
|
pda_changed = true
|
|
end
|
|
if item_device.is_pda_active() then
|
|
local thm = theme.pda_thm
|
|
if thm then
|
|
|
|
theme = hud_themes[thm]
|
|
end
|
|
end
|
|
if pda_changed then
|
|
vl("PDA mode has changed, resetting theme")
|
|
self:Reset(theme)
|
|
end
|
|
else
|
|
widget_active = psw_sidebar_state
|
|
end
|
|
|
|
if theme.tex then self.dialog:InitTexture(theme.tex) end
|
|
local pos = theme.pos
|
|
if widget_use_custom_pos then
|
|
pos = widget_custom_pos
|
|
end
|
|
|
|
self.dialog:SetWndPos(vector2():set(pos.x,pos.y))
|
|
|
|
local acticon = pawdata.curr_ico_name
|
|
if (self.icon_curr ~= acticon) or (self.set_curr ~= pawdata.curr_set_name) then
|
|
vl("UIPAWIndicator:Update - icon/set has changed (new curr icon: %s)",acticon)
|
|
self.set_curr = pawdata.curr_set_name
|
|
self.icon_curr = acticon
|
|
self.box_curr:InitTexture(texture_for_icon(self.icon_curr))
|
|
if theme.style ~= "compact" then
|
|
self.box_prev:InitTexture(texture_for_icon(get_prev_icon()))
|
|
self.box_next:InitTexture(texture_for_icon(get_next_icon()))
|
|
end
|
|
if theme.style == "full" then
|
|
self.box_text:SetText(ts("ui_mcm_lst_pawsys_pg_"..self.set_curr))
|
|
self.box_text2:SetText(ts("ui_mcm_lst_"..self.icon_curr))
|
|
elseif theme.style == "minimal" then
|
|
self.box_text:SetText(ts("ui_mcm_lst_"..self.icon_curr))
|
|
end
|
|
widget_last_used = time_global()
|
|
widget_active = true
|
|
end
|
|
if widget_hide_delay > 0 then
|
|
if time_global() > widget_last_used + widget_hide_delay then widget_active = false end
|
|
end
|
|
self.dialog:Show(widget_active)
|
|
if widget_active and self.settings_mode then
|
|
self.mwi_set:Show(false)
|
|
self.mwi_icon:Show(false)
|
|
for ctrl,icoset in pairs(hover_elements) do
|
|
--printf("Checking hover state for %s element %s",icoset,ctrl)
|
|
if self[ctrl]:IsCursorOverWindow() then
|
|
self["mwi_"..icoset]:Show(true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function reset_indicator(force,anchor)
|
|
vl("Resetting PAW indicator")
|
|
if GUI_PinInd then GUI_PinInd:Destroy() end
|
|
if not (force or widget_enabled) then return end
|
|
vl("Re-initializing PAW indicator")
|
|
GUI_PinInd = UIPAWIndicator(force,anchor)
|
|
end
|
|
|
|
|
|
function show_indicator(tf)
|
|
if not (GUI_PinInd and widget_enabled) then return end
|
|
if tf == nil then
|
|
widget_active = not widget_active
|
|
else
|
|
widget_active = (tf == true) or false
|
|
end
|
|
GUI_PinInd:Show(widget_active)
|
|
end
|
|
|
|
|
|
-- ======================================================================
|
|
--[[ WAYPOINT AND PIN HUD ICONS
|
|
Some pieces adapted from GT's "HUD Ubisoft Friendly" addon
|
|
-- ====================================================================]]
|
|
|
|
function unsquish_aspect(element)
|
|
local w = element:GetWidth()
|
|
local h = element:GetHeight()
|
|
element:SetWndSize(vector2():set((w*unsquish_ratio),h))
|
|
end
|
|
|
|
function dist_from_crosshair(position)
|
|
local toPoint = vector():set(position):sub(device().cam_pos):normalize()
|
|
return toPoint:dotproduct(device().cam_dir)
|
|
end
|
|
|
|
--[[
|
|
animate_texture(
|
|
container,
|
|
500,
|
|
{512.5,384.5},
|
|
{512.5,384.5},
|
|
{0,0},
|
|
{200, 200},
|
|
1,
|
|
0,
|
|
function() printf("anim_finished") end,
|
|
function(x) return x^2 end
|
|
)
|
|
--]]
|
|
|
|
function easing_outquint(x)
|
|
if not x then return end
|
|
return 1 - math.pow(1 - x, 5)
|
|
end
|
|
|
|
function easing_inquint(x)
|
|
if not x then return end
|
|
return x * x * x * x * x
|
|
end
|
|
|
|
function abort_fade_in()
|
|
return HUD_RET.fading_out or not HUD_RET.fading_in
|
|
end
|
|
|
|
function abort_fade_out()
|
|
return HUD_RET.fading_in or not HUD_RET.fading_out
|
|
end
|
|
|
|
|
|
function animate_texture(element, duration, start_pos, end_pos, start_size, end_size, alpha_start, alpha_end , on_finish_func, anim_curve_modifier_func, r, g, b)
|
|
r = r or 255
|
|
g = g or 255
|
|
b = b or 255
|
|
|
|
local anim_state = 0
|
|
local start_time = time_global()
|
|
local end_time = time_global() + duration
|
|
local anim_curve_modifier_func = anim_curve_modifier_func or function(x) return x end
|
|
CreateTimeEvent("animate_texture", time_global(), 0, function()
|
|
local x = anim_curve_modifier_func(anim_state)
|
|
local pos_x = lerp(start_pos.x, end_pos.x, x)
|
|
local pos_y = lerp(start_pos.y, end_pos.y, x)
|
|
|
|
local size_x = lerp(start_size.x, end_size.x, x)
|
|
local size_y = lerp(start_size.y, end_size.y, x)
|
|
|
|
local alpha = lerp(alpha_start, alpha_end, x)
|
|
|
|
|
|
if anim_state == 1 then
|
|
if on_finish_func then on_finish_func() end
|
|
return true
|
|
end
|
|
anim_state = math.min(1, normalize(time_global(), start_time, end_time))
|
|
end)
|
|
end
|
|
|
|
local active_anims = {}
|
|
|
|
function anim_fade(box,alpha_start,alpha_end,duration,event_id,instanced, r, g, b, anim_curve_modifier_func, on_finish_func,abort_func)
|
|
if not box then return end
|
|
local fade_dir = (alpha_start > alpha_end) and "out" or "in"
|
|
dl("anim_fade: start %s end %s dur %s | event_id %s | instanced %s ",alpha_start,alpha_end, duration,event_id,instanced)
|
|
if (event_id == nil) then event_id = "anim_fade" end
|
|
local anim_id = event_id.."_"..tostring(time_global())
|
|
r = r or 255
|
|
g = g or 255
|
|
b = b or 255
|
|
|
|
if active_anims[event_id] then
|
|
alpha_start = active_anims[event_id].a
|
|
dl("Repeat invocation of non-instanced fade event, aborting fade-%s and starting new at current alpha (%s)",fade_dir,alpha_start)
|
|
active_anims[event_id] = nil
|
|
if on_finish_func then on_finish_func(box,event_id,alpha_end,r,g,b) end
|
|
--anim_fade(box,alpha_start,alpha_end,duration,event_id,instanced, r, g, b, anim_curve_modifier_func, on_finish_func,abort_func)
|
|
--return true
|
|
end
|
|
|
|
local anim_state = 0
|
|
local start_time= time_global()
|
|
local end_time = time_global() + duration
|
|
local anim_curve_modifier_func = anim_curve_modifier_func or function(x) return x end
|
|
active_anims[event_id] = {
|
|
|
|
box = box,
|
|
instanced = instanced and true or false,
|
|
anim_id = anim_id,
|
|
start_time = start_time,
|
|
end_time = end_time,
|
|
active = true,
|
|
a_start = alpha_start,
|
|
a_end = alpha_end,
|
|
a = alpha_start,
|
|
r = r,
|
|
g = g,
|
|
b = b,
|
|
}
|
|
|
|
--vl("Creating fade-%s time event %s | %s",fade_dir,event_id,anim_id)
|
|
CreateTimeEvent("animate_fade"..event_id..anim_id, time_global(), 0, function()
|
|
local abort = abort_func and abort_func()
|
|
if abort then
|
|
vl("Received abort for %s",event_id)
|
|
anim_state = 1
|
|
else
|
|
local anim = active_anims[event_id]
|
|
if anim then
|
|
local x = anim_curve_modifier_func(anim_state)
|
|
local alpha = lerp(alpha_start, alpha_end, x)
|
|
anim.a,anim.r,anim.g,anim.b = alpha,r,g,b
|
|
box:SetTextureColor(GetARGB(alpha,r,g,b))
|
|
--vl("Fade-%s time event: setting transparency for %s to %s at time %s",fade_dir,event_id,alpha,time_global())
|
|
else
|
|
vl("Event data for %s has cleared, aborting",event_id)
|
|
anim_state = 1
|
|
end
|
|
end
|
|
|
|
if (anim_state == 1) then
|
|
vl("Fade-%s animation %s completed at %s",fade_dir,event_id,time_global())
|
|
if on_finish_func then on_finish_func(box,event_id,alpha_end,r,g,b) end
|
|
return true
|
|
end
|
|
anim_state = math.min(1, normalize(time_global(), start_time, end_time))
|
|
end)
|
|
end
|
|
|
|
function fade_by_dist(element,dist,min,mid,max,alpha,r,g,b,mode)
|
|
-- 0 : fade Static element
|
|
-- 1 : fade text in Static
|
|
-- 2 : fade text in TextWnd
|
|
|
|
alpha = alpha or 255
|
|
r = r or 255
|
|
g = g or 255
|
|
b = b or 255
|
|
if not (cart_mode and cartmode_unfade) then
|
|
if (dist <= min) then
|
|
if dist < min then
|
|
alpha = alpha * (dist / min)
|
|
end
|
|
elseif dist > mid then
|
|
if (mid > 0) then
|
|
if (dist > (mid + max)) then
|
|
alpha = 0
|
|
elseif dist > mid then
|
|
alpha = alpha * (1 - ((dist - mid) / max))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if mode == 1 then
|
|
element:TextControl():SetTextColor(GetARGB(alpha,r,g,b))
|
|
elseif mode == 2 then
|
|
element:SetTextColor(GetARGB(alpha,r,g,b))
|
|
else
|
|
element:SetTextureColor(GetARGB(alpha,r,g,b))
|
|
end
|
|
end
|
|
|
|
|
|
function scale_by_dist(element,dist,w,h,min,mid,max,unsquish)
|
|
--printf("scale_by_dist for %sx%s element at dist %s | unsquish %s | %s - %s - %s ",w,h,dist,unsquish,min,mid,max)
|
|
dist = clamp(dist,0,max)
|
|
local nw = w
|
|
local nh = h
|
|
if (dist <= min) then
|
|
nw = w + ((1 - (dist / min)) * (w * 0.5))
|
|
nh = h + ((1 - (dist / min)) * (h * 0.5))
|
|
elseif dist > mid then
|
|
nw = w - (((dist - mid) / (max - mid)) * (w * 0.4)) -- trying 0.4 rather than 0.3 to bring down min size
|
|
nh = h - (((dist - mid) / (max - mid)) * (h * 0.4))
|
|
end
|
|
|
|
if unsquish then
|
|
nw = nw * unsquish_ratio
|
|
end
|
|
--printf("scale_by_dist for %sx%s element:\nw %s -> nw %s | h %s -> nh %s | ratio: %s",element:GetWidth(),element:GetHeight(),w,nw,h,nh,unsquish_ratio)
|
|
|
|
return nw,nh
|
|
end
|
|
|
|
|
|
local function zoom_delay_over() zoom_delay = false end
|
|
local zoom_delay = false
|
|
local last_zoom_coef = 1
|
|
local last_zoom_state = false
|
|
|
|
function get_current_zoom_coef()
|
|
if zoom_delay then return last_zoom_coef end
|
|
|
|
local obj = db.actor:active_item()
|
|
if (obj and IsWeapon(obj)) then
|
|
local wpn = obj:cast_Weapon()
|
|
end
|
|
|
|
local is_zoomed = axr_main.binoc_is_zoomed or (wpn and wpn:IsZoomed())
|
|
if is_zoomed ~= last_zoom_state then
|
|
last_zoom_state = is_zoomed
|
|
zoom_delay = true
|
|
CreateTimeEvent("zoomdelay","paw_zoom"..tostring(time_global()),0.25,tasks_placeable_waypoints.zoom_delay_over)
|
|
return last_zoom_coef
|
|
end
|
|
|
|
local fov = device().fov
|
|
local zoom_coef = fov / 85
|
|
last_zoom_coef = zoom_coef
|
|
|
|
return zoom_coef
|
|
end
|
|
|
|
|
|
function get_screen_coords(id)
|
|
local pos = nil
|
|
local is_npc,is_place
|
|
local obj = db.storage[id] and db.storage[id].object or level.object_by_id(id)
|
|
local se_obj = alife_object(id)
|
|
--printf("<PAW> get_screen_coords: id %s -> obj %s (%s) | se_obj %s",id,obj and obj:name(),obj and obj:id(),se_obj and se_obj:name())
|
|
if not (obj or se_obj) then
|
|
local is_wp = (id == (placed_waypoint and placed_waypoint.id)) and (not waypoint_canceling) and end_waypoint_task(id)
|
|
local pin = pins[id] and do_paw_action("pn_del",se_obj,nil,{syscall=true,id=id})
|
|
local exit = (is_wp and " canceling waypoint and") or (pin and " clearing pin and") or ""
|
|
dl("get_screen_coords: no valid game or server object could be found for %s,%s exiting",id,exit)
|
|
return
|
|
end
|
|
|
|
if (obj and IsStalker(obj) or IsMonster(obj)) then
|
|
pos = obj and utils_obj.safe_bone_pos(obj,"bip01_head")
|
|
is_npc = true
|
|
--printf("<PAW> Pinned object %s is an npc",id)
|
|
elseif (se_obj:clsid() == clsid.smart_terrain) or (se_obj:clsid() == clsid.script_zone) then
|
|
pos = se_obj.position
|
|
is_place = true
|
|
--printf("<PAW> Pinned object %s is a place",id)
|
|
elseif (obj and (type(obj.position) == "function")) then
|
|
local tmp = obj:position()
|
|
pos = tmp and vector():set(tmp.x,tmp.y,tmp.z)
|
|
end
|
|
|
|
if (pos == nil) then
|
|
if not (se_obj and se_obj.online) then
|
|
return nil
|
|
elseif (se_obj:clsid() == clsid.online_offline_group_s) then
|
|
local i = se_obj:commander_id()
|
|
local npc = i and db.storage[i] and db.storage[i].object or level.object_by_id(i)
|
|
pos = npc and utils_obj.safe_bone_pos(npc,"bip01_head")
|
|
is_npc = true
|
|
--printf("<PAW> Pinned object %s is an npc squad",id)
|
|
else
|
|
local tmp = se_obj and se_obj.position
|
|
pos = tmp and vector():set(tmp.x,tmp.y,tmp.z)
|
|
end
|
|
end
|
|
if not ((pos and pos.x) and (pos and pos.x) and (pos and pos.z)) then
|
|
dl("WARNING: unable to get valid pos for %s",id)
|
|
return nil
|
|
end
|
|
|
|
--printf("<PAW> pos found for id %s: %s,%s,%s",id,pos and pos.x,pos and pos.y,pos and pos.z)
|
|
|
|
local dist = db.actor:position():distance_to(pos)
|
|
local true_dist = dist -- store this
|
|
local min_dist = 0 -- distance floor for proximity adjustment range
|
|
local near_dist = 15 -- max dist where proximity adjustment range begins
|
|
local mid_dist = 15 -- dist at which far adjustments begin
|
|
local max_dist = 60 -- distance ceiling for the far adjustment range
|
|
local near_adj = 0 -- max icon vertical position change from proximity
|
|
local far_adj = 1.75 -- max icon vertical position change from distance
|
|
local vert_adj = 0 -- icon position above object will be adjusted by this
|
|
|
|
if is_place then
|
|
near_adj = 1.2 -- location spots are usually on or in the ground
|
|
elseif is_npc then
|
|
min_dist = 2 -- to allow for npc bounding box
|
|
near_adj = 0.45 -- max increase in height above npc head from proximity < 12m
|
|
end
|
|
local vert_adj = near_adj
|
|
local dist_prog = 0 -- 0 to 1 progress from beginning to end of adjustment range
|
|
local dist_coef = 1 -- 0 to 1 multiplier based on distance
|
|
dist = clamp(dist,min_dist,max_dist)
|
|
|
|
if (dist <= near_dist) then
|
|
dist_prog = ((near_dist - min_dist) - (dist - min_dist)) * 0.1
|
|
dist_coef = math.abs(math.sqrt(math.pow(dist_prog, 2)))
|
|
vert_adj = near_adj - (near_adj * dist_coef)
|
|
elseif (dist > mid_dist) then
|
|
local far_range = max_dist - mid_dist
|
|
local far_dist = dist - mid_dist
|
|
if dist >= max_dist then
|
|
dist_prog = 1
|
|
else
|
|
dist_prog = (far_dist / far_range)
|
|
end
|
|
dist_coef = dist_prog -- linear
|
|
--dist_coef = math.cos(((1 - dist_prog) * math.pi) / 2) -- eastInSine - this one works ok
|
|
--dist_coef = math.sin((dist_prog * math.pi) / 2) -- easeOutSine
|
|
--dist_coef = math.abs(math.sqrt(math.pow(dist_prog, 2)))
|
|
vert_adj = near_adj + (dist_coef * far_adj)
|
|
end
|
|
--local zoom_coef = get_current_fov_coef() or 1
|
|
local zoom_coef = (device().fov / 85)
|
|
|
|
pos.y = pos.y + 0.575 + (vert_adj * zoom_coef)
|
|
--printf("* Actor is %s from %s (near_dist %s | max_dist %s\n* dist_prog %s | dist_coef %s\n| Final vertical adjustment: %s",true_dist,id,near_dist,max_dist,dist_prog,dist_coef,vert_adj)
|
|
|
|
local vec = pos and game.world2ui(vector():set(pos.x,pos.y,pos.z),false)
|
|
--printf("final vec for %s: %s,%s",id,vec and vec.x,vec and vec.y)
|
|
if (vec and (vec.x ~= -9999) and (vec.y ~= 0)) then
|
|
return vec
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
-- ======================================================================
|
|
|
|
HUD_MT = nil
|
|
|
|
function show_hud_waypoint()
|
|
if not db.actor then return end
|
|
if (HUD_MT == nil) then
|
|
HUD_MT = UIPAWHUDWaypoint()
|
|
get_hud():AddDialogToRender(HUD_MT)
|
|
end
|
|
end
|
|
|
|
function hide_hud_waypoint()
|
|
if not db.actor then return end
|
|
if (HUD_MT ~= nil) then
|
|
HUD_MT:ShowDialog(false)
|
|
get_hud():RemoveDialogToRender(HUD_MT)
|
|
HUD_MT = nil
|
|
end
|
|
end
|
|
|
|
function update_hud_waypoint()
|
|
if not db.actor then return end
|
|
if (HUD_MT ~= nil) then
|
|
HUD_MT:Update(true)
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
|
|
class "UIPAWHUDWaypoint" (CUIScriptWnd)
|
|
|
|
function UIPAWHUDWaypoint:__init() super()
|
|
self:InitControls()
|
|
RegisterScriptCallback("actor_on_net_destroy", self)
|
|
end
|
|
|
|
|
|
function UIPAWHUDWaypoint:__finalize()
|
|
end
|
|
|
|
|
|
function UIPAWHUDWaypoint:InitControls()
|
|
self:SetAutoDelete(true)
|
|
self.xml = CScriptXmlInit()
|
|
self.xml:ParseFile("paw_hud_wp_icon.xml")
|
|
self.marker = self.xml:InitStatic("marker",self)
|
|
self.dist = self.xml:InitStatic("marker:distance_sh:distance",self)
|
|
self.dist:TextControl():SetTextColor( GetARGB(255,230,230,230) )
|
|
self.dist:TextControl():SetFont(GetFontSmall())
|
|
self.dist_sh = self.xml:InitStatic("marker:distance_sh",self.dist)
|
|
self.dist_sh:TextControl():SetTextColor( GetARGB(255,0,0,0) )
|
|
self.dist_sh:TextControl():SetFont(GetFontSmall())
|
|
self.dist_sh:SetWndPos(vector2():set(1,1))
|
|
self.wref = self.xml:InitStatic("marker:distance_sh:distance",self.dist)
|
|
self.wref:TextControl():SetFont(GetFontSmall())
|
|
self.wref:Show(false)
|
|
end
|
|
|
|
|
|
function UIPAWHUDWaypoint:Destroy()
|
|
get_hud():RemoveDialogToRender(self)
|
|
end
|
|
|
|
|
|
function UIPAWHUDWaypoint:actor_on_net_destroy()
|
|
get_hud():RemoveDialogToRender(self)
|
|
end
|
|
|
|
|
|
|
|
function UIPAWHUDWaypoint:ShowMarker(onoff)
|
|
self.dist:Show(onoff and marker_dist_shown("wp"))
|
|
self.dist_sh:Show(onoff and marker_dist_shown("wp"))
|
|
self.marker:Show(onoff)
|
|
end
|
|
|
|
function UIPAWHUDWaypoint:Update()
|
|
CUIScriptWnd.Update(self)
|
|
if waypoint_active and (main_hud_shown() or axr_main.binoc_is_zoomed or axr_main.scoped_weapon_is_zoomed) and not waypoint_canceling then
|
|
local vec = placed_waypoint and placed_waypoint.id and get_screen_coords(placed_waypoint.id)
|
|
if (vec) then
|
|
self.marker:SetWndPos(vec)
|
|
local id = placed_waypoint and placed_waypoint.id
|
|
local se_obj = id and alife_object(id)
|
|
if se_obj then
|
|
local dist = db.actor:position():distance_to(se_obj.position)
|
|
local h,v = scale_by_dist(self.marker,dist,20,20,50,100,200,true)
|
|
self.marker:SetWndSize(vector2():set(h,v))
|
|
|
|
local f_near = wp_near_fade_dist
|
|
local f_far = wp_far_fade_dist
|
|
local f_hide = wp_far_hide_dist
|
|
fade_by_dist(self.marker, dist,f_near,f_far,f_hide)
|
|
fade_by_dist(self.dist, dist,f_near,f_far,f_hide,255,230,230,230,1)
|
|
fade_by_dist(self.dist_sh, dist,f_near,f_far,f_hide,255,0,0,0,1)
|
|
|
|
if marker_dist_shown("wp") then
|
|
local pos = self.marker:GetWndPos()
|
|
--local dist_txt = string.format("%.1f",dist)..ts("st_paw_meters_abbr")
|
|
local dist_txt = string.format("%.1f",dist).."m"
|
|
self.dist:Show(false)
|
|
self.dist_sh:Show(false)
|
|
self.dist:TextControl():SetText(dist_txt)
|
|
self.dist_sh:TextControl():SetText(dist_txt)
|
|
self.wref:TextControl():SetText(dist_txt)
|
|
self.wref:AdjustWidthToText()
|
|
local tw = self.wref:GetWidth()
|
|
self.dist:SetWndPos(vector2():set(pos.x - (tw / 2) - 1, pos.y + v - 8))
|
|
end
|
|
self:ShowMarker(se_obj.online and true)
|
|
end
|
|
return
|
|
end
|
|
self:ShowMarker(false)
|
|
else
|
|
self:ShowMarker(false)
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
|
|
hud_pin_objs = {}
|
|
|
|
function update_hud_pins()
|
|
for k,v in pairs(hud_pin_objs) do
|
|
v:Update(true)
|
|
end
|
|
end
|
|
|
|
function hide_hud_pin(id)
|
|
if not id then return end
|
|
if hud_pin_objs[id] then
|
|
get_hud():RemoveDialogToRender(hud_pin_objs[id])
|
|
hud_pin_objs[id] = nil
|
|
end
|
|
return true
|
|
end
|
|
|
|
function show_hud_pin(id)
|
|
vl("show_hud_pin called for pin ID %s",id)
|
|
if hud_pin_objs[id] then
|
|
hide_hud_pin(id)
|
|
end
|
|
hud_pin_objs[id] = UIPAWHUDPin(id)
|
|
get_hud():AddDialogToRender(hud_pin_objs[id])
|
|
return true
|
|
end
|
|
|
|
function init_hud_pins()
|
|
for k,v in pairs(pins) do
|
|
local id = v and v.id
|
|
if id and v.hud then
|
|
local se_obj = alife_object(id)
|
|
if se_obj and se_obj.online then
|
|
show_hud_pin(id)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
|
|
class "UIPAWHUDPin" (CUIScriptWnd)
|
|
|
|
function UIPAWHUDPin:__init(id) super()
|
|
self.pin_id = id
|
|
self.pin_se_obj = alife_object(id)
|
|
self:InitControls(id)
|
|
RegisterScriptCallback("actor_on_net_destroy", self)
|
|
RegisterScriptCallback("on_localization_change", self)
|
|
self.med_hint_font = (language == "rus")
|
|
end
|
|
|
|
|
|
function UIPAWHUDPin:__finalize()
|
|
end
|
|
|
|
|
|
function UIPAWHUDPin:InitControls(id)
|
|
self:SetAutoDelete(true)
|
|
self.xml = CScriptXmlInit()
|
|
self.xml:ParseFile("paw_hud_pin_icon.xml")
|
|
self.marker = self.xml:InitStatic("marker",self)
|
|
local tex = texture_for_icon(pins[id].icon)
|
|
--local name = pins[id].text or pins[id].name
|
|
local name = pins[id].name
|
|
self.marker:InitTexture(tex)
|
|
local color = colors.active
|
|
if pins[id].custom_colors then
|
|
self.custom_argb = pins[id].colors
|
|
local pcc = self.custom_argb
|
|
vl("Pin %s has custom ARGB %s,%s,%s,%s",id,pcc.a,pcc.r,pcc.g,pcc.b)
|
|
color = GetARGB(pcc.a,pcc.r,pcc.g,pcc.b)
|
|
end
|
|
self.marker:SetTextureColor(color) -- this may require logic adjustment for transparency interacting with fades
|
|
self.label = self.xml:InitStatic("marker:label",self)
|
|
self.label:TextControl():SetTextColor( GetARGB(255,230,230,230) )
|
|
|
|
self.label_sh = self.xml:InitStatic("marker:label_sh",self.label)
|
|
self.label_sh:TextControl():SetTextColor( GetARGB(255,0,0,0) )
|
|
self.label_sh:SetWndPos(vector2():set(1,1))
|
|
self.lref = self.xml:InitStatic("marker:label",self.label)
|
|
self.label:TextControl():SetText(name)
|
|
self.label_sh:TextControl():SetText(name)
|
|
self.lref:TextControl():SetFont(GetFontSmall())
|
|
self.lref:Show(false)
|
|
self:on_localization_change()
|
|
vl("Adding label %s to pin %s",name,self.pin_id)
|
|
|
|
self.dist = self.xml:InitStatic("marker:distance",self)
|
|
self.dist:TextControl():SetTextColor( GetARGB(255,230,230,230) )
|
|
self.dist:TextControl():SetFont(GetFontSmall())
|
|
self.dist_sh = self.xml:InitStatic("marker:distance_sh",self.dist)
|
|
self.dist_sh:TextControl():SetTextColor( GetARGB(255,0,0,0) )
|
|
self.dist_sh:TextControl():SetFont(GetFontSmall())
|
|
self.dist_sh:SetWndPos(vector2():set(1,1))
|
|
self.wref = self.xml:InitStatic("marker:distance",self.dist)
|
|
self.wref:TextControl():SetFont(GetFontSmall())
|
|
self.wref:Show(false)
|
|
self.last_dist = nil
|
|
|
|
--local np,dp = self.label:GetWndPos(),self.dist:GetWndPos()
|
|
--local nx,ny,dx,dy = np.x,np.y,dp.x,dp.y
|
|
--printf("Init: name pos %s,%s | dist pos %s,%s",nx,ny,dx,dy)
|
|
end
|
|
|
|
|
|
function UIPAWHUDPin:Destroy()
|
|
hide_hud_pin(self.pin_id)
|
|
get_hud():RemoveDialogToRender(self)
|
|
end
|
|
|
|
function UIPAWHUDPin:on_localization_change()
|
|
self.med_hint_font = (language == "rus")
|
|
if self.med_hint_font then
|
|
self.label:TextControl():SetFont(GetFontMedium())
|
|
self.label_sh:TextControl():SetFont(GetFontMedium())
|
|
self.lref:TextControl():SetFont(GetFontMedium())
|
|
else
|
|
self.label:TextControl():SetFont(GetFontSmall())
|
|
self.label_sh:TextControl():SetFont(GetFontSmall())
|
|
self.lref:TextControl():SetFont(GetFontSmall())
|
|
end
|
|
end
|
|
|
|
function UIPAWHUDPin:actor_on_net_destroy()
|
|
get_hud():RemoveDialogToRender(self)
|
|
end
|
|
|
|
function UIPAWHUDPin:ShowMarker(onoff)
|
|
self.dist:Show(onoff and marker_dist_shown("pins"))
|
|
self.dist_sh:Show(onoff and marker_dist_shown("pins"))
|
|
self.label:Show(onoff and marker_hint_shown("pins"))
|
|
self.label_sh:Show(onoff and marker_hint_shown("pins"))
|
|
self.marker:Show(onoff)
|
|
end
|
|
|
|
function UIPAWHUDPin:Update()
|
|
--printf("UIPAWHUDPin:Update")
|
|
if not (pins and pins[self.pin_id]) then
|
|
self:Destroy()
|
|
end
|
|
if item_device.is_pda_active() or not (self.pin_se_obj and self.pin_se_obj.online) then
|
|
self.marker:Show(false)
|
|
return
|
|
end
|
|
CUIScriptWnd.Update(self)
|
|
if (main_hud_shown() or axr_main.binoc_is_zoomed or axr_main.scoped_weapon_is_zoomed) then
|
|
local vec = self.pin_id and get_screen_coords(self.pin_id)
|
|
|
|
if (vec) then
|
|
local pindist = db.actor:position():distance_to(self.pin_se_obj.position)
|
|
local szx,szy = scale_by_dist(self.marker,pindist,24,24,10,20,50,true)
|
|
|
|
self.marker:SetWndPos(vec)
|
|
self.marker:SetWndSize(vector2():set(szx,szy))
|
|
|
|
local f_near = pin_near_fade_dist
|
|
local f_far = pin_far_fade_dist
|
|
local f_hide = pin_far_hide_dist
|
|
local colors = self.custom_argb or {a=255,r=255,g=255,b=255}
|
|
fade_by_dist(self.marker, pindist,f_near,f_far,f_hide,colors.a,colors.r,colors.g,colors.b)
|
|
fade_by_dist(self.label, pindist,f_near,f_far,f_hide,255,230,230,230,1)
|
|
fade_by_dist(self.label_sh, pindist,f_near,f_far,f_hide,255,0,0,0,1)
|
|
fade_by_dist(self.dist, pindist,f_near,f_far,f_hide,255,230,230,230,1)
|
|
fade_by_dist(self.dist_sh, pindist,f_near,f_far,f_hide,255,0,0,0,1)
|
|
|
|
local name = pins[self.pin_id].text
|
|
local maxd = 100
|
|
local disty = pindist
|
|
if pindist >= maxd then
|
|
disty = maxd
|
|
end
|
|
local yadj = (disty / maxd * 6)
|
|
local pos = self.marker:GetWndPos()
|
|
local nx,ny,dx,dy,tw
|
|
|
|
if marker_hint_shown("pins") then
|
|
self.label:TextControl():SetText(name)
|
|
self.label_sh:TextControl():SetText(name)
|
|
self.lref:TextControl():SetText(name)
|
|
self.lref:AdjustWidthToText()
|
|
tw = self.lref:GetWidth()
|
|
nx = pos.x - (tw * .5)
|
|
ny = pos.y - 22 + yadj
|
|
--printf("Container for pin %s is %sx%s",name,nx,ny)
|
|
self.label:SetWndPos(vector2():set(nx, ny))
|
|
end
|
|
|
|
if marker_dist_shown("pins") then
|
|
self.last_dist = pindist
|
|
--local dist_txt = string.format("%.1f",pindist)..ts("st_paw_meters_abbr")
|
|
local dist_txt = string.format("%.1f",pindist).."m"
|
|
self.dist:TextControl():SetText(dist_txt)
|
|
self.dist_sh:TextControl():SetText(dist_txt)
|
|
self.wref:TextControl():SetText(dist_txt)
|
|
self.wref:AdjustWidthToText()
|
|
tw = self.wref:GetWidth()
|
|
nx = pos.x - (tw * .5)
|
|
ny = pos.y + szy - 11 + yadj
|
|
self.dist:SetWndPos(vector2():set(nx, ny))
|
|
end
|
|
|
|
self:ShowMarker(true)
|
|
return
|
|
end
|
|
self:ShowMarker(false)
|
|
else
|
|
self:ShowMarker(false)
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- HUD RETICLE (see ui_paw_reticle.script)
|
|
-- ======================================================================
|
|
|
|
HUD_RET = nil
|
|
|
|
function enable_vo_crosshair()
|
|
if not db.actor then return end
|
|
if (HUD_RET == nil) then
|
|
HUD_RET = ui_paw_reticle and ui_paw_reticle.UIPAWReticle()
|
|
if HUD_RET then
|
|
get_hud():AddDialogToRender(HUD_RET)
|
|
else
|
|
printf(logprefix.."ERROR: Unable to load ui_paw_reticle.script or initialize its HUD class")
|
|
end
|
|
end
|
|
end
|
|
|
|
function disable_vo_crosshair()
|
|
if not db.actor then return end
|
|
if (HUD_RET ~= nil) then
|
|
HUD_RET:ShowDialog(false)
|
|
get_hud():RemoveDialogToRender(HUD_RET)
|
|
HUD_RET = nil
|
|
end
|
|
end
|
|
|
|
function update_vo_crosshair()
|
|
if not db.actor then return end
|
|
if (HUD_RET ~= nil) then
|
|
HUD_RET:Update(true)
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- TASK FUNCTORS
|
|
-- ======================================================================
|
|
|
|
|
|
task_functor.waypoint_task_target_functor = function (task_id,field,p,tsk)
|
|
if not paw_enabled then return end
|
|
-- vl("waypoint_task_target_functor called with task_id %s | field %s",task_id,field)
|
|
|
|
if placed_waypoint == nil then
|
|
dl("WARNING: waypoint_task_target_functor called but placed_waypoint is nil, cancelling waypoint task to avoid crash")
|
|
end_waypoint_task()
|
|
return default_id
|
|
end
|
|
|
|
if (field == "target") then
|
|
tsk.target = placed_waypoint.id
|
|
tsk.current_target = placed_waypoint.id
|
|
return placed_waypoint.id
|
|
end
|
|
end
|
|
|
|
|
|
task_functor.waypoint_task_text_functor = function (task_id,field,p,tsk)
|
|
if not (paw_enabled and placed_waypoint) then return end
|
|
-- vl("waypoint_task_text_functor called with task_id %s | field %s",task_id,field)
|
|
if (field == "title") then
|
|
-- vl("custom_name: %s")
|
|
return custom_name or ts("st_paw_placed_waypoint")..(": "..placed_waypoint.name or "")
|
|
elseif (field == "descr") then
|
|
-- vl("custom_desc: %s")
|
|
return custom_desc or ts("st_paw_proceed")
|
|
end
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- CALLBACKS
|
|
-- ======================================================================
|
|
|
|
function npc_on_death_callback(victim,killer)
|
|
vl("npc_on_death_callback: %s (%s) | clear_pin_on_death: %s",victim:name(),victim:id(),clear_pin_on_death)
|
|
if not clear_pin_on_death then return end
|
|
local id = safeid(victim)
|
|
if not (id and (id > 0)) then return end
|
|
if not (id and pins[id]) then return end
|
|
dl("Clearing existing pin for dead body id %s",id)
|
|
local se_obj = alife_object(id)
|
|
do_paw_action("pn_del",se_obj,nil,{syscall=true})
|
|
end
|
|
|
|
|
|
function update_hud_on_show_hide()
|
|
update_hud_waypoint()
|
|
update_vo_crosshair()
|
|
update_hud_pins()
|
|
end
|
|
|
|
local mod_keys = {
|
|
[DIK_keys.DIK_LSHIFT] = {pressed=false,code=1},
|
|
[DIK_keys.DIK_LCONTROL] = {pressed=false,code=2},
|
|
[DIK_keys.DIK_LMENU] = {pressed=false,code=3},
|
|
}
|
|
local mod_key_codes = {
|
|
[1] = DIK_keys.DIK_LSHIFT,
|
|
[2] = DIK_keys.DIK_LCONTROL,
|
|
[3] = DIK_keys.DIK_LMENU,
|
|
}
|
|
local function mod_key_pressed(key)
|
|
if ui_mcm then
|
|
return ui_mcm.get_mod_key(key)
|
|
else
|
|
return mod_keys and mod_keys[key] and mod_keys[key].pressed
|
|
end
|
|
end
|
|
|
|
local function mod_key_held()
|
|
return
|
|
mod_keys[DIK_keys.DIK_LSHIFT].pressed or
|
|
mod_keys[DIK_keys.DIK_LCONTROL].pressed or
|
|
mod_keys[DIK_keys.DIK_LMENU].pressed
|
|
end
|
|
|
|
function on_key_press(key)
|
|
--if not active_binds[key] then return end
|
|
--printf("Monitored keybind %s pressed",key)
|
|
local args
|
|
if mod_keys[key] then
|
|
mod_keys[key].pressed = true
|
|
return
|
|
end
|
|
--local keyname = DIK_name(key)
|
|
--vl("on_key_press(%s) : %s\nModifiers held: Shift %s | Ctrl %s | Alt %s",key,keyname,mod_key_pressed(1),mod_key_pressed(2),mod_key_pressed(3))
|
|
for k,v in pairs(keybinds) do
|
|
if v and v.enabled then
|
|
--local bindtxt = bindtext(v.bind,v.mod)
|
|
--vl("** Checking keybind %s (bind %s | mod %s | hold %s)",k,bindtxt,v.bind,v.mod,v.hold)
|
|
if (key == v.bind) and mod_key_pressed(v.mod) then
|
|
--vl("on_key_press(%s): keybind %s matched %s with bind %s and mod %s",key,k,bindtxt,v.bind,mod)
|
|
if v.hold then
|
|
args = true
|
|
end
|
|
v.action(args)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
--vl("on_key_press: no matching keybind for %s",keyname)
|
|
end
|
|
|
|
|
|
function on_key_release(key)
|
|
local do_action = false
|
|
if mod_keys[key] then
|
|
mod_keys[key].pressed = false
|
|
end
|
|
|
|
--local keyname = DIK_name(key)
|
|
--vl("on_key_release(%s) : %s\nModifiers held: Shift %s | Ctrl %s | Alt %s",key,keyname,mod_key_pressed(1),mod_key_pressed(2),mod_key_pressed(3))
|
|
for k,v in pairs(keybinds) do
|
|
if v and v.enabled and v.hold then
|
|
--local bindtxt = bindtext(v.bind,v.mod)
|
|
--vl("** Checking keybind %s: %s (bind %s | mod %s | hold %s)",k,bindtxt,v.bind,v.mod,v.hold)
|
|
if (key == v.bind) and mod_key_pressed(v.mod) then
|
|
--vl("on_key_release(%s): keybind %s matched %s with bind %s and mod %s",key,k,bindtxt,v.bind,mod)
|
|
v.action(false)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function ctrl_alt_rclick(se_obj,map_table)
|
|
-- not currently implemented - considering uses
|
|
end
|
|
|
|
function on_map_right_click(property_ui, map_table)
|
|
if not map_table then return end
|
|
if map_table.object_id ~= 65535 then return end
|
|
|
|
local pos = map_table.pos
|
|
local se_obj = register_script_zone(pos,map_table.lvid,map_table.gvid)
|
|
map_table.object_id = se_obj and se_obj.id
|
|
|
|
if not se_obj then
|
|
dl("<PAW> Right-click capture failed - unable to find or create valid se_obj")
|
|
return
|
|
else
|
|
if mod_key_pressed(1) then
|
|
-- LSHIFT : unused
|
|
elseif mod_key_pressed(2) then
|
|
--if mod_key_pressed(3) then
|
|
-- CTRL+ALT (unused at this time)
|
|
-- ctrl_alt_rclick(se_obj,map_table)
|
|
-- return
|
|
--end
|
|
|
|
-- LCTRL : Set/Move Waypoint
|
|
if waypoint_active then
|
|
do_paw_action("wp_mov",se_obj)
|
|
else
|
|
do_paw_action("wp_set",se_obj)
|
|
end
|
|
return
|
|
elseif mod_key_pressed(3) then
|
|
-- LALT : Add or edit Pin
|
|
if pins[se_obj.id] then
|
|
open_pin_settings(se_obj.id)
|
|
else
|
|
do_paw_action("pn_add",se_obj)
|
|
return
|
|
end
|
|
end
|
|
dl("<PAW> Passing right-click to get_context_menu_options with id %s and pos %s",se_obj.id,pos)
|
|
last_clicked_id = se_obj.id
|
|
get_context_menu_options(property_ui,se_obj.id,map_table)
|
|
end
|
|
end
|
|
|
|
function map_spot_menu_add_property(property_ui,id)
|
|
last_clicked_id = id
|
|
get_context_menu_options(property_ui,id)
|
|
end
|
|
|
|
|
|
function map_spot_menu_property_clicked(property_ui,id,level_name,prop)
|
|
execute_context_menu_option(property_ui,id,level_name,prop)
|
|
end
|
|
|
|
|
|
function load_file_data()
|
|
dl("<PAW> Loading file data and populating tables")
|
|
local attr_tex = "texture"
|
|
local minimap = "mini_map"
|
|
local levelmap = "level_map"
|
|
local ind = 0
|
|
xml = CScriptXmlInit()
|
|
xml:ParseFile("map_spots.xml")
|
|
for k,v in pairs(icons) do
|
|
local tex,th,tw
|
|
local spot = v
|
|
xml:NavigateToRoot()
|
|
th = xml:ReadAttribute(spot,0,"height")
|
|
tw = xml:ReadAttribute(spot,0,"width")
|
|
xml:NavigateToNode(spot,0)
|
|
vl("trying to find texture data for %s | %s",k,v)
|
|
if xml:NodeExist(attr_tex,0) then
|
|
tex = xml:ReadValue(attr_tex,0)
|
|
vl("texture node found with value %s",tex)
|
|
else
|
|
local spotnode = ""
|
|
local typ = ""
|
|
if xml:NodeExist(minimap) then
|
|
spotnode = xml:ReadAttribute(minimap,0,"spot")
|
|
typ = minimap
|
|
end
|
|
if xml:NodeExist(levelmap) then
|
|
spotnode = xml:ReadAttribute(levelmap,0,"spot")
|
|
typ = levelmap
|
|
end
|
|
if spotnode ~= "" then
|
|
xml:NavigateToRoot()
|
|
th = xml:ReadAttribute(spotnode,0,"height")
|
|
tw = xml:ReadAttribute(spotnode,0,"width")
|
|
vl("ReadAttribute for %s: h %s w %s",v,th,tw)
|
|
xml:NavigateToNode(spotnode,0)
|
|
tex = xml:ReadValue(attr_tex,0)
|
|
vl("%s node found: %s",typ,spotnode)
|
|
end
|
|
end
|
|
|
|
if spot == "paw_pin_redpush32" then
|
|
if not tex then return false end
|
|
end
|
|
|
|
texture_data[spot] = {
|
|
id = k,
|
|
t = tex,
|
|
h = th,
|
|
w = tw,
|
|
}
|
|
ind = ind + 1
|
|
icon_index[ind] = {
|
|
id = k,
|
|
icon = spot,
|
|
data = texture_data[spot],
|
|
}
|
|
vl("Texture for %s: %s (%sx%s)",spot,tex,tw,th)
|
|
end
|
|
current_ico_max = ind
|
|
for k,v in pairs(texture_data) do
|
|
dl("texture_data(%s): tex %s | id %s | %sx%s",k,v.t,v.id,v.w,v.h)
|
|
end
|
|
|
|
ind = 0
|
|
for w, _ in pairs(iconset_ltx) do
|
|
local iconset_ltx_prefix = "iconset_"
|
|
local icons_pos = string.find(w,iconset_ltx_prefix)
|
|
if icons_pos == 1 then
|
|
local group = string.sub(w,icons_pos+string.len(iconset_ltx_prefix))
|
|
local set_cfg = icon_sets_ini:collect_section(w)
|
|
local name = set_cfg.name
|
|
local def = set_cfg.default
|
|
local sec_list = group.."_icons"
|
|
ind = ind + 1
|
|
icon_sets[group] = {
|
|
name = name,
|
|
group = group,
|
|
default = def,
|
|
active_icon = icons[def],
|
|
i = ind,
|
|
}
|
|
local setdata = icon_sets[group]
|
|
set_index[ind] = {
|
|
id = group,
|
|
data = setdata,
|
|
}
|
|
dl("Found icon set %s with group %s, section %s",setdata.name,group,sec_list)
|
|
set_index[ind].ii = {}
|
|
setdata.ii = {}
|
|
setdata.ri = {}
|
|
local iconlist = {}
|
|
local il = icon_sets_ini:collect_section(sec_list)
|
|
local i = 0
|
|
for k,_ in pairs(il) do
|
|
i = i + 1
|
|
local spot = icons[k]
|
|
vl("set %s iconlist: icons[%s] = %s",group,k,spot)
|
|
iconlist[spot] = texture_data[spot].t
|
|
set_index[ind].ii[i] = spot
|
|
setdata.ii[i] = spot
|
|
setdata.ri[spot] = i
|
|
end
|
|
setdata.inum = i
|
|
setdata.icons = iconlist
|
|
end
|
|
end
|
|
current_set_max = ind
|
|
dl("Loading menu actions from actions_ini")
|
|
for w, _ in pairs(actions_ltx) do
|
|
action_codes[w] = actions_ini:collect_section(w)
|
|
local ac = action_codes[w]
|
|
local opt_loc = ts(ac.text)
|
|
dl("<PAW> ac.mode: %s | type: %s | as num: %s | >0: %s",ac and ac.mode,ac and type(ac.mode),ac and tonumber(ac.mode),ac and (tonumber(ac.mode) > 0))
|
|
ac.mode = clamp(tonumber(ac and ac.mode) or 0,0,4)
|
|
ac.enable = (ac.enable == "true")
|
|
action[opt_loc] = w
|
|
if verbose then
|
|
vl("Initializing menu action:\n%s = %s",opt_loc,action[opt_loc])
|
|
for k,v in pairs(ac) do vl("%s = %s",k,v) end
|
|
end
|
|
end
|
|
|
|
dl("Loading and parsing valid clsids (%s)",size_table(clsids_ltx))
|
|
for k,v in pairs(clsids_ltx) do
|
|
dl("%s = %s",k,v)
|
|
if v == "number" then
|
|
local k1 = tonumber(k)
|
|
if k1 and k1 > 0 then
|
|
vl("Found valid clsid number value: %s",k1)
|
|
valid_clsids[tonumber(k1)] = true
|
|
end
|
|
elseif v == "string" then
|
|
if k and clsid[k] then
|
|
local k1 = tonumber(clsid[k])
|
|
vl("Found valid clsid string value: %s = %s",k,k1)
|
|
valid_clsids[tonumber(k1)] = true
|
|
end
|
|
end
|
|
end
|
|
table.sort(icons)
|
|
table.sort(icon_sets)
|
|
catsy_paw_mcm.icon_sets = icon_sets
|
|
table.sort(action_codes)
|
|
dl(logprefix.."All file data loaded")
|
|
--utils_data.print_table(icon_sets)
|
|
started = true
|
|
local load_set_curr = axr_main.config:r_value("mcm", "pawsys/pawpins/pin_icon_group", {val=0}) or "pins"
|
|
local load_pin_curr = axr_main.config:r_value("mcm", "pawsys/pawpins/poi_icon_"..load_set_curr, {val=0})
|
|
|
|
printf(logprefix.."Personal Adjustable Waypoint %s started at %s",script_version,time_global())
|
|
return true
|
|
end
|
|
|
|
|
|
function load_state(data)
|
|
dl("load_state: Checking for saved PAW data")
|
|
|
|
local ps = data.pawsys
|
|
local pd = data.pawdata
|
|
if ps then
|
|
vl("load_state: pawsys found, loading")
|
|
placed_waypoint = ps.current_waypoint
|
|
last_waypoint = ps.last_waypoint
|
|
custom_name = ps.custom_name
|
|
custom_desc = ps.custom_desc
|
|
pins = ps.pins
|
|
if placed_waypoint then waypoint_active = true end
|
|
welcome_msg_shown = ps.welcome_msg_shown
|
|
|
|
end
|
|
if pd and pd.valid then
|
|
dl("load_state: pawdata found, loading")
|
|
pawdata = pd
|
|
pins = pawdata.pins
|
|
else
|
|
dl("load_state: pawdata not found, initializing")
|
|
pawdata.curr_set_name = "pins"
|
|
pawdata.curr_set_data = icon_sets[pawdata.curr_set_name]
|
|
local setdata = pawdata.curr_set_data
|
|
pawdata.curr_set_data = setdata
|
|
pawdata.curr_set_ind = setdata.i
|
|
pawdata.curr_ico_name = setdata.active_icon
|
|
pawdata.curr_ico_ind = setdata.ri[root_patch_name(setdata.active_icon)]
|
|
vl("pawdata: set %s (%s) | icon %s (%s)",pawdata.curr_set_name,pawdata.curr_set_ind,pawdata.curr_ico_name,pawdata.curr_ico_ind)
|
|
end
|
|
if pins_exist() then
|
|
for k,v in pairs(pins) do
|
|
pins[k].label = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function save_state(data)
|
|
update_mcm_icoset_data()
|
|
dl("save_state: Cleaning up script zones and temp markers")
|
|
script_zone_cleanup()
|
|
dl("save_state: Saving waypoint and config data")
|
|
data.paw_waypoint_info = nil
|
|
data.pawsys = {}
|
|
data.pawsys.current_waypoint = placed_waypoint
|
|
data.pawsys.last_waypoint = last_waypoint
|
|
data.pawsys.custom_name = custom_name
|
|
data.pawsys.custom_desc = custom_desc
|
|
data.pawsys.dynamic_faves = dynamic_faves
|
|
data.pawsys.welcome_msg_shown = welcome_msg_shown
|
|
data.pawsys.pins = {}
|
|
pawdata.valid = true
|
|
data.pawdata = pawdata
|
|
dl("save_state: Saving player's pins")
|
|
data.pawsys.pins = pins
|
|
end
|
|
|
|
function actor_on_update()
|
|
tick()
|
|
end
|
|
|
|
function actor_on_first_update()
|
|
on_option_change()
|
|
if not paw_enabled then
|
|
UnregisterScriptCallback("actor_on_update",actor_on_update)
|
|
return
|
|
end
|
|
temp_pin_cleanup(true)
|
|
active_set(icon_sets[current_active_set].i)
|
|
show_all_pins(true)
|
|
if waypoint_active then
|
|
local id = placed_waypoint.id
|
|
local se_obj = alife_object(id)
|
|
if not se_obj then return end
|
|
local savelast = last_waypoint
|
|
do_paw_action("wp_mov",se_obj)
|
|
last_waypoint = savelast
|
|
end
|
|
reset_indicator()
|
|
if wp_hud_icon_enabled then
|
|
show_hud_waypoint()
|
|
else
|
|
hide_hud_waypoint()
|
|
end
|
|
if (reticle_mode > 0) or (autotag_mode > 0) then
|
|
enable_vo_crosshair()
|
|
else
|
|
disable_vo_crosshair()
|
|
end
|
|
|
|
init_hud_pins()
|
|
if not welcome_msg_shown then
|
|
CreateTimeEvent("paw_welcome_message",0,5,paw_welcome_message)
|
|
end
|
|
end
|
|
|
|
|
|
function actor_on_net_destroy()
|
|
script_zone_cleanup()
|
|
hide_hud_waypoint()
|
|
empty_table(hud_pin_objs)
|
|
end
|
|
|
|
|
|
function on_mouse_wheel(scroll_dir, flags)
|
|
if not mwheel_enabled then
|
|
UnregisterScriptCallback("on_mouse_wheel",on_mouse_wheel)
|
|
return
|
|
end
|
|
local now = time_global()
|
|
if now < mwheel_next_poll then return end
|
|
mwheel_next_poll = now + mwheel_poll_interval
|
|
|
|
local cycling_active = (icon_cycle_active or set_cycle_active)
|
|
local invalid_uistate = actor_menu.inventory_opened() or not cycling_active
|
|
local pin_wnd_open = pin_window_is_open()
|
|
--printf("on_mouse_wheel: cycling_active %s | invalid_uistate %s | pin_wnd_open %s",cycling_active,invalid_uistate,pin_wnd_open)
|
|
if invalid_uistate and not pin_wnd_open then
|
|
--printf("Invalid UI state for mouse wheel use, aborting")
|
|
return
|
|
end
|
|
|
|
flags.ret_value = false
|
|
|
|
local cycle_dir = scroll_dir
|
|
if cycle_dir == 0 then cycle_dir = -1 end
|
|
vl("scroll_dir: %s | cycle_dir: %s",scroll_dir,cycle_dir)
|
|
|
|
if pin_wnd_open and GUI_PinInd then
|
|
for ctrl,icoset in pairs(hover_elements) do
|
|
--printf("Checking hover state for GUI_PinInd[%s]",ctrl)
|
|
if GUI_PinInd[ctrl]:IsCursorOverWindow() then
|
|
cycle_items(cycle_dir,icoset)
|
|
return
|
|
end
|
|
end
|
|
if not cycling_active then
|
|
flags.ret_value = true
|
|
return
|
|
end
|
|
end
|
|
cycle_items(cycle_dir)
|
|
end
|
|
|
|
--[[
|
|
function actor_on_stash_create(data)
|
|
-- figure out why this causes busyhands with hideout furniture
|
|
if not use_custom_backpack_icon then return end
|
|
local id = data and data.stash_id
|
|
if not id then return end
|
|
local hint = data and data.stash_name
|
|
local mapspot = stash_icons["player"] or "treasure"
|
|
dl("Player placed backpack stash %s (%s), replacing mapspot with %s",hint,id,mapspot)
|
|
function replace_spot()
|
|
remove_mapspot(id,stash_icons["basic"])
|
|
if init_backpack_as_pin then
|
|
local sec = data.stash_section
|
|
init_new_pin(id,sec,hint,mapspot)
|
|
level.map_add_object_spot(id,mapspot,hint)
|
|
else
|
|
level.map_add_object_spot_ser(id,mapspot,hint)
|
|
end
|
|
end
|
|
-- For some reason the backpack UI script will shit itself if you don't delay messing with the mapspots
|
|
CreateTimeEvent("pawdelay","paw"..tostring(time_global()),0.125,replace_spot)
|
|
end
|
|
|
|
function actor_on_stash_remove(data)
|
|
if not use_custom_backpack_icon then return end
|
|
local id = data and data.stash_id
|
|
if not id then return end
|
|
local mapspot = stash_icons["player"] or "treasure"
|
|
dl("Player picked up backpack stash %s, removing custom mapspot %s",id,mapspot)
|
|
if init_backpack_as_pin then
|
|
do_paw_action("pn_del",nil,nil,{syscall=true,id=id})
|
|
else
|
|
remove_mapspot(id,mapspot)
|
|
end
|
|
end
|
|
--]]
|
|
|
|
function unregister_all_callbacks()
|
|
UnregisterScriptCallback("actor_on_update",actor_on_update)
|
|
--UnregisterScriptCallback("actor_on_stash_create",actor_on_stash_create)
|
|
--UnregisterScriptCallback("actor_on_stash_remove",actor_on_stash_remove)
|
|
UnregisterScriptCallback("actor_on_net_destroy",actor_on_net_destroy)
|
|
UnregisterScriptCallback("actor_on_first_update",actor_on_first_update)
|
|
UnregisterScriptCallback("load_state",load_state)
|
|
UnregisterScriptCallback("save_state",save_state)
|
|
UnregisterScriptCallback("map_spot_menu_add_property",map_spot_menu_add_property)
|
|
UnregisterScriptCallback("map_spot_menu_property_clicked",map_spot_menu_property_clicked)
|
|
UnregisterScriptCallback("on_key_press",on_key_press)
|
|
UnregisterScriptCallback("on_key_release",on_key_release)
|
|
UnregisterScriptCallback("GUI_on_show",update_hud_on_show_hide)
|
|
UnregisterScriptCallback("GUI_on_hide",update_hud_on_show_hide)
|
|
UnregisterScriptCallback("monster_on_death_callback",npc_on_death_callback)
|
|
UnregisterScriptCallback("npc_on_death_callback",npc_on_death_callback)
|
|
if mwheel_avail then
|
|
UnregisterScriptCallback("on_mouse_wheel",on_mouse_wheel)
|
|
end
|
|
if right_click_avail then
|
|
UnregisterScriptCallback("on_map_right_click",on_map_right_click)
|
|
end
|
|
end
|
|
|
|
function register_all_callbacks()
|
|
RegisterScriptCallback("actor_on_update",actor_on_update)
|
|
--RegisterScriptCallback("actor_on_stash_create",actor_on_stash_create)
|
|
--RegisterScriptCallback("actor_on_stash_remove",actor_on_stash_remove)
|
|
RegisterScriptCallback("actor_on_net_destroy",actor_on_net_destroy)
|
|
RegisterScriptCallback("actor_on_first_update",actor_on_first_update)
|
|
RegisterScriptCallback("load_state",load_state)
|
|
RegisterScriptCallback("save_state",save_state)
|
|
RegisterScriptCallback("map_spot_menu_add_property",map_spot_menu_add_property)
|
|
RegisterScriptCallback("map_spot_menu_property_clicked",map_spot_menu_property_clicked)
|
|
RegisterScriptCallback("on_key_press",on_key_press)
|
|
RegisterScriptCallback("on_key_release",on_key_release)
|
|
RegisterScriptCallback("GUI_on_show",update_hud_on_show_hide)
|
|
RegisterScriptCallback("GUI_on_hide",update_hud_on_show_hide)
|
|
RegisterScriptCallback("monster_on_death_callback",npc_on_death_callback)
|
|
RegisterScriptCallback("npc_on_death_callback",npc_on_death_callback)
|
|
if mwheel_avail then
|
|
RegisterScriptCallback("on_mouse_wheel",on_mouse_wheel)
|
|
end
|
|
if right_click_avail then
|
|
RegisterScriptCallback("on_map_right_click",on_map_right_click)
|
|
end
|
|
end
|
|
|
|
function on_game_start()
|
|
if load_failed then return end
|
|
RegisterScriptCallback("on_option_change",on_option_change)
|
|
register_all_callbacks()
|
|
on_option_change()
|
|
end
|
|
|
|
-- ======================================================================
|
|
-- LOAD FILE DATA - KILLSWITCH AND NOTIFY ON FAILURE
|
|
-- ======================================================================
|
|
|
|
if not load_file_data() then
|
|
disable_mcm_updates = true
|
|
load_failed = true
|
|
paw_enabled = false
|
|
started = false
|
|
unregister_all_callbacks()
|
|
|
|
if not disable_load_warning then
|
|
local tiperr = psk(game.translate_string("st_paw_texture_load_error_tip"),text_colors)
|
|
RegisterScriptCallback("actor_on_first_update",
|
|
function()
|
|
CreateTimeEvent("pawerror",0,5,(
|
|
function()
|
|
db.actor:give_game_news("PAW System",tiperr,"ui_inGame2_Mesta_evakuatsii",0,15000)
|
|
xr_sound.set_sound_play(AC_ID,"pda_tips")
|
|
return true
|
|
end
|
|
))
|
|
end
|
|
)
|
|
end
|
|
|
|
local errstr = game.translate_string("st_paw_texture_load_error1").."\n\n"..game.translate_string("st_paw_texture_load_error2")
|
|
assert(not load_failed, "\n\n"..
|
|
"~ ------------------------------------------------------------------------\n"..
|
|
errstr.."\n"..
|
|
"~ ------------------------------------------------------------------------\n"
|
|
)
|
|
end
|
|
|
|
-- ======================================================================
|
|
|