mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 11:05:03 +01:00
Merge branch 'master' into my-nanomaps-cant-be-this-cute
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
* tgui modals
|
||||
*
|
||||
* Allows creation of modals within tgui.
|
||||
*/
|
||||
|
||||
GLOBAL_LIST(tgui_modals)
|
||||
|
||||
/**
|
||||
* Call this from a proc that is called in tgui_act() to process modal actions
|
||||
*
|
||||
* Example: /obj/machinery/chem_master/proc/tgui_act_modal
|
||||
* You can then switch based on the return value and show different
|
||||
* modals depending on the answer.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * action - The called action
|
||||
* * params - The params to the action
|
||||
*/
|
||||
/datum/proc/tgui_modal_act(datum/source = src, action = "", params)
|
||||
ASSERT(istype(source))
|
||||
|
||||
. = null
|
||||
switch(action)
|
||||
if("modal_open") // Params: id, arguments
|
||||
return TGUI_MODAL_OPEN
|
||||
if("modal_answer") // Params: id, answer, arguments
|
||||
params["answer"] = tgui_modal_preprocess_answer(source, params["answer"])
|
||||
if(tgui_modal_answer(source, params["id"], params["answer"])) // If there's a current modal with a delegate that returned TRUE, no need to continue
|
||||
. = TGUI_MODAL_DELEGATE
|
||||
else
|
||||
. = TGUI_MODAL_ANSWER
|
||||
tgui_modal_clear(source)
|
||||
if("modal_close") // Params: id
|
||||
tgui_modal_clear(source)
|
||||
return TGUI_MODAL_CLOSE
|
||||
|
||||
/**
|
||||
* Call this from tgui_data() to return modal information if needed
|
||||
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
*/
|
||||
/datum/proc/tgui_modal_data(datum/source = src)
|
||||
ASSERT(istype(source))
|
||||
|
||||
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, source.UID())
|
||||
if(!current)
|
||||
return null
|
||||
|
||||
return current.to_data()
|
||||
|
||||
/**
|
||||
* Clears the current modal for a given datum
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
*/
|
||||
/datum/proc/tgui_modal_clear(datum/source = src)
|
||||
ASSERT(istype(source))
|
||||
|
||||
LAZYINITLIST(GLOB.tgui_modals)
|
||||
var/datum/tgui_modal/previous = GLOB.tgui_modals[source.UID()]
|
||||
if(!previous)
|
||||
return FALSE
|
||||
|
||||
for(var/i in 1 to length(GLOB.tgui_modals))
|
||||
var/key = GLOB.tgui_modals[i]
|
||||
if(previous == GLOB.tgui_modals[key])
|
||||
GLOB.tgui_modals.Cut(i, i + 1)
|
||||
break
|
||||
|
||||
SStgui.update_uis(source)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Opens a message TGUI modal
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when closed
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
*/
|
||||
/datum/proc/tgui_modal_message(datum/source = src, id, text = "Default modal message", delegate, arguments)
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/modal = new(id, text, delegate, arguments)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a text input TGUI modal
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when submitted
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * value - The default value of the input
|
||||
* * max_length - The maximum char length of the input
|
||||
*/
|
||||
/datum/proc/tgui_modal_input(datum/source = src, id, text = "Default modal message", delegate, arguments, value = "", max_length = TGUI_MODAL_INPUT_MAX_LENGTH)
|
||||
ASSERT(length(id))
|
||||
ASSERT(max_length > 0)
|
||||
|
||||
var/datum/tgui_modal/input/modal = new(id, text, delegate, arguments, value, max_length)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a dropdown input TGUI modal
|
||||
*
|
||||
* Internally checks if the answer is in the list of choices.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when submitted
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * value - The default value of the dropdown
|
||||
* * choices - The list of available choices in the dropdown
|
||||
*/
|
||||
/datum/proc/tgui_modal_choice(datum/source = src, id, text = "Default modal message", delegate, arguments, value = "", choices)
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/input/choice/modal = new(id, text, delegate, arguments, value, choices)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a bento input TGUI modal
|
||||
*
|
||||
* Internally checks if the answer is in the list of choices.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when submitted
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * value - The default value of the bento
|
||||
* * choices - The list of available choices in the bento
|
||||
*/
|
||||
/datum/proc/tgui_modal_bento(datum/source = src, id, text = "Default modal message", delegate, arguments, value, choices)
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/input/bento/modal = new(id, text, delegate, arguments, value, choices)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a yes/no TGUI modal
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when "Yes" is pressed
|
||||
* * delegate_no - The proc to call when "No" is pressed
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * yes_text - The text to show in the "Yes" button
|
||||
* * no_text - The text to show in the "No" button
|
||||
*/
|
||||
/datum/proc/tgui_modal_boolean(datum/source = src, id, text = "Default modal message", delegate, delegate_no, arguments, yes_text = "Yes", no_text = "No")
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/boolean/modal = new(id, text, delegate, delegate_no, arguments, yes_text, no_text)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Registers a given modal to a source. Private.
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * modal - The datum/tgui_modal to register
|
||||
* * replace_previous - Whether any modal currently assigned to source should be replaced
|
||||
* * instant_update - Whether the changes should reflect immediately
|
||||
*/
|
||||
/datum/proc/tgui_modal_new(datum/source = src, datum/tgui_modal/modal = null, replace_previous = TRUE, instant_update = TRUE)
|
||||
ASSERT(istype(source))
|
||||
ASSERT(istype(modal))
|
||||
|
||||
var/datum/tgui_modal/previous = LAZYACCESS(GLOB.tgui_modals, source.UID())
|
||||
if(previous && !replace_previous)
|
||||
return FALSE
|
||||
|
||||
modal.owning_source = source
|
||||
|
||||
// Previous one should get GC'd
|
||||
LAZYSET(GLOB.tgui_modals, source.UID(), modal)
|
||||
if(instant_update)
|
||||
SStgui.update_uis(source)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Calls the source's currently assigned modal's (if there is one) on_answer() proc. Private.
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * answer - The provided answer
|
||||
*/
|
||||
/datum/proc/tgui_modal_answer(datum/source = src, id, answer = "")
|
||||
ASSERT(istype(source))
|
||||
|
||||
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, source.UID())
|
||||
if(!current)
|
||||
return FALSE
|
||||
|
||||
return current.on_answer(answer)
|
||||
|
||||
/**
|
||||
* Passes an answer from JS through the modal's proc.
|
||||
*
|
||||
* Used namely for cutting the text short if it's longer
|
||||
* than an input modal's max_length.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * answer - The provided answer
|
||||
*/
|
||||
/datum/proc/tgui_modal_preprocess_answer(datum/source = src, answer = "")
|
||||
ASSERT(istype(source))
|
||||
|
||||
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, source.UID())
|
||||
if(!current)
|
||||
return answer
|
||||
|
||||
return current.preprocess_answer(answer)
|
||||
|
||||
/**
|
||||
* Modal datum (contains base information for a modal)
|
||||
*/
|
||||
/datum/tgui_modal
|
||||
var/datum/owning_source
|
||||
var/id
|
||||
var/text
|
||||
var/delegate
|
||||
var/list/arguments
|
||||
var/modal_type = "message"
|
||||
|
||||
/datum/tgui_modal/New(id, text, delegate, list/arguments)
|
||||
src.id = id
|
||||
src.text = text
|
||||
src.delegate = delegate
|
||||
src.arguments = arguments
|
||||
|
||||
/**
|
||||
* Called when it's time to pre-process the answer before using it
|
||||
*
|
||||
* Arguments:
|
||||
* * answer - The answer, a nullable text
|
||||
*/
|
||||
/datum/tgui_modal/proc/preprocess_answer(answer)
|
||||
return reject_bad_text(answer, TGUI_MODAL_INPUT_MAX_LENGTH) // bleh
|
||||
|
||||
/**
|
||||
* Called when a modal receives an answer
|
||||
*
|
||||
* Arguments:
|
||||
* * answer - The answer, a nullable text
|
||||
*/
|
||||
/datum/tgui_modal/proc/on_answer(answer)
|
||||
if(delegate)
|
||||
return call(owning_source, delegate)(answer, arguments)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Creates a list that describes a modal visually to be passed to JS
|
||||
*/
|
||||
/datum/tgui_modal/proc/to_data()
|
||||
. = list()
|
||||
.["id"] = id
|
||||
.["text"] = text
|
||||
.["args"] = arguments || list()
|
||||
.["type"] = modal_type
|
||||
|
||||
/**
|
||||
* Input modal - has a text entry that can be used to enter an answer
|
||||
*/
|
||||
/datum/tgui_modal/input
|
||||
modal_type = "input"
|
||||
var/value
|
||||
var/max_length
|
||||
|
||||
/datum/tgui_modal/input/New(id, text, delegate, list/arguments, value, max_length)
|
||||
..(id, text, delegate, arguments)
|
||||
src.value = value
|
||||
src.max_length = max_length
|
||||
|
||||
/datum/tgui_modal/input/preprocess_answer(answer)
|
||||
. = ..(answer)
|
||||
if(length(answer) > max_length)
|
||||
. = copytext(., 1, max_length + 1)
|
||||
|
||||
/datum/tgui_modal/input/to_data()
|
||||
. = ..()
|
||||
.["value"] = value
|
||||
|
||||
/**
|
||||
* Choice modal - has a dropdown menu that can be used to select an answer
|
||||
*/
|
||||
/datum/tgui_modal/input/choice
|
||||
modal_type = "choice"
|
||||
var/choices
|
||||
|
||||
/datum/tgui_modal/input/choice/New(id, text, delegate, list/arguments, value, choices)
|
||||
..(id, text, delegate, arguments, value, TGUI_MODAL_INPUT_MAX_LENGTH) // Max length doesn't really matter in dropdowns, but whatever
|
||||
src.choices = choices
|
||||
|
||||
/datum/tgui_modal/input/choice/on_answer(answer)
|
||||
if(answer in choices) // Make sure the answer is actually in our choices!
|
||||
return ..(answer, arguments)
|
||||
return FALSE
|
||||
|
||||
/datum/tgui_modal/input/choice/to_data()
|
||||
. = ..()
|
||||
.["choices"] = choices
|
||||
|
||||
/**
|
||||
* Bento modal - Similar to choice, it displays the choices in a grid of images
|
||||
*
|
||||
* The returned answer is the index of the choice.
|
||||
*/
|
||||
/datum/tgui_modal/input/bento
|
||||
modal_type = "bento"
|
||||
var/choices
|
||||
|
||||
/datum/tgui_modal/input/bento/New(id, text, delegate, list/arguments, value, choices)
|
||||
..(id, text, delegate, arguments, text2num(value), TGUI_MODAL_INPUT_MAX_LENGTH) // Max length doesn't really matter in here, but whatever
|
||||
src.choices = choices
|
||||
|
||||
/datum/tgui_modal/input/bento/preprocess_answer(answer)
|
||||
return text2num(answer) || 0
|
||||
|
||||
/datum/tgui_modal/input/bento/on_answer(answer)
|
||||
if(answer >= 1 && answer <= length(choices)) // Make sure the answer index is actually in our indexes!
|
||||
return ..(answer, arguments)
|
||||
return FALSE
|
||||
|
||||
/datum/tgui_modal/input/bento/to_data()
|
||||
. = ..()
|
||||
.["choices"] = choices
|
||||
|
||||
/**
|
||||
* Boolean modal - has yes/no buttons that do different actions depending on which is pressed
|
||||
*/
|
||||
/datum/tgui_modal/boolean
|
||||
modal_type = "boolean"
|
||||
var/delegate_no
|
||||
var/yes_text
|
||||
var/no_text
|
||||
|
||||
/datum/tgui_modal/boolean/New(id, text, delegate, delegate_no, list/arguments, yes_text, no_text)
|
||||
..(id, text, delegate, arguments)
|
||||
src.delegate_no = delegate_no
|
||||
src.yes_text = yes_text
|
||||
src.no_text = no_text
|
||||
|
||||
/datum/tgui_modal/boolean/preprocess_answer(answer)
|
||||
return text2num(answer) || FALSE
|
||||
|
||||
/datum/tgui_modal/boolean/on_answer(answer)
|
||||
if(answer)
|
||||
return ..(answer, arguments)
|
||||
else if(delegate_no)
|
||||
return call(owning_source, delegate_no)(arguments)
|
||||
return FALSE
|
||||
|
||||
/datum/tgui_modal/boolean/to_data()
|
||||
. = ..()
|
||||
.["yes_text"] = yes_text
|
||||
.["no_text"] = no_text
|
||||
@@ -0,0 +1,100 @@
|
||||
/datum/tgui_module/ert_manager
|
||||
name = "ERT Manager"
|
||||
var/ert_type = "Red"
|
||||
var/commander_slots = 1 // defaults for open slots
|
||||
var/security_slots = 4
|
||||
var/medical_slots = 0
|
||||
var/engineering_slots = 0
|
||||
var/janitor_slots = 0
|
||||
var/paranormal_slots = 0
|
||||
var/cyborg_slots = 0
|
||||
|
||||
/datum/tgui_module/ert_manager/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_admin_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ERTManager", name, 350, 430, master_ui, state)
|
||||
ui.autoupdate = TRUE
|
||||
ui.open()
|
||||
|
||||
/datum/tgui_module/ert_manager/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["str_security_level"] = capitalize(get_security_level())
|
||||
switch(GLOB.security_level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
data["security_level_color"] = "green"
|
||||
if(SEC_LEVEL_BLUE)
|
||||
data["security_level_color"] = "blue"
|
||||
if(SEC_LEVEL_RED)
|
||||
data["security_level_color"] = "red"
|
||||
else
|
||||
data["security_level_color"] = "purple"
|
||||
data["ert_type"] = ert_type
|
||||
data["com"] = commander_slots
|
||||
data["sec"] = security_slots
|
||||
data["med"] = medical_slots
|
||||
data["eng"] = engineering_slots
|
||||
data["jan"] = janitor_slots
|
||||
data["par"] = paranormal_slots
|
||||
data["cyb"] = cyborg_slots
|
||||
data["total"] = commander_slots + security_slots + medical_slots + engineering_slots + janitor_slots + paranormal_slots + cyborg_slots
|
||||
data["spawnpoints"] = GLOB.emergencyresponseteamspawn.len
|
||||
return data
|
||||
|
||||
/datum/tgui_module/ert_manager/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("ert_type")
|
||||
ert_type = params["ert_type"]
|
||||
if("toggle_com")
|
||||
commander_slots = commander_slots ? 0 : 1
|
||||
if("set_sec")
|
||||
security_slots = text2num(params["set_sec"])
|
||||
if("set_med")
|
||||
medical_slots = text2num(params["set_med"])
|
||||
if("set_eng")
|
||||
engineering_slots = text2num(params["set_eng"])
|
||||
if("set_jan")
|
||||
janitor_slots = text2num(params["set_jan"])
|
||||
if("set_par")
|
||||
paranormal_slots = text2num(params["set_par"])
|
||||
if("set_cyb")
|
||||
cyborg_slots = text2num(params["set_cyb"])
|
||||
if("dispatch_ert")
|
||||
var/datum/response_team/D
|
||||
switch(ert_type)
|
||||
if("Amber")
|
||||
D = new /datum/response_team/amber
|
||||
if("Red")
|
||||
D = new /datum/response_team/red
|
||||
if("Gamma")
|
||||
D = new /datum/response_team/gamma
|
||||
else
|
||||
to_chat(usr, "<span class='userdanger'>Invalid ERT type.</span>")
|
||||
return
|
||||
GLOB.ert_request_answered = TRUE
|
||||
var/slots_list = list()
|
||||
if(commander_slots > 0)
|
||||
slots_list += "commander: [commander_slots]"
|
||||
if(security_slots > 0)
|
||||
slots_list += "security: [security_slots]"
|
||||
if(medical_slots > 0)
|
||||
slots_list += "medical: [medical_slots]"
|
||||
if(engineering_slots > 0)
|
||||
slots_list += "engineering: [engineering_slots]"
|
||||
if(janitor_slots > 0)
|
||||
slots_list += "janitor: [janitor_slots]"
|
||||
if(paranormal_slots > 0)
|
||||
slots_list += "paranormal: [paranormal_slots]"
|
||||
if(cyborg_slots > 0)
|
||||
slots_list += "cyborg: [cyborg_slots]"
|
||||
var/slot_text = english_list(slots_list)
|
||||
notify_ghosts("An ERT is being dispatched. Open positions: [slot_text]")
|
||||
message_admins("[key_name_admin(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]", 1)
|
||||
log_admin("[key_name(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]")
|
||||
GLOB.event_announcement.Announce("Attention, [station_name()]. We are attempting to assemble an ERT. Standby.", "ERT Protocol Activated")
|
||||
trigger_armed_response_team(D, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
Reference in New Issue
Block a user