mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-12 02:32:10 +00:00
## About The Pull Request ### Adds this TGUI spawn panel with a lot of stuff  ### Adds two useful admining hotkeys `Ctrl + Shift + LMB` on an atom opens the View Variables window `Ctrl + LMB` on a mob opens the Player Panel window This PR is an upgrade/continuation/upstreaming of the following PR by @Ez-Briz: https://github.com/ss220club/BandaStation/pull/1242 ## Why It's Good For The Game ### Icon and object previews! https://github.com/user-attachments/assets/894c4383-0455-4ba8-9cc1-7fb0d8dff6c7 ### Introducing Fuzzy Search!  ### Easier datum marking and recalling! https://github.com/user-attachments/assets/4934ecca-18aa-45ce-83af-1fe90263b534 ### Targeted spawn and quick targeted droppods (Build Mode Lite™️) (RMB to disengage)! https://github.com/user-attachments/assets/38eb6e08-74bf-471c-8bd5-61e1b219086b ### Weaponize your tiders with a hover of a mouse! https://github.com/user-attachments/assets/9840d0ed-d20d-4d48-91e0-2dc1eaf17e36 The options are persistent between opens and even rounds, using local `storage`, which means you won't have to readjust your panel every time you close it! ...and it doesn't end there. ## WIP things: - [x] implement fuzzy search (requires https://github.com/tgstation/tgui-core/pull/166 to be merged); - [x] add a modal window to adjust description, icon file/state/size and badmin flags; - [x] clean the code up; ## Changelog 🆑 mcbalaam, Ez-Briz admin: Added a new TGUI spawn panel, removing it's ancestors - HTML "Create X" panels /🆑
337 lines
10 KiB
Plaintext
337 lines
10 KiB
Plaintext
#define WHERE_FLOOR_BELOW_MOB "Current location"
|
|
#define WHERE_SUPPLY_BELOW_MOB "Current location (droppod)"
|
|
#define WHERE_MOB_HAND "In own mob's hand"
|
|
#define WHERE_MARKED_OBJECT "At a marked object"
|
|
#define WHERE_IN_MARKED_OBJECT "In the marked object"
|
|
#define WHERE_TARGETED_LOCATION "Targeted location"
|
|
#define WHERE_TARGETED_LOCATION_POD "Targeted location (droppod)"
|
|
#define WHERE_TARGETED_MOB_HAND "In targeted mob's hand"
|
|
|
|
#define PRECISE_MODE_OFF "Off"
|
|
#define PRECISE_MODE_TARGET "Target"
|
|
#define PRECISE_MODE_MARK "Mark"
|
|
#define PRECISE_MODE_COPY "Copy"
|
|
|
|
#define OFFSET_ABSOLUTE "Absolute offset"
|
|
#define OFFSET_RELATIVE "Relative offset"
|
|
|
|
GLOBAL_LIST_INIT(spawnpanels_by_ckey, list())
|
|
|
|
/*
|
|
An instance of a /tg/UI™ Spawn Panel. Stores preferences, spawns things, controls the UI. Unique for each user (their ckey).
|
|
*/
|
|
/datum/spawnpanel
|
|
/// Who this instance of spawn panel belongs to. The instances are unique to correctly keep modified values between multiple admins.
|
|
var/owner_ckey
|
|
/// Where and how the atom should be spawned.
|
|
var/where_target_type = WHERE_FLOOR_BELOW_MOB
|
|
/// The atom selected from the panel.
|
|
var/atom/selected_atom = null
|
|
/// The icon selected for the atom from the panel.
|
|
var/selected_atom_icon = null
|
|
/// The icon state selected for the atom from the panel.
|
|
var/selected_atom_icon_state = null
|
|
/// Should selected icon/icon state override the initial ones? Added as an edge case to not replace animated GAGS icons.
|
|
var/apply_icon_override = FALSE
|
|
/// A list of icon states to display in preview panels.
|
|
var/list/available_icon_states = null
|
|
/// Override for the icon size of the spawned mob.
|
|
var/atom_icon_size = 100
|
|
/// How many atoms will be spawned at once.
|
|
var/atom_amount = 1
|
|
/// Custom atom name (leave `null` for initial).
|
|
var/atom_name = null
|
|
/// Custom atom description (leave `null` for initial).
|
|
var/atom_desc = null
|
|
/// Custom atom dir (leave `null` for `2`).
|
|
var/atom_dir = 1
|
|
/// An associative list of x-y-z offsets.
|
|
var/offset = list()
|
|
/// The pivot point for offsetting — relative or absolute.
|
|
var/offset_type = OFFSET_RELATIVE
|
|
/// Precise mode toggle. Used for build-mode-like spawning experience and targeting datums.
|
|
var/precise_mode = PRECISE_MODE_OFF
|
|
|
|
/datum/spawnpanel/New()
|
|
. = ..()
|
|
offset = list("X" = 0, "Y" = 0, "Z" = 0)
|
|
|
|
/datum/spawnpanel/ui_interact(mob/user, datum/tgui/ui)
|
|
if(user.client.ckey != owner_ckey)
|
|
return
|
|
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "SpawnPanel")
|
|
ui.open()
|
|
|
|
/// Returns a `spawnpanel` instance belonging to this `user`, or creates and registers a new one
|
|
/proc/get_spawnpanel_for_admin(mob/user)
|
|
if(!user?.client?.ckey)
|
|
return null
|
|
|
|
var/ckey = user.client.ckey
|
|
|
|
if(GLOB.spawnpanels_by_ckey[ckey])
|
|
return GLOB.spawnpanels_by_ckey[ckey]
|
|
|
|
var/datum/spawnpanel/new_panel = new()
|
|
new_panel.owner_ckey = ckey
|
|
GLOB.spawnpanels_by_ckey[ckey] = new_panel
|
|
|
|
return new_panel
|
|
|
|
/datum/spawnpanel/ui_close(mob/user)
|
|
. = ..()
|
|
if (precise_mode && precise_mode != PRECISE_MODE_OFF)
|
|
toggle_precise_mode(PRECISE_MODE_OFF)
|
|
|
|
/datum/spawnpanel/ui_state(mob/user)
|
|
if(user.client.ckey != owner_ckey)
|
|
return GLOB.never_state
|
|
return ADMIN_STATE(R_ADMIN)
|
|
|
|
/datum/spawnpanel/ui_act(action, params)
|
|
if(..())
|
|
return FALSE
|
|
|
|
if(usr.client.ckey != owner_ckey)
|
|
return FALSE
|
|
|
|
switch(action)
|
|
if("select-new-DMI")
|
|
var/icon/new_icon = input("Select a new icon file:", "Icon") as null|icon
|
|
if(new_icon)
|
|
selected_atom_icon = new_icon
|
|
available_icon_states = icon_states(selected_atom_icon)
|
|
if(!(selected_atom_icon_state in available_icon_states))
|
|
selected_atom_icon_state = available_icon_states[1]
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("set-apply-icon-override")
|
|
apply_icon_override = !!params["value"]
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("reset-DMI-icon")
|
|
selected_atom_icon = null
|
|
selected_atom_icon_state = null
|
|
if(selected_atom)
|
|
selected_atom_icon = initial(selected_atom.icon)
|
|
selected_atom_icon_state = initial(selected_atom.icon_state)
|
|
available_icon_states = icon_states(selected_atom_icon)
|
|
else
|
|
available_icon_states = list()
|
|
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("select-new-icon-state")
|
|
selected_atom_icon_state = params["new_state"]
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("reset-icon-state")
|
|
selected_atom_icon_state = null
|
|
if(selected_atom)
|
|
selected_atom_icon_state = initial(selected_atom.icon_state)
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("set-icon-size")
|
|
atom_icon_size = params["size"]
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("reset-icon-size")
|
|
atom_icon_size = 100
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("get-icon-states")
|
|
available_icon_states = icon_states(selected_atom_icon)
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if("selected-atom-changed")
|
|
var/path = text2path(params["newObj"])
|
|
if(path)
|
|
var/atom/temp_atom = path
|
|
selected_atom_icon = initial(temp_atom.icon)
|
|
selected_atom_icon_state = initial(temp_atom.icon_state)
|
|
available_icon_states = icon_states(selected_atom_icon)
|
|
selected_atom = temp_atom
|
|
return TRUE
|
|
|
|
if("create-atom-action")
|
|
var/list/spawn_params = list(
|
|
"selected_atom" = selected_atom,
|
|
"offset" = params["offset"],
|
|
"atom_dir" = text2num(params["dir"]) || 1,
|
|
"atom_amount" = text2num(params["atom_amount"]) || 1,
|
|
"atom_name" = params["atom_name"],
|
|
"where_target_type" = params["where_target_type"] || WHERE_FLOOR_BELOW_MOB,
|
|
"atom_icon_size" = params["atom_icon_size"],
|
|
"offset_type" = params["offset_type"] || OFFSET_RELATIVE,
|
|
"apply_icon_override" = apply_icon_override,
|
|
)
|
|
|
|
if(apply_icon_override)
|
|
spawn_params["selected_atom_icon"] = selected_atom_icon
|
|
spawn_params["selected_atom_icon_state"] = selected_atom_icon_state
|
|
|
|
spawn_atom(spawn_params, usr)
|
|
return TRUE
|
|
|
|
if("toggle-precise-mode")
|
|
var/precise_type = params["newPreciseType"]
|
|
if(precise_type == PRECISE_MODE_TARGET && params["where_target_type"])
|
|
where_target_type = params["where_target_type"]
|
|
toggle_precise_mode(precise_type)
|
|
return TRUE
|
|
|
|
if("update-settings")
|
|
if(params["atom_amount"])
|
|
atom_amount = text2num(params["atom_amount"])
|
|
if(params["atom_dir"])
|
|
atom_dir = text2num(params["atom_dir"])
|
|
if(params["offset"])
|
|
var/list/temp_offset = params["offset"]
|
|
offset["X"] = temp_offset[1]
|
|
offset["Y"] = temp_offset[2]
|
|
offset["Z"] = temp_offset[3]
|
|
if(params["atom_name"])
|
|
atom_name = params["atom_name"]
|
|
if(params["where_target_type"])
|
|
where_target_type = params["where_target_type"]
|
|
if(params["offset_type"])
|
|
offset_type = params["offset_type"]
|
|
if(params["atom_icon_size"])
|
|
atom_icon_size = text2num(params["atom_icon_size"])
|
|
if(params["selected_atom_icon"])
|
|
selected_atom_icon = params["selected_atom_icon"]
|
|
if(params["selected_atom_icon_state"])
|
|
selected_atom_icon_state = params["selected_atom_icon_state"]
|
|
return TRUE
|
|
|
|
/datum/spawnpanel/proc/toggle_precise_mode(precise_type)
|
|
precise_mode = precise_type
|
|
var/client/admin_client = usr.client
|
|
if (!admin_client)
|
|
return
|
|
|
|
admin_client.mouse_up_icon = null
|
|
admin_client.mouse_down_icon = null
|
|
admin_client.mouse_override_icon = null
|
|
admin_client.click_intercept = null
|
|
|
|
if (precise_mode != PRECISE_MODE_OFF)
|
|
admin_client.mouse_up_icon = 'icons/effects/mouse_pointers/supplypod_pickturf.dmi'
|
|
admin_client.mouse_down_icon = 'icons/effects/mouse_pointers/supplypod_pickturf_down.dmi'
|
|
admin_client.mouse_override_icon = admin_client.mouse_up_icon
|
|
admin_client.mouse_pointer_icon = admin_client.mouse_override_icon
|
|
admin_client.click_intercept = src
|
|
|
|
winset(admin_client, "mapwindow.map", "right-click=true")
|
|
else
|
|
winset(admin_client, "mapwindow.map", "right-click=false")
|
|
|
|
var/mob/holder_mob = admin_client.mob
|
|
holder_mob?.update_mouse_pointer()
|
|
|
|
/datum/spawnpanel/proc/InterceptClickOn(mob/user, params, atom/target)
|
|
var/list/modifiers = params2list(params)
|
|
var/left_click = LAZYACCESS(modifiers, LEFT_CLICK)
|
|
var/right_click = LAZYACCESS(modifiers, RIGHT_CLICK)
|
|
|
|
if(right_click)
|
|
toggle_precise_mode(PRECISE_MODE_OFF)
|
|
SStgui.update_uis(src)
|
|
return TRUE
|
|
|
|
if(left_click)
|
|
if(istype(target,/atom/movable/screen))
|
|
return FALSE
|
|
|
|
var/turf/clicked_turf = get_turf(target)
|
|
if(!clicked_turf)
|
|
return FALSE
|
|
|
|
switch(precise_mode)
|
|
if(PRECISE_MODE_TARGET)
|
|
var/list/spawn_params = list(
|
|
"selected_atom" = selected_atom,
|
|
"atom_amount" = atom_amount,
|
|
"offset" = "0,0,0",
|
|
"atom_dir" = atom_dir,
|
|
"atom_name" = atom_name,
|
|
"atom_desc" = atom_desc,
|
|
"offset_type" = OFFSET_ABSOLUTE,
|
|
"where_target_type" = where_target_type,
|
|
"target" = target,
|
|
"atom_icon_size" = atom_icon_size,
|
|
"apply_icon_override" = apply_icon_override,
|
|
)
|
|
|
|
if(apply_icon_override)
|
|
spawn_params["selected_atom_icon"] = selected_atom_icon
|
|
spawn_params["selected_atom_icon_state"] = selected_atom_icon_state
|
|
|
|
if(where_target_type == WHERE_TARGETED_LOCATION || where_target_type == WHERE_TARGETED_LOCATION_POD)
|
|
spawn_params["X"] = clicked_turf.x
|
|
spawn_params["Y"] = clicked_turf.y
|
|
spawn_params["Z"] = clicked_turf.z
|
|
|
|
spawn_atom(spawn_params, user)
|
|
|
|
if(PRECISE_MODE_MARK)
|
|
var/client/admin_client = user.client
|
|
admin_client.mark_datum(target)
|
|
to_chat(user, span_notice("Marked object: [icon2html(target, user)] [span_bold("[target]")]"))
|
|
toggle_precise_mode(PRECISE_MODE_OFF)
|
|
SStgui.update_uis(src)
|
|
|
|
if(PRECISE_MODE_COPY)
|
|
to_chat(user, span_notice("Picked object: [icon2html(target, user)] [span_bold("[target]")]"))
|
|
selected_atom = target
|
|
toggle_precise_mode(PRECISE_MODE_OFF)
|
|
SStgui.update_uis(src)
|
|
|
|
return TRUE
|
|
|
|
/datum/spawnpanel/ui_data(mob/user)
|
|
var/data = list()
|
|
data["icon"] = selected_atom_icon
|
|
data["iconState"] = selected_atom_icon_state
|
|
data["iconSize"] = atom_icon_size
|
|
data["apply_icon_override"] = apply_icon_override
|
|
var/list/states = list()
|
|
if(available_icon_states)
|
|
for(var/state in available_icon_states)
|
|
states += state
|
|
data["iconStates"] = states
|
|
data["precise_mode"] = precise_mode
|
|
data["selected_object"] = selected_atom ? "[selected_atom.type]" : ""
|
|
return data
|
|
|
|
/datum/spawnpanel/ui_assets(mob/user)
|
|
return list(
|
|
get_asset_datum(/datum/asset/json/spawnpanel),
|
|
)
|
|
|
|
#undef WHERE_FLOOR_BELOW_MOB
|
|
#undef WHERE_SUPPLY_BELOW_MOB
|
|
#undef WHERE_MOB_HAND
|
|
#undef WHERE_MARKED_OBJECT
|
|
#undef WHERE_IN_MARKED_OBJECT
|
|
#undef WHERE_TARGETED_LOCATION
|
|
#undef WHERE_TARGETED_LOCATION_POD
|
|
#undef WHERE_TARGETED_MOB_HAND
|
|
#undef PRECISE_MODE_OFF
|
|
#undef PRECISE_MODE_TARGET
|
|
#undef PRECISE_MODE_MARK
|
|
#undef PRECISE_MODE_COPY
|
|
#undef OFFSET_ABSOLUTE
|
|
#undef OFFSET_RELATIVE
|