TGUI fixes, part 3 (#16560)

* a

* TGUI fixes part 3

* ugh

* bwuh

* ambiguous my ass

* AOAOAOAO

* pt 4

* extra foolproof

* a

* ok good thing i caught that

* enable that for AI

---------

Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: Werner <1331699+Arrow768@users.noreply.github.com>
This commit is contained in:
Matt Atlas
2023-06-27 23:33:21 +02:00
committed by GitHub
parent 06f8ced03b
commit e237808ea9
25 changed files with 259 additions and 178 deletions

View File

@@ -314,8 +314,8 @@
// This only works on 511 because it relies on 511's `var/something = foo = bar` syntax. // This only works on 511 because it relies on 511's `var/something = foo = bar` syntax.
#define WEAKREF(D) (istype(D, /datum) && !D:gcDestroyed ? (D:weakref || (D:weakref = new/datum/weakref(D))) : null) #define WEAKREF(D) (istype(D, /datum) && !D:gcDestroyed ? (D:weakref || (D:weakref = new/datum/weakref(D))) : null)
#define ADD_VERB_IN(the_atom,time,verb) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(add_verb), verb), time, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_NO_HASH_WAIT) #define ADD_VERB_IN(the_atom,time,verb) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(add_verb), the_atom, verb), time, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_NO_HASH_WAIT)
#define ADD_VERB_IN_IF(the_atom,time,verb,callback) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(add_verb), verb, callback), time, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_NO_HASH_WAIT) #define ADD_VERB_IN_IF(the_atom,time,verb,callback) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(add_verb), the_atom, verb, callback), time, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_NO_HASH_WAIT)
// Maploader bounds indices // Maploader bounds indices
#define MAP_MINX 1 #define MAP_MINX 1

View File

@@ -105,8 +105,8 @@
return return
..() ..()
/mob/living/silicon/ai/AltClickOn(var/atom/A) /mob/living/silicon/ai/AltClickOn(var/mob/living/silicon/user)
if(!control_disabled && A.AIAltClick(src)) if(!control_disabled && user.AIAltClick(src))
return return
/mob/living/silicon/ai/MiddleClickOn(var/atom/A) /mob/living/silicon/ai/MiddleClickOn(var/atom/A)
@@ -122,64 +122,55 @@
/atom/proc/AICtrlShiftClick() /atom/proc/AICtrlShiftClick()
return return
/atom/proc/AIShiftClick() /atom/proc/AIShiftClick(var/mob/user)
return return
/obj/machinery/door/airlock/AIShiftClick() // Opens and closes doors! /obj/machinery/door/airlock/AIShiftClick(var/mob/user) // Opens and closes doors!
if(density) open_interact(user, density)
Topic(src, list("command"="open", "activate" = "1")) return TRUE
else
Topic(src, list("command"="open", "activate" = "0"))
return 1
/atom/proc/AICtrlClick(mob/user) /atom/proc/AICtrlClick(mob/user)
return return
/obj/machinery/door/airlock/AICtrlClick(mob/user) // Bolts doors /obj/machinery/door/airlock/AICtrlClick(mob/user) // Bolts doors
var/command = player_is_antag(user.mind) ? "bolts_override" : "bolts" if(player_is_antag(user.mind))
if(locked) bolts_override(user, !locked, FALSE, player_is_antag(user.mind))
Topic(src, list("command"=command, "activate" = "0"))
else else
Topic(src, list("command"=command, "activate" = "1")) bolts_interact(user, !locked, FALSE, player_is_antag(user.mind))
return 1 return TRUE
/obj/machinery/power/apc/AICtrlClick() // turns off/on APCs. /obj/machinery/power/apc/AICtrlClick() // turns off/on APCs.
Topic(src, list("breaker"="1")) toggle_breaker()
return 1 return TRUE
/obj/machinery/turretid/AICtrlClick() //turns off/on Turrets /obj/machinery/turretid/AICtrlClick() //turns off/on Turrets
Topic(src, list("turret_ref" = "this", "command"="enable", "value"="[!enabled]")) enabled = !enabled
return 1 updateTurrets()
return TRUE
/atom/proc/AIAltClick(var/atom/A) /atom/proc/AIAltClick(var/mob/living/silicon/user)
return AltClick(A) return AltClick(user)
/obj/machinery/door/airlock/AIAltClick() // Electrifies doors. /obj/machinery/door/airlock/AIAltClick(var/mob/living/silicon/user) // Electrifies doors.
if(!electrified_until) var/antag = player_is_antag(user.mind)
// permanent shock if(!antag && (electrified_until == 0))
Topic(src, list("command"="electrify_permanently", "activate" = "1")) to_chat(user, SPAN_WARNING("Your programming prevents you from electrifying the door."))
return FALSE
else else
// disable/6 is not in Topic; disable/5 disables both temporary and permanent shock if(!electrified_until)
Topic(src, list("command"="electrify_permanently", "activate" = "0")) // permanent shock
return 1 electrify(-1, 1)
else
electrify(0)
return TRUE
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets /obj/machinery/turretid/AIAltClick(var/mob/living/silicon/user) //toggles lethal on turrets
Topic(src, list("turret_ref" = "this", "command"="lethal", "value"="[!lethal]")) lethal = !lethal
return 1 updateTurrets()
return TRUE
/atom/proc/AIMiddleClick(var/mob/living/silicon/user) /atom/proc/AIMiddleClick(var/mob/living/silicon/user)
return 0 return FALSE
/obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights.
if(..())
return
if(!src.lights)
Topic(src, list("command"="lights", "activate" = "1"))
else
Topic(src, list("command"="lights", "activate" = "0"))
return 1
// //
// Override AdjacentQuick for AltClicking // Override AdjacentQuick for AltClicking
// //

View File

@@ -111,42 +111,39 @@
if (doClickAction) if (doClickAction)
A.BorgAltClick(src) A.BorgAltClick(src)
/atom/proc/BorgCtrlShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden /atom/proc/BorgCtrlShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlShiftClick(user) CtrlShiftClick(user)
/obj/machinery/door/airlock/BorgCtrlShiftClick() /obj/machinery/door/airlock/BorgCtrlShiftClick(var/mob/living/silicon/robot/user)
AICtrlShiftClick() AICtrlShiftClick(user)
/atom/proc/BorgShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden /atom/proc/BorgShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
ShiftClick(user) ShiftClick(user)
/obj/machinery/door/airlock/BorgShiftClick() // Opens and closes doors! Forwards to AI code. /obj/machinery/door/airlock/BorgShiftClick(var/mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
AIShiftClick() AIShiftClick(user)
/atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden /atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlClick(user) CtrlClick(user)
/obj/machinery/door/airlock/BorgCtrlClick(mob/user) // Bolts doors. Forwards to AI code. /obj/machinery/door/airlock/BorgCtrlClick(var/mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
AICtrlClick(user) AICtrlClick(user)
/obj/machinery/power/apc/BorgCtrlClick() // turns off/on APCs. Forwards to AI code. /obj/machinery/power/apc/BorgCtrlClick(var/mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
AICtrlClick() AICtrlClick(user)
/obj/machinery/turretid/BorgCtrlClick() //turret control on/off. Forwards to AI code. /obj/machinery/turretid/BorgCtrlClick(var/mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
AICtrlClick() AICtrlClick(user)
/atom/proc/BorgAltClick(var/mob/living/silicon/robot/user) /atom/proc/BorgAltClick(var/mob/living/silicon/robot/user)
AltClick(user) AltClick(user)
return return
/obj/machinery/door/airlock/BorgAltClick() // Eletrifies doors. Forwards to AI code. /obj/machinery/door/airlock/BorgAltClick(var/mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
AIAltClick() AIAltClick(user)
/obj/machinery/turretid/BorgAltClick() //turret lethal on/off. Forwards to AI code. /obj/machinery/turretid/BorgAltClick(var/mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
AIAltClick() AIAltClick(user)
/* /*
As with AI, these are not used in click code, As with AI, these are not used in click code,
@@ -163,4 +160,4 @@
/atom/proc/attack_robot(mob/user) /atom/proc/attack_robot(mob/user)
attack_ai(user) attack_ai(user)
return return

View File

@@ -46,7 +46,7 @@
our_ui = null our_ui = null
/datum/late_choices/proc/update_character_icon() /datum/late_choices/proc/update_character_icon()
if(our_ui.status < UI_INTERACTIVE) if(our_ui && our_ui.status < UI_INTERACTIVE)
do_update_character_icon() do_update_character_icon()
else else
update_icon_on_next_open = TRUE update_icon_on_next_open = TRUE

View File

@@ -930,45 +930,9 @@ About the new airlock wires panel:
if(!backup_power_lost_until) if(!backup_power_lost_until)
src.loseBackupPower() src.loseBackupPower()
if("bolts") if("bolts")
if(isrobot(usr) && !Adjacent(usr)) bolts_interact(usr, activate, isAdmin, antag)
to_chat(usr, SPAN_WARNING("Your frame does not allow long distance wireless bolt control, you will need be adjacent the door."))
return
if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) // cut wire is noop
to_chat(usr, SPAN_WARNING("The door bolt control wire is cut - Door bolts permanently dropped."))
else if(isAdmin || issilicon(usr)) // controls for silicons, "stealthy" antag silicons and "stealthy" admins
if(!src.arePowerSystemsOn()) // cannot queue actions or "speak" from unpowered doors
to_chat(usr, SPAN_WARNING("The door is unpowered - Cannot [activate ? "drop" : "raise"] bolts."))
else if(!aiBolting)
to_chat(usr, SPAN_WARNING("The door is configured not to allow remote bolt operation."))
else if(!isnull(src.aiActionTimer))
to_chat(usr, SPAN_WARNING("An action is already queued. Please wait for it to complete."))
else if(activate)
to_chat(usr, SPAN_NOTICE("The door bolts should drop in [src.aiBoltingDelay] seconds."))
src.audible_message("[icon2html(src.icon, viewers(get_turf(src)))] <b>[src]</b> announces, <span class='notice'>\"Bolts set to drop in <strong>[src.aiBoltingDelay] seconds</strong>.\"</span>")
src.aiActionTimer = addtimer(CALLBACK(src, PROC_REF(lock)), src.aiBoltingDelay SECONDS, TIMER_UNIQUE|TIMER_NO_HASH_WAIT|TIMER_STOPPABLE)
else
to_chat(usr, SPAN_NOTICE("The door bolts should raise in [src.aiUnBoltingDelay] seconds."))
src.audible_message("[icon2html(src.icon, viewers(get_turf(src)))] <b>[src]</b> announces, <span class='notice'>\"Bolts set to raise in <strong>[src.aiUnBoltingDelay] seconds</strong>.\"</span>")
src.aiActionTimer = addtimer(CALLBACK(src, PROC_REF(unlock)), src.aiUnBoltingDelay SECONDS, TIMER_UNIQUE|TIMER_NO_HASH_WAIT|TIMER_STOPPABLE)
else // everyone else
if(activate)
if(src.lock())
to_chat(usr, SPAN_NOTICE("The door bolts have been dropped."))
else
if(src.unlock())
to_chat(usr, SPAN_NOTICE("The door bolts have been raised."))
if("bolts_override") if("bolts_override")
if(isAdmin || (issilicon(usr) && antag)) // admin and silicon antag can override bolts_override(usr, activate, antag)
if(!isAdmin && src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) // cut wire is noop, except for admins
to_chat(usr, SPAN_WARNING("The door bolt control wire is cut - Door bolts permanently dropped."))
else if(!isAdmin && !src.arePowerSystemsOn()) // door must be powered - display friendly message if not (admins can magically skip this)
to_chat(usr, SPAN_WARNING("The door is unpowered - Cannot [activate ? "drop" : "raise"] bolts."))
else if(activate)
if(src.lock())
to_chat(usr, SPAN_NOTICE("The door bolts have been dropped."))
else
if(src.unlock())
to_chat(usr, SPAN_NOTICE("The door bolts have been raised."))
if("electrify_temporary") if("electrify_temporary")
if(!isAdmin && issilicon(usr) && !antag) if(!isAdmin && issilicon(usr) && !antag)
to_chat(usr, SPAN_WARNING("Your programming prevents you from electrifying the door.")) to_chat(usr, SPAN_WARNING("Your programming prevents you from electrifying the door."))
@@ -980,18 +944,7 @@ About the new airlock wires panel:
else else
electrify(-1 * activate, 1) electrify(-1 * activate, 1)
if("open") if("open")
if(src.welded) open_interact(usr, activate)
to_chat(usr, SPAN_WARNING("The airlock has been welded shut!"))
else if(src.locked)
to_chat(usr, SPAN_WARNING("The door bolts are down!"))
else if(!src.arePowerSystemsOn() && issilicon(usr)) // AIs get a nice notice that the door is unpowered
to_chat(usr, SPAN_WARNING("The door is unpowered, its motors do not respond to your commands."))
else if(activate && density)
open()
if (isAI(usr))
SSfeedback.IncrementSimpleStat("AI_DOOR")
else if(!activate && !density)
close()
if("safeties") if("safeties")
if(!isAdmin && safe && issilicon(usr) && !antag) if(!isAdmin && safe && issilicon(usr) && !antag)
to_chat(usr, SPAN_WARNING("Your programming prevents you from disabling the door safeties.")) to_chat(usr, SPAN_WARNING("Your programming prevents you from disabling the door safeties."))
@@ -1018,6 +971,62 @@ About the new airlock wires panel:
update_icon() update_icon()
return TRUE return TRUE
/obj/machinery/door/airlock/proc/bolts_interact(var/mob/user, var/activate, var/isAdmin, var/antag)
if(isrobot(user) && !Adjacent(user))
to_chat(user, SPAN_WARNING("Your frame does not allow long distance wireless bolt control, you will need be adjacent the door."))
return
if(isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) // cut wire is noop
to_chat(user, SPAN_WARNING("The door bolt control wire is cut - Door bolts permanently dropped."))
else if(isAdmin || issilicon(user)) // controls for silicons, "stealthy" antag silicons and "stealthy" admins
if(!arePowerSystemsOn()) // cannot queue actions or "speak" from unpowered doors
to_chat(user, SPAN_WARNING("The door is unpowered - Cannot [activate ? "drop" : "raise"] bolts."))
else if(!aiBolting)
to_chat(user, SPAN_WARNING("The door is configured not to allow remote bolt operation."))
else if(!isnull(aiActionTimer))
to_chat(user, SPAN_WARNING("An action is already queued. Please wait for it to complete."))
else if(activate)
to_chat(user, SPAN_NOTICE("The door bolts should drop in [aiBoltingDelay] seconds."))
audible_message("[icon2html(icon, viewers(get_turf(src)))] <b>[src]</b> announces, <span class='notice'>\"Bolts set to drop in <strong>[aiBoltingDelay] seconds</strong>.\"</span>")
aiActionTimer = addtimer(CALLBACK(src, PROC_REF(lock)), aiBoltingDelay SECONDS, TIMER_UNIQUE|TIMER_NO_HASH_WAIT|TIMER_STOPPABLE)
else
to_chat(user, SPAN_NOTICE("The door bolts should raise in [aiUnBoltingDelay] seconds."))
audible_message("[icon2html(icon, viewers(get_turf(src)))] <b>[src]</b> announces, <span class='notice'>\"Bolts set to raise in <strong>[aiUnBoltingDelay] seconds</strong>.\"</span>")
aiActionTimer = addtimer(CALLBACK(src, PROC_REF(unlock)), aiUnBoltingDelay SECONDS, TIMER_UNIQUE|TIMER_NO_HASH_WAIT|TIMER_STOPPABLE)
else // everyone else
if(activate)
if(lock())
to_chat(user, SPAN_NOTICE("The door bolts have been dropped."))
else
if(unlock())
to_chat(user, SPAN_NOTICE("The door bolts have been raised."))
/obj/machinery/door/airlock/proc/bolts_override(var/mob/user, var/activate, var/isAdmin, var/antag)
if(isAdmin || (issilicon(user) && antag)) // admin and silicon antag can override
if(!isAdmin && src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) // cut wire is noop, except for admins
to_chat(user, SPAN_WARNING("The door bolt control wire is cut - Door bolts permanently dropped."))
else if(!isAdmin && !arePowerSystemsOn()) // door must be powered - display friendly message if not (admins can magically skip this)
to_chat(user, SPAN_WARNING("The door is unpowered - Cannot [activate ? "drop" : "raise"] bolts."))
else if(activate)
if(lock())
to_chat(user, SPAN_NOTICE("The door bolts have been dropped."))
else
if(unlock())
to_chat(user, SPAN_NOTICE("The door bolts have been raised."))
/obj/machinery/door/airlock/proc/open_interact(var/mob/user, var/activate)
if(welded)
to_chat(usr, SPAN_WARNING("The airlock has been welded shut!"))
else if(locked)
to_chat(usr, SPAN_WARNING("The door bolts are down!"))
else if(!arePowerSystemsOn() && issilicon(usr)) // AIs get a nice notice that the door is unpowered
to_chat(usr, SPAN_WARNING("The door is unpowered, its motors do not respond to your commands."))
else if(activate && density)
open()
if (isAI(usr))
SSfeedback.IncrementSimpleStat("AI_DOOR")
else if(!activate && !density)
close()
/obj/machinery/door/airlock/proc/hack(mob/user as mob) /obj/machinery/door/airlock/proc/hack(mob/user as mob)
if(src.aiHacking==0) if(src.aiHacking==0)
src.aiHacking=1 src.aiHacking=1

View File

@@ -132,7 +132,7 @@
/obj/machinery/turretid/ui_data(mob/user) /obj/machinery/turretid/ui_data(mob/user)
var/list/data = list() var/list/data = list()
data["turrets"] = list() data["turrets"] = list()
data["locked"] = locked data["locked"] = isAI(user) ? FALSE : locked
data["enabled"] = enabled data["enabled"] = enabled
data["is_lethal"] = TRUE data["is_lethal"] = TRUE
data["lethal"] = lethal data["lethal"] = lethal

View File

@@ -253,7 +253,7 @@
M.gestalt = src M.gestalt = src
add_verb(M, /mob/living/carbon/alien/diona/proc/merge_back_to_gestalt) add_verb(M, /mob/living/carbon/alien/diona/proc/merge_back_to_gestalt)
add_verb(M, /mob/living/carbon/alien/diona/proc/switch_to_gestalt) add_verb(M, /mob/living/carbon/alien/diona/proc/switch_to_gestalt)
add_verb(src, /mob/living/carbon/human/proc/switch_to_nymph) add_verb(M, /mob/living/carbon/human/proc/switch_to_nymph)
M.detached = TRUE M.detached = TRUE
M.update_verbs(TRUE) M.update_verbs(TRUE)
M.languages = languages.Copy() M.languages = languages.Copy()

View File

@@ -1,10 +1,11 @@
/mob/living /mob/living
var/datum/language/default_language var/datum/language/default_language
/mob/living/verb/set_default_language(language as null|anything in languages) /mob/living/verb/set_default_language()
set name = "Set Default Language" set name = "Set Default Language"
set category = "IC" set category = "IC"
var/datum/language/language = input(src, "Choose a language.", "Set Default Language") as null|anything in languages
if(language) if(language)
to_chat(src, "<span class='notice'>You will now speak [language] if you do not specify a language when speaking.</span>") to_chat(src, "<span class='notice'>You will now speak [language] if you do not specify a language when speaking.</span>")
else else

View File

@@ -294,13 +294,11 @@
if(next_alarm_notice && (world.time > next_alarm_notice)) if(next_alarm_notice && (world.time > next_alarm_notice))
next_alarm_notice = 0 next_alarm_notice = 0
var/alarm_raised = FALSE
for(var/datum/alarm_handler/AH in queued_alarms) for(var/datum/alarm_handler/AH in queued_alarms)
var/list/alarms = queued_alarms[AH] var/list/alarms = queued_alarms[AH]
var/reported = FALSE var/reported = FALSE
for(var/datum/alarm/A in alarms) for(var/datum/alarm/A in alarms)
if(alarms[A] == 1) if(alarms[A] == 1)
alarm_raised = TRUE
if(!reported) if(!reported)
reported = TRUE reported = TRUE
to_chat(src, SPAN_WARNING("--- [AH.category] Detected ---")) to_chat(src, SPAN_WARNING("--- [AH.category] Detected ---"))
@@ -316,9 +314,6 @@
to_chat(src, SPAN_NOTICE("--- [AH.category] Cleared ---")) to_chat(src, SPAN_NOTICE("--- [AH.category] Cleared ---"))
to_chat(src, "\The [A.alarm_name()].") to_chat(src, "\The [A.alarm_name()].")
if(alarm_raised)
to_chat(src, "<A HREF=?src=\ref[src];showalerts=1>\[Show Alerts\]</A>")
for(var/datum/alarm_handler/AH in queued_alarms) for(var/datum/alarm_handler/AH in queued_alarms)
var/list/alarms = queued_alarms[AH] var/list/alarms = queued_alarms[AH]
alarms.Cut() alarms.Cut()

View File

@@ -1250,8 +1250,9 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT)
/mob/proc/in_neck_grab() /mob/proc/in_neck_grab()
for(var/thing in grabbed_by) for(var/thing in grabbed_by)
var/obj/item/grab/G = thing var/obj/item/grab/G = thing
if(G.state >= GRAB_NECK) if(istype(G))
return TRUE if(G.state >= GRAB_NECK)
return TRUE
return FALSE return FALSE
/mob/get_cell() /mob/get_cell()

View File

@@ -78,13 +78,14 @@
for(var/datum/computer_file/program/P in hard_drive.stored_files) for(var/datum/computer_file/program/P in hard_drive.stored_files)
if(P.program_hidden()) if(P.program_hidden())
continue continue
data["programs"] += list(list( if(!istype(P, /datum/computer_file/program/scanner))
"filename" = P.filename, data["programs"] += list(list(
"desc" = P.filedesc, "filename" = P.filename,
"autorun" = istype(autorun) && (autorun.stored_data == P.filename), "desc" = P.filedesc,
"running" = (P in idle_threads) "autorun" = istype(autorun) && (autorun.stored_data == P.filename),
)) "running" = (P in idle_threads)
if(P.program_type & PROGRAM_SERVICE) ))
else
data["services"] += list(list( data["services"] += list(list(
"filename" = P.filename, "filename" = P.filename,
"desc" = P.filedesc, "desc" = P.filedesc,

View File

@@ -143,11 +143,11 @@
"focused" = (focused_conv == channel) "focused" = (focused_conv == channel)
) )
if(can_interact) if(can_interact)
our_channel["msg"] = channel.messages
our_channel["users"] = list() our_channel["users"] = list()
for(var/datum/ntnet_user/U in channel.users) for(var/datum/ntnet_user/U in channel.users)
var/uref = text_ref(U) var/uref = text_ref(U)
our_channel["users"] += list(list("ref" = uref, "username" = U.username)) our_channel["users"] += list(list("ref" = uref, "username" = U.username))
data["msg"] = channel.messages
data["channels"] += list(our_channel) data["channels"] += list(our_channel)
data["users"] = list() data["users"] = list()

View File

@@ -36,6 +36,7 @@
"wtype" = W.wtype "wtype" = W.wtype
)) ))
data["allwarrants"] = allwarrants data["allwarrants"] = allwarrants
data["active_warrant"] = null
return data return data
/datum/computer_file/program/digitalwarrant/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) /datum/computer_file/program/digitalwarrant/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)

View File

@@ -59,6 +59,8 @@
if(!category) if(!category)
category = "Alive" category = "Alive"
var/special_char = is_special_character(M) var/special_char = is_special_character(M)
if(!name)
continue
ghosts += list(list("name" = name, "ref" = ref(M), "category" = category, "special_character" = special_char)) ghosts += list(list("name" = name, "ref" = ref(M), "category" = category, "special_character" = special_char))
categories |= category categories |= category

View File

@@ -0,0 +1,51 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# wip (For works in progress)
# tweak
# soundadd
# sounddel
# rscadd (general adding of nice things)
# rscdel (general deleting of nice things)
# imageadd
# imagedel
# maptweak
# spellcheck (typo fixes)
# experiment
# balance
# admin
# backend
# security
# refactor
#################################
# Your name.
author: MattAtlas
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
changes:
- bugfix: "Chat client now updates properly."
- bugfix: "Synth altclick/shiftclick to interact with machines like APCs and doors works properly."
- bugfix: "Vampire verbs now return to the user properly."
- bugfix: "Fixed not being able to vote for crew transfer for real."
- bugfix: "Photocopiers now allow you to remove items."
- bugfix: "Fixed services like the med analyzer not working."
- bugfix: "Ghost spawner filters now work properly. They didn't work at all before..."
- bugfix: "You can now print all account data from the account database."
- bugfix: "Set default language verb now actually works."
- bugfix: "Fixed warrant assistant UI not updating when going back."
- bugfix: "Fixed Dionae not getting a switch to nymph verb when detaching one."

View File

@@ -74,7 +74,15 @@ export const AccountWindow = (props, context) => {
const [new_funds, setNewFunds] = useLocalState(context, 'new_funds', 0); const [new_funds, setNewFunds] = useLocalState(context, 'new_funds', 0);
return ( return (
<Section title="Idris Account Database"> <Section
title="Idris Account Database"
buttons={
<Button
content="Print All Data"
icon="print"
onClick={() => act('print')}
/>
}>
{active ? ( {active ? (
<Tabs> <Tabs>
<Tabs.Tab onClick={() => setTab('All Accounts')}> <Tabs.Tab onClick={() => setTab('All Accounts')}>

View File

@@ -12,6 +12,7 @@ export type ChatData = {
can_netadmin_mode: BooleanLike; can_netadmin_mode: BooleanLike;
message_mute: BooleanLike; message_mute: BooleanLike;
msg: string[];
channels: Channel[]; channels: Channel[];
users: User[]; users: User[];
}; };
@@ -24,7 +25,6 @@ type Channel = {
can_interact: BooleanLike; can_interact: BooleanLike;
can_manage: BooleanLike; can_manage: BooleanLike;
focused: BooleanLike; focused: BooleanLike;
msg: string[];
users: User[]; users: User[];
}; };
@@ -91,7 +91,7 @@ export const ChatClient = (props, context) => {
)} )}
</> </>
}> }>
{data.users.length ? <Users /> : 'There are no users.'} {data.users && data.users.length ? <Users /> : 'There are no users.'}
{!active ? <ChannelsWindow /> : ''} {!active ? <ChannelsWindow /> : ''}
</Section> </Section>
</NtosWindow.Content> </NtosWindow.Content>
@@ -270,7 +270,8 @@ export const Chat = (props, context) => {
</> </>
}> }>
{active && {active &&
active.msg.map((message) => ( data.msg &&
data.msg.map((message) => (
<Box <Box
key={message} key={message}
preserveWhitespace preserveWhitespace

View File

@@ -108,7 +108,7 @@ export const CommandCommunications = (props, context) => {
content="Change Alert Level" content="Change Alert Level"
icon="lightbulb" icon="lightbulb"
selected={choosingAlert} selected={choosingAlert}
disabled={data.isAI || !data.net_comms || !data.net_syscont} disabled={!data.net_comms || !data.net_syscont}
onClick={() => setChoosingAlert(!choosingAlert)} onClick={() => setChoosingAlert(!choosingAlert)}
/> />
{choosingAlert ? ( {choosingAlert ? (

View File

@@ -45,30 +45,32 @@ export const FollowMenu = (props, context) => {
{data.categories.sort().map((category) => ( {data.categories.sort().map((category) => (
<Section title={category} key={category}> <Section title={category} key={category}>
<Collapsible open={1}> <Collapsible open={1}>
{data.ghosts {data.ghosts &&
.filter( data.ghosts.length &&
(ghost) => data.ghosts
ghost.name .filter(
.toLowerCase() (ghost) =>
.indexOf(searchTerm.toLowerCase()) > -1 && ghost.name
category === ghost.category .toLowerCase()
) .indexOf(searchTerm.toLowerCase()) > -1 &&
.map((ghost) => ( category === ghost.category
<Button )
key={ghost.name} .map((ghost) => (
content={ghost.name} <Button
color={ key={ghost.name}
data.is_mod content={ghost.name}
? ghost.special_character > 0 color={
? 'bad' data.is_mod
? ghost.special_character > 0
? 'bad'
: ''
: '' : ''
: '' }
} onClick={() =>
onClick={() => act('follow_target', { follow_target: ghost.ref })
act('follow_target', { follow_target: ghost.ref }) }
} />
/> ))}
))}
</Collapsible> </Collapsible>
</Section> </Section>
))} ))}

View File

@@ -78,7 +78,7 @@ export const GhostSpawner = (props, context) => {
) )
.map( .map(
(spawner) => (spawner) =>
(spawner.tags.indexOf(tab) || tab === 'All') && ( (spawner.tags.indexOf(tab) > -1 || tab === 'All') && (
<Table.Row key={spawner.short_name}> <Table.Row key={spawner.short_name}>
<Table.Cell>{spawner.name}</Table.Cell> <Table.Cell>{spawner.name}</Table.Cell>
<Table.Cell>{spawner.desc}</Table.Cell> <Table.Cell>{spawner.desc}</Table.Cell>

View File

@@ -70,7 +70,11 @@ export const NTOSMain = (props, context) => {
content={service.desc} content={service.desc}
color="transparent" color="transparent"
selected={service.running} selected={service.running}
onClick={() => act('PC_toggleservice', service)} onClick={() =>
act('PC_toggleservice', {
service_to_toggle: service.filename,
})
}
/> />
</Table.Cell> </Table.Cell>
<Table.Cell collapsing> <Table.Cell collapsing>
@@ -80,7 +84,11 @@ export const NTOSMain = (props, context) => {
icon="times" icon="times"
tooltip="Disable Service" tooltip="Disable Service"
tooltipPosition="left" tooltipPosition="left"
onClick={() => act('PC_toggleservice', service)} onClick={() =>
act('PC_toggleservice', {
service_to_toggle: service.filename,
})
}
/> />
)} )}
</Table.Cell> </Table.Cell>

View File

@@ -24,7 +24,20 @@ export const Photocopier = (props, context) => {
<BlockQuote>No toner cartridge inserted.</BlockQuote> <BlockQuote>No toner cartridge inserted.</BlockQuote>
)} )}
</Section> </Section>
<Section title="Printing"> <Section
title="Printing"
buttons={
data.gotitem ? (
<Button
content="Remove"
color="red"
icon="times"
onClick={() => act('remove')}
/>
) : (
''
)
}>
{data.gotitem ? ( {data.gotitem ? (
<PrintOptions /> <PrintOptions />
) : ( ) : (

View File

@@ -82,7 +82,7 @@ export const StartVoteWindow = (props, context) => {
<Box> <Box>
<Button <Button
content="Crew Transfer" content="Crew Transfer"
disabled={data.allow_vote_restart} disabled={!data.allow_vote_restart}
tooltip="Disallowed on Code Red or above." tooltip="Disallowed on Code Red or above."
onClick={(value) => act('crew_transfer')} onClick={(value) => act('crew_transfer')}
/> />
@@ -90,7 +90,7 @@ export const StartVoteWindow = (props, context) => {
<Box> <Box>
<Button <Button
content="Toggle Restart / Crew Transfer Voting" content="Toggle Restart / Crew Transfer Voting"
disabled={!data.is_staff || !data.allow_vote_restart} disabled={!data.is_staff}
onClick={(value) => act('toggle_restart')} onClick={(value) => act('toggle_restart')}
/> />
</Box> </Box>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long