whitelist updates (#19288)

* whitelist updates

* migrate things to module

* .

* some more

* robot IDs are now handled by module

* special ids

* .

* .

* .

* .

* .

* .

* move that

* .

* initial

* admin whitelist TGUI

* .

* .

* lol
This commit is contained in:
Kashargul
2026-03-20 20:16:13 -04:00
committed by GitHub
parent a6b6ccb167
commit 418bc73c80
52 changed files with 742 additions and 378 deletions
+3 -3
View File
@@ -161,16 +161,16 @@ Once in open space, consider disabling nonessential power-consuming electronics
/mob/living/silicon/robot/drone/talon
foreign_droid = TRUE
idcard_type = /obj/item/card/id/synthetic/talon
module_type = /obj/item/robot_module/drone/talon
/obj/item/card/id/synthetic/talon
/obj/item/card/id/talon
name = "\improper Talon synthetic ID"
desc = "Access module for Talon synthetics"
icon_state = "id-robot"
item_state = "tdgreen"
assignment = "Talon synthetic"
/obj/item/card/id/synthetic/talon/Initialize(mapload)
/obj/item/card/id/talon/Initialize(mapload)
. = ..()
access = list(ACCESS_TALON, ACCESS_SYNTH)
+1
View File
@@ -101,6 +101,7 @@ _ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_categor
#define ADMIN_CATEGORY_SERVER "Server"
#define ADMIN_CATEGORY_SERVER_GAME "Server.Game"
#define ADMIN_CATEGORY_SERVER_ADMIN "Server.Admin"
#define ADMIN_CATEGORY_SERVER_CONFIG "Server.Config"
// Fun categories
#define ADMIN_CATEGORY_FUN_EVENT_KIT "Fun.Event Kit"
+6 -3
View File
@@ -52,10 +52,13 @@ GLOBAL_LIST_INIT(shell_module_types, list(
"Janitor", "Service", "Clown", "Clerical", "Security",
"Research", "Command" //"Exploration"
))
// List of modules available malf borgs
GLOBAL_LIST_INIT(malf_module_types, list("Lost", "Gravekeeper"))
// List of modules available toantags
GLOBAL_LIST_INIT(antag_module_types, list("Protector", "Mechanist", "Combat Medic", "Ninja"))
// List of whitelisted modules
GLOBAL_LIST_INIT(whitelisted_module_types, list(
"Lost"
))
GLOBAL_LIST_INIT(whitelisted_module_types, list("Combat", "Lost", "Gravekeeper", "Protector", "Mechanist", "Combat Medic", "Ninja"))
// Bomb cap!
GLOBAL_VAR_INIT(max_explosion_range, 14)
+2 -2
View File
@@ -1336,8 +1336,8 @@ GLOBAL_LIST_INIT(robot_modules, list(
"Exploration" = /obj/item/robot_module/robot/exploration,
"Engineering" = /obj/item/robot_module/robot/engineering,
"Janitor" = /obj/item/robot_module/robot/janitor,
"Gravekeeper" = /obj/item/robot_module/robot/gravekeeper,
"Lost" = /obj/item/robot_module/robot/lost,
"Gravekeeper" = /obj/item/robot_module/robot/malf/gravekeeper,
"Lost" = /obj/item/robot_module/robot/malf/lost,
"Protector" = /obj/item/robot_module/robot/syndicate/protector,
"Mechanist" = /obj/item/robot_module/robot/syndicate/mechanist,
"Combat Medic" = /obj/item/robot_module/robot/syndicate/combat_medic,
@@ -187,7 +187,7 @@
// Connect the cyborg to AI
target.connected_ai = user
user.connected_robots += target
target.lawupdate = 1
target.lawupdate = TRUE
target.sync()
target.show_laws()
user.hacking = 0
+144 -47
View File
@@ -1,14 +1,16 @@
#define WHITELISTFILE "data/whitelist.txt"
#define VALID_KINDS list("job", "species", "language", "robot")
GLOBAL_LIST_EMPTY(whitelist)
GLOBAL_LIST_EMPTY(job_whitelist)
GLOBAL_LIST_EMPTY(alien_whitelist)
GLOBAL_LIST_EMPTY(language_whitelist)
GLOBAL_LIST_EMPTY(robot_whitelist)
// Not yet implemented
//ADMIN_VERB(open_whitelist_editor, R_ADMIN, "Open Whitelist Editor", "Opens the editor for alien- and jobwhitelists.", ADMIN_CATEGORY_GAME)
// if(user.holder)
// user.holder.whitelist_editor = new /datum/whitelist_editor()
// user.holder.whitelist_editor.tgui_interact(user.mob)
ADMIN_VERB(open_whitelist_editor, R_ADMIN|R_SERVER, "Open Whitelist Editor", "Opens the editor for alien- and jobwhitelists.", ADMIN_CATEGORY_SERVER_CONFIG)
if(user.holder)
user.holder.whitelist_editor = new /datum/whitelist_editor()
user.holder.whitelist_editor.tgui_interact(user.mob)
/datum/whitelist_editor
@@ -22,17 +24,33 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
ui.open()
/datum/whitelist_editor/tgui_data(mob/user)
var/list/data = list()
data["alienwhitelist"] = GLOB.alien_whitelist
data["jobwhitelist"] = GLOB.job_whitelist
var/list/data = list(
"alienwhitelist" = GLOB.alien_whitelist,
"languagewhitelist" = GLOB.language_whitelist,
"robotwhitelist" = GLOB.robot_whitelist,
"jobwhitelist" = GLOB.job_whitelist
)
return data
/datum/whitelist_editor/tgui_static_data(mob/user)
var/list/data = list()
var/list/whitelist_jobs = list()
for(var/datum/job/our_job in GLOB.job_master.occupations)
if(our_job.whitelist_only)
whitelist_jobs += our_job.title
data["species_requiring_whitelist"] = GLOB.whitelisted_species
var/list/whitelisted_language = list()
for(var/language, value in GLOB.all_languages)
var/datum/language/current_lang = value
if(current_lang.flags & WHITELISTED)
whitelisted_language += language
var/list/data = list(
"species_with_whitelist" = GLOB.whitelisted_species,
"language_with_whitelist" = whitelisted_language,
"robot_with_whitelist" = GLOB.whitelisted_module_types,
"jobs_with_whitelist" = whitelist_jobs
)
return data
@@ -44,25 +62,94 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
switch(action)
if("add_alienwhitelist")
if (!CONFIG_GET(flag/sql_enabled))
to_chat(ui.user, "This action is not supported while the database is disabled. Please edit [global.config.directory]/alienwhitelist.txt.")
to_chat(ui.user, span_warning("This action is not supported while the database is disabled. Please edit [global.config.directory]/alienwhitelist.txt."))
return
// TODO: Add to database
. = TRUE
var/ckey = params["ckey"]
if(ckey != ckey(ckey))
to_chat(ui.user, span_warning("Error, invalid ckey. Did you enter the key?"))
return FALSE
var/kind = params["type"]
if(!(kind in VALID_KINDS))
to_chat(ui.user, span_warning("Error, invalid type entered."))
return FALSE
var/role = params["role"]
switch(kind)
if("job")
var/datum/job/job = GLOB.job_master.GetJob(role)
if(!job)
to_chat(ui.user, span_warning("Error, invalid job entered. Check spelling and capitalization."))
return FALSE
if(!job.whitelist_only)
to_chat(ui.user, span_warning("Error, job \"[role]\" is not a whitelist job."))
return FALSE
if("species")
if(!(role in GLOB.playable_species))
to_chat(ui.user, span_warning("Error, invalid species entered. Check spelling and capitalization."))
return FALSE
if(!(role in GLOB.whitelisted_species))
to_chat(ui.user, span_warning("Error, species \"[role]\" is not a whitelist species."))
return FALSE
if("language")
var/datum/language/chosen_language = GLOB.all_languages[role]
if(!chosen_language)
to_chat(ui.user, span_warning("Error, invalid language entered. Check spelling and capitalization."))
return FALSE
if(!(chosen_language.flags & WHITELISTED))
to_chat(ui.user, span_warning("Error, language \"[role]\" is not a whitelist language."))
return FALSE
if("robot")
if(!(role in GLOB.robot_modules))
to_chat(ui.user, span_warning("Error, invalid robot module entered. Check spelling and capitalization."))
return FALSE
if(!(role in GLOB.whitelisted_module_types))
to_chat(ui.user, span_warning("Error, robot module \"[role]\" is not a whitelist robot module."))
return FALSE
var/datum/db_query/command_add = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("whitelist")] (ckey, kind, entry) VALUES (:ckey, :kind, :entry)",
list("ckey" = ckey, "kind" = kind, "entry" = role)
)
if(!command_add.Execute())
log_sql("Error while trying to add [ckey] to the [role] [kind] whitelist.")
to_chat(ui.user, span_warning("Error while trying to add [ckey] to the [role] [kind] whitelist. Please review SQL logs."))
qdel(command_add)
return FALSE
qdel(command_add)
log_and_message_admins("added [ckey]'s [role] entry to [kind] whitelsit.", ui.user)
return TRUE
if("remove_alienwhitelist")
if (!CONFIG_GET(flag/sql_enabled))
to_chat(ui.user, "This action is not supported while the database is disabled. Please edit [global.config.directory]/alienwhitelist.txt.")
return
// TODO: Remove from database
. = TRUE
return FALSE
var/ckey = params["ckey"]
if(ckey != ckey(ckey))
to_chat(ui.user, span_warning("Error, invalid ckey. Did you enter the key?"))
return FALSE
var/kind = params["type"]
if(!(kind in VALID_KINDS))
to_chat(ui.user, span_warning("Error, invalid type entered."))
return FALSE
var/role = params["role"]
var/datum/db_query/command_remove = SSdbcore.NewQuery(
"DELETE FROM [format_table_name("whitelist")] WHERE ckey = :ckey AND kind = :kind AND entry = :entry",
list("ckey" = ckey, "kind" = kind, "entry" = role)
)
if(!command_remove.Execute())
log_sql("Error while trying to remove [ckey] from the [role] [kind] whitelist.")
to_chat(ui.user, span_warning("Error while trying to remove [ckey] from the [role] [kind] whitelist. Please review SQL logs."))
qdel(command_remove)
return FALSE
qdel(command_remove)
log_and_message_admins("removed [ckey]'s [role] entry from [kind] whitelsit.", ui.user)
return TRUE
if("reload_alienwhitelist")
reload_alienwhitelist()
. = TRUE
return TRUE
if("reload_jobwhitelist")
reload_jobwhitelist()
. = TRUE
return TRUE
/proc/load_whitelist()
GLOB.whitelist = world.file2list(WHITELISTFILE)
@@ -75,22 +162,24 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
/proc/load_alienwhitelist(dbfail = FALSE)
if (CONFIG_GET(flag/sql_enabled) && !dbfail)
var/datum/db_query/query_load_alienwhistelist = SSdbcore.NewQuery("SELECT ckey, entry FROM [format_table_name("whitelist")] WHERE kind = 'species'")
var/datum/db_query/query_load_alienwhistelist = SSdbcore.NewQuery("SELECT ckey, entry, kind FROM [format_table_name("whitelist")] WHERE kind IN ('species', 'language', 'robot')")
if(!query_load_alienwhistelist.Execute())
message_admins("Error loading alienwhitelist from database. Loading from [global.config.directory]/alienwhitelist.txt.")
log_sql("Error loading alienwhitelist from database. Loading from [global.config.directory]/alienwhitelist.txt.")
load_alienwhitelist(dbfail = TRUE)
qdel(query_load_alienwhistelist)
return
else
while(query_load_alienwhistelist.NextRow())
var/ckey = query_load_alienwhistelist.item[1]
var/entry = query_load_alienwhistelist.item[2]
while(query_load_alienwhistelist.NextRow())
var/ckey = query_load_alienwhistelist.item[1]
var/entry = query_load_alienwhistelist.item[2]
switch(query_load_alienwhistelist.item[3])
if("species")
LAZYADD(GLOB.alien_whitelist[ckey], entry)
if("language")
LAZYADD(GLOB.language_whitelist[ckey], entry)
if("robot")
LAZYADD(GLOB.robot_whitelist[ckey], entry)
var/list/our_whitelists = GLOB.alien_whitelist[ckey]
if(!our_whitelists) // Guess this is their first/only whitelist entry
our_whitelists = list()
GLOB.alien_whitelist[ckey] = our_whitelists
our_whitelists += entry
qdel(query_load_alienwhistelist)
else
var/text = file2text("[global.config.directory]/alienwhitelist.txt")
@@ -99,19 +188,25 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
else
var/lines = splittext(text, "\n") // Now we've got a bunch of "ckey = something" strings in a list
for(var/line in lines)
var/list/left_and_right = splittext(line, " - ") // Split it on the dash into left and right
if(LAZYLEN(left_and_right) != 2)
var/list/data_entry = splittext(line, " - ") // Split it on the dash into left and right
if(LAZYLEN(data_entry) != 3)
WARNING("Alien whitelist entry is invalid: [line]") // If we didn't end up with a left and right, the line is bad
continue
var/key = left_and_right[1]
var/key = data_entry[2]
if(key != ckey(key))
WARNING("Alien whitelist entry appears to have key, not ckey: [line]") // The key contains invalid ckey characters
continue
var/list/our_whitelists = GLOB.alien_whitelist[key] // Try to see if we have one already and add to it
if(!our_whitelists) // Guess this is their first/only whitelist entry
our_whitelists = list()
GLOB.alien_whitelist[key] = our_whitelists
our_whitelists += left_and_right[2]
var/type = data_entry[1]
switch(type)
if("species")
LAZYADD(GLOB.alien_whitelist[key], data_entry[3])
if("language")
LAZYADD(GLOB.language_whitelist[key], data_entry[3])
if("robot")
LAZYADD(GLOB.robot_whitelist[key], data_entry[3])
else
WARNING("Alien whitelist entry type is invalid: [line]")
return
#ifdef TESTING
var/msg = "Alienwhitelist Built:\n"
@@ -124,6 +219,8 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
/proc/reload_alienwhitelist()
GLOB.alien_whitelist.Cut()
GLOB.language_whitelist.Cut()
GLOB.robot_whitelist.Cut()
load_alienwhitelist()
/proc/is_alien_whitelisted(client/C, var/datum/species/species)
@@ -177,11 +274,11 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
for(var/line in lines)
var/list/left_and_right = splittext(line, " - ") // Split it on the dash into left and right
if(LAZYLEN(left_and_right) != 2)
warning("Alien whitelist entry is invalid: [line]") // If we didn't end up with a left and right, the line is bad
WARNING("Job whitelist entry is invalid: [line]") // If we didn't end up with a left and right, the line is bad
continue
var/key = left_and_right[1]
if(key != ckey(key))
warning("Alien whitelist entry appears to have key, not ckey: [line]") // The key contains invalid ckey characters
WARNING("Job whitelist entry appears to have key, not ckey: [line]") // The key contains invalid ckey characters
continue
var/list/our_whitelists = GLOB.job_whitelist[key] // Try to see if we have one already and add to it
if(!our_whitelists) // Guess this is their first/only whitelist entry
@@ -216,7 +313,7 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
var/list/our_whitelists = GLOB.job_whitelist[M.client.ckey]
if("All" in our_whitelists)
return TRUE
if(lowertext(rank) in our_whitelists)
if(rank in our_whitelists)
return TRUE
return FALSE
@@ -235,7 +332,7 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
return TRUE
//Search the whitelist
var/list/our_whitelists = GLOB.alien_whitelist[M.ckey]
var/list/our_whitelists = GLOB.language_whitelist[M.ckey]
if("All" in our_whitelists)
return TRUE
if(language.name in our_whitelists)
@@ -257,12 +354,11 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
return 1
//If we have a loaded file, search it
if(GLOB.alien_whitelist)
for (var/s in GLOB.alien_whitelist)
if(findtext(s,"[M.ckey] - [module]"))
return 1
if(findtext(s,"[M.ckey] - All"))
return 1
var/list/our_whitelists = GLOB.robot_whitelist[M.ckey]
if("All" in our_whitelists)
return TRUE
if(module in our_whitelists)
return TRUE
/proc/whitelist_overrides(client/C)
if(!CONFIG_GET(flag/usealienwhitelist))
@@ -277,3 +373,4 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
return FALSE
#undef WHITELISTFILE
#undef VALID_KINDS
+1 -1
View File
@@ -114,7 +114,7 @@
var/circuit = /obj/item/circuitboard/geiger
var/number = 0
var/last_tick //used to delay the powercheck
var/wiresexposed = 0
var/wiresexposed = FALSE
mounted = TRUE
/obj/item/geiger/wall/Initialize(mapload)
@@ -271,20 +271,18 @@
return
return
/obj/item/card/id/cargo/miner/borg
/obj/item/card/id/synthetic/borg
var/mob/living/silicon/robot/R
var/last_robot_loc
name = "Robot Miner ID"
rank = JOB_SHAFT_MINER
/obj/item/card/id/cargo/miner/borg/Initialize(mapload)
/obj/item/card/id/synthetic/borg/Initialize(mapload)
. = ..()
if(isrobot(loc?.loc))
R = loc.loc
registered_name = R.braintype
RegisterSignal(src, COMSIG_MOVABLE_ATTEMPTED_MOVE, PROC_REF(check_loc))
/obj/item/card/id/cargo/miner/borg/proc/check_loc(atom/movable/mover, atom/old_loc, atom/new_loc)
/obj/item/card/id/synthetic/borg/proc/check_loc(atom/movable/mover, atom/old_loc, atom/new_loc)
SIGNAL_HANDLER
if(old_loc == R || old_loc == R.module)
last_robot_loc = old_loc
@@ -297,7 +295,7 @@
if(loc == R)
hud_layerise()
/obj/item/card/id/cargo/miner/borg/Destroy()
/obj/item/card/id/synthetic/borg/Destroy()
if(R)
UnregisterSignal(src, COMSIG_MOVABLE_ATTEMPTED_MOVE)
R = null
@@ -295,39 +295,6 @@
initial_sprite_stack = list("base-stamp-silver", "top-olive", "stamp-n", "pips-white")
rank = JOB_PATHFINDER
/obj/item/card/id/exploration/borg
var/mob/living/silicon/robot/R
var/last_robot_loc
name = "Robot Exploration ID"
rank = JOB_EXPLORER
/obj/item/card/id/exploration/borg/Initialize(mapload)
. = ..()
if(isrobot(loc?.loc))
R = loc.loc
registered_name = R.braintype
RegisterSignal(src, COMSIG_MOVABLE_ATTEMPTED_MOVE, PROC_REF(check_loc))
/obj/item/card/id/exploration/borg/proc/check_loc(atom/movable/mover, atom/old_loc, atom/new_loc)
SIGNAL_HANDLER
if(old_loc == R || old_loc == R.module)
last_robot_loc = old_loc
if(!istype(loc, /obj/machinery) && loc != R && loc != R.module)
if(last_robot_loc)
forceMove(last_robot_loc)
last_robot_loc = null
else
forceMove(R)
if(loc == R)
hud_layerise()
/obj/item/card/id/exploration/borg/Destroy()
if(R)
UnregisterSignal(src, COMSIG_MOVABLE_ATTEMPTED_MOVE)
R = null
last_robot_loc = null
. = ..()
//Talon
/obj/item/card/id/talon
@@ -17,7 +17,7 @@
/obj/structure/ghost_pod/manual/lost_drone/create_occupant(var/mob/M)
density = FALSE
var/mob/living/silicon/robot/lost/randomlaws/R = new(get_turf(src))
var/mob/living/silicon/robot/malf/lost/randomlaws/R = new(get_turf(src))
R.adjustBruteLoss(rand(5, 30))
R.adjustFireLoss(rand(5, 10))
if(M.mind)
@@ -47,7 +47,7 @@
/obj/structure/ghost_pod/automatic/gravekeeper_drone/create_occupant(var/mob/M)
density = FALSE
var/mob/living/silicon/robot/gravekeeper/R = new(get_turf(src))
var/mob/living/silicon/robot/malf/gravekeeper/R = new(get_turf(src))
if(M.mind)
M.mind.transfer_to(R)
// Put this text here before ckey change so that their laws are shown below it, since borg login() shows it.
@@ -7,7 +7,7 @@
return ..()
else
density = FALSE
var/mob/living/silicon/robot/lost/randomlaws/vore/R = new(get_turf(src))
var/mob/living/silicon/robot/malf/lost/randomlaws/vore/R = new(get_turf(src))
R.adjustBruteLoss(rand(5, 30))
R.adjustFireLoss(rand(5, 10))
if(M.mind)
+20 -12
View File
@@ -67,14 +67,14 @@
.["target"]["active_restrictions"] = target.restrict_modules_to
var/list/possible_restrictions = list()
for(var/entry in GLOB.robot_modules)
if(!target.restrict_modules_to.Find(entry))
if(!(target.restrict_modules_to?.Find(entry)))
possible_restrictions += entry
.["target"]["possible_restrictions"] = possible_restrictions
// Target section for options once a module has been selected
if(target.module)
.["target"]["active"] = target.icon_selected
.["target"]["sprite"] = sanitize_css_class_name("[target.sprite_datum.type]")
.["target"]["sprite_size"] = spritesheet.icon_size_id(.["target"]["sprite"] + "S")
.["target"]["sprite_size"] = spritesheet?.icon_size_id(.["target"]["sprite"] + "S")
.["target"]["modules"] = get_target_items(user)
var/list/module_options = list()
for(var/module in GLOB.robot_modules)
@@ -185,10 +185,16 @@
target.crisis_override = !target.crisis_override
return TRUE
if("add_restriction")
target.restrict_modules_to |= params["new_restriction"]
var/new_restriction = params["new_restriction"]
if(!(new_restriction in GLOB.robot_modules))
return FALSE
LAZYOR(target.restrict_modules_to, new_restriction)
return TRUE
if("remove_restriction")
target.restrict_modules_to -= params["rem_restriction"]
var/rem_restriction = params["rem_restriction"]
if(!(rem_restriction in GLOB.robot_modules))
return FALSE
LAZYREMOVE(target.restrict_modules_to, rem_restriction)
return TRUE
if("select_source")
if(source)
@@ -196,13 +202,15 @@
var/module_type = GLOB.robot_modules[params["new_source"]]
if(ispath(module_type, /obj/item/robot_module/robot/syndicate))
source = new /mob/living/silicon/robot/syndicate(null)
else if(ispath(module_type, /obj/item/robot_module/robot/malf))
source = new /mob/living/silicon/robot/malf(null)
else
source = new /mob/living/silicon/robot(null)
source.modtype = params["new_source"]
var/obj/item/robot_module/robot/robot_type = new module_type(source)
source.sprite_datum = pick(SSrobot_sprites.get_module_sprites(source.modtype, source))
source.update_icon()
source.emag_items = 1
source.emag_items = TRUE
if(!istype(robot_type, /obj/item/robot_module/robot))
QDEL_NULL(source)
return TRUE
@@ -291,7 +299,7 @@
new module_type(source)
source.sprite_datum = target.sprite_datum
source.update_icon()
source.emag_items = 1
source.emag_items = TRUE
// Target
target.uneq_all()
target.hud_used?.update_robot_modules_display(TRUE)
@@ -599,25 +607,25 @@
if(!our_ai)
our_ai = select_active_ai_with_fewest_borgs()
if(our_ai)
target.lawupdate = 1
target.lawupdate = TRUE
target.connect_to_ai(our_ai)
return TRUE
if("disconnect_ai")
if(target.is_slaved())
target.disconnect_from_ai()
target.lawupdate = 0
target.lawupdate = FALSE
return TRUE
if("toggle_emag")
if(target.emagged)
target.emagged = 0
target.emagged = FALSE
target.clear_supplied_laws()
target.clear_inherent_laws()
target.laws = new using_map.default_law_type
to_chat(target, span_danger("Laws updated!\n") + target.laws.get_formatted_laws())
target.hud_used?.update_robot_modules_display()
else
target.emagged = 1
target.lawupdate = 0
target.emagged = TRUE
target.lawupdate = FALSE
target.disconnect_from_ai()
target.clear_supplied_laws()
target.clear_inherent_laws()
@@ -639,7 +647,7 @@
var/list/source_list = list()
source_list["model"] = source.module
source_list["sprite"] = sanitize_css_class_name("[source.sprite_datum.type]")
source_list["sprite_size"] = spritesheet.icon_size_id(source_list["sprite"] + "S")
source_list["sprite_size"] = spritesheet?.icon_size_id(source_list["sprite"] + "S")
var/list/source_items = list()
for(var/obj/item in (source.module.modules | source.module.emag))
var/exists
+4 -2
View File
@@ -85,7 +85,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
var/override_CPURate = 0 // Bonus/Penalty CPU generation rate. For use by admins/testers.
var/datum/ai_icon/selected_sprite // The selected icon set
var/custom_sprite = 0 // Whether the selected icon is custom
var/custom_sprite = FALSE // Whether the selected icon is custom
var/carded
// Multicam Vars
@@ -97,6 +97,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
var/max_multicams = 6
can_be_antagged = TRUE
var/idcard_type = /obj/item/card/id/synthetic
/mob/living/silicon/ai/proc/add_ai_verbs()
add_verb(src, GLOB.ai_verbs_default)
@@ -185,6 +186,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
GLOB.ai_list += src
. = ..()
init_id(idcard_type)
new /obj/machinery/ai_powersupply(src)
@@ -283,7 +285,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
if(Entry[1] == src.ckey && Entry[2] == src.real_name)
icon = CUSTOM_ITEM_SYNTH
custom_sprite = 1
custom_sprite = TRUE
selected_sprite = new/datum/ai_icon("Custom", "[src.ckey]-ai", "4", "[ckey]-ai-crash", "#FFFFFF", "#FFFFFF", "#FFFFFF")
else
selected_sprite = GLOB.default_ai_icon
+2 -1
View File
@@ -13,7 +13,7 @@
can_pull_size = ITEMSIZE_SMALL
can_pull_mobs = MOB_PULL_SMALLER
idcard_type = /obj/item/card/id
var/idcard_type = /obj/item/card/id
var/idaccessible = 0
var/network = "SS13"
@@ -105,6 +105,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////
/mob/living/silicon/pai/Initialize(mapload)
. = ..()
init_id(idcard_type)
card = loc
if(!istype(card))
@@ -29,7 +29,7 @@ GLOBAL_LIST_EMPTY(robot_custom_icons)
return
var/sprite_owner = GLOB.robot_custom_icons[sprite_name]
if(sprite_owner && sprite_owner == ckey)
custom_sprite = 1
custom_sprite = TRUE
icon = CUSTOM_ITEM_SYNTH
if(icon_state == "robot")
icon_state = "[ckey]-[sprite_name]-Standard" //Compliant with robot.dm line 236 ~Mech
@@ -32,7 +32,7 @@ GLOBAL_LIST_EMPTY(mob_hat_cache)
gender = NEUTER
pass_flags = PASSTABLE
braintype = "Drone"
lawupdate = 0
lawupdate = FALSE
density = TRUE
req_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
integrated_light_power = 3
@@ -276,8 +276,8 @@ GLOBAL_LIST_EMPTY(mob_hat_cache)
var/time = time2text(world.realtime,"hh:mm:ss")
GLOB.lawchanges.Add("[time] " + span_bold(":") + " [user.name]([user.key]) emagged [name]([key])")
emagged = 1
lawupdate = 0
emagged = TRUE
lawupdate = FALSE
connected_ai = null
clear_supplied_laws()
clear_inherent_laws()
@@ -359,7 +359,7 @@ GLOBAL_LIST_EMPTY(mob_hat_cache)
if(player.mob && player.mob.mind)
player.mob.mind.transfer_to(src)
lawupdate = 0
lawupdate = FALSE
to_chat(src, span_infoplain(span_bold("Systems rebooted") + " Loading base pattern maintenance protocol... " + span_bold("loaded") + "."))
full_law_reset()
welcome_drone()
@@ -13,12 +13,12 @@
gender = NEUTER
pass_flags = PASSTABLE
braintype = "Drone"
lawupdate = 0
lawupdate = FALSE
density = TRUE
idcard_type = /obj/item/card/id/syndicate
req_access = list(999)
integrated_light_power = 3
local_transmit = 0
can_pick_shell = FALSE
can_pull_size = ITEMSIZE_NO_CONTAINER
can_pull_mobs = MOB_PULL_SMALLER
@@ -54,13 +54,13 @@
if(lights_on)
cell_use_power(30) // 30W light. Normal lights would use ~15W, but increased for balance reasons.
has_power = 1
has_power = TRUE
else
if (has_power)
to_chat(src, span_red("You are now running on emergency backup power."))
has_power = 0
has_power = FALSE
if(lights_on) // Light is on but there is no power!
lights_on = 0
lights_on = FALSE
set_light(0)
/mob/living/silicon/robot/handle_regular_status_updates()
+31 -23
View File
@@ -15,13 +15,13 @@
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
var/lights_on = 0 // Is our integrated light on?
var/lights_on = FALSE // Is our integrated light on?
var/grabbable = FALSE //disables/enables pick-up mechanics.
var/robot_light_col = "#FFFFFF"
var/used_power_this_tick = 0
var/sight_mode = 0
var/custom_name = ""
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
var/custom_sprite = FALSE //Due to all the sprites involved, a var for our custom borgs may be best
var/sprite_name = null // The name of the borg, for the purposes of custom icon sprite indexing.
var/crisis //Admin-settable for combat module use.
var/crisis_override = 0
@@ -72,7 +72,7 @@
var/scrubbing = FALSE //Floor cleaning enabled
// Subtype limited modules or admin restrictions
var/list/restrict_modules_to = list()
var/list/restrict_modules_to
// Components are basically robot organs.
var/list/components = list()
@@ -81,12 +81,12 @@
var/obj/item/pda/ai/rbPDA = null
var/opened = 0
var/emagged = 0
var/emag_items = 0
var/wiresexposed = 0
var/locked = 1
var/has_power = 1
var/opened = FALSE
var/emagged = FALSE
var/emag_items = FALSE
var/wiresexposed = FALSE
var/locked = TRUE
var/has_power = TRUE
var/list/req_access = list(ACCESS_ROBOTICS)
var/ident = 0
//var/list/laws = list()
@@ -102,11 +102,11 @@
var/killswitch_time = 60
var/weapon_lock = 0
var/weaponlock_time = 120
var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default
var/lawupdate = TRUE //Cyborgs will sync their laws with their AI by default
var/lockcharge //Used when looking to see if a borg is locked down.
var/lockdown = 0 //Controls whether or not the borg is actually locked down.
var/speed = 0 //Cause sec borgs gotta go fast //No they dont!
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
var/scrambledcodes = FALSE // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
var/tracking_entities = 0 //The number of known entities currently accessing the internal camera
var/braintype = JOB_CYBORG
@@ -256,12 +256,10 @@
additional_law_channels["Binary"] = "#b"
var/new_ai = select_active_ai_with_fewest_borgs()
if(new_ai)
lawupdate = 1
lawupdate = TRUE
connect_to_ai(new_ai)
else
lawupdate = 0
lawupdate = FALSE
/mob/living/silicon/robot/SetName(pickedName as text)
custom_name = pickedName
@@ -375,7 +373,7 @@
if(new_sprites && new_sprites.len)
module_sprites = new_sprites.Copy()
//Custom_sprite check and entry
if (custom_sprite == 1)
if (custom_sprite)
module_sprites["Custom"] = "[ckey]-[sprite_name]-[modtype]" //Made compliant with custom_sprites.dm line 32. (src.) was apparently redundant as it's implied. ~Mech
icontype = "Custom"
else
@@ -851,8 +849,7 @@
hands.icon_state = get_hud_module_icon()
if(notify)
notify_ai(ROBOT_NOTIFICATION_MODULE_RESET, module.name)
module.Reset(src)
QDEL_NULL(module)
module.reset_module(src)
icon_selected = FALSE
updatename("Default")
has_recoloured = FALSE
@@ -1106,11 +1103,11 @@
/mob/living/silicon/robot/proc/UnlinkSelf()
disconnect_from_ai()
lawupdate = 0
lawupdate = FALSE
lockcharge = 0
lockdown = 0
canmove = 1
scrambledcodes = 1
scrambledcodes = TRUE
//Disconnect it's camera so it's not so easily tracked.
if(src.camera)
src.camera.clear_all_networks()
@@ -1261,7 +1258,7 @@
if(locked)
if(prob(90))
to_chat(user, span_filter_notice("You emag the cover lock."))
locked = 0
locked = FALSE
else
to_chat(user, span_filter_warning("You fail to emag the cover lock."))
to_chat(src, span_filter_warning("Hack attempt detected."))
@@ -1298,9 +1295,9 @@
sleep(6)
if(prob(50))
emagged = 1
emagged = TRUE
robotact.update_static_data_for_all_viewers()
lawupdate = 0
lawupdate = FALSE
disconnect_from_ai()
to_chat(user, span_filter_notice("You emag [src]'s interface."))
message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.")
@@ -1652,4 +1649,15 @@
/mob/living/silicon/robot/proc/get_ui_theme()
if(emagged)
return "syndicate"
if(module?.ui_theme)
return module.ui_theme
return ui_theme
/mob/living/silicon/robot/handle_special_unlocks()
if(!module)
return
module.handle_special_unlocks(src)
/mob/living/silicon/robot/proc/scramble_hardware(var/chance)
if(prob(chance)) //Small chance to spawn with a scrambled
emag_items = TRUE
@@ -1,11 +1,14 @@
/* Other, unaffiliated modules */
/obj/item/robot_module/robot/malf
hide_on_manifest = TRUE
ui_theme = "malfunction"
idcard_type = /obj/item/card/id/lost
// The module that borgs on the surface have. Generally has a lot of useful tools in exchange for questionable loyalty to the crew.
/obj/item/robot_module/robot/lost
/obj/item/robot_module/robot/malf/lost
name = "lost robot module"
hide_on_manifest = TRUE
/obj/item/robot_module/robot/lost/create_equipment(var/mob/living/silicon/robot/robot)
/obj/item/robot_module/robot/malf/lost/create_equipment(var/mob/living/silicon/robot/robot)
..()
// Sec
src.modules += new /obj/item/melee/robotic/baton/shocker(src)
@@ -36,16 +39,22 @@
src.modules += new /obj/item/dogborg/sleeper/lost(src)
src.modules += new /obj/item/dogborg/pounce(src)
/obj/item/robot_module/robot/lost/adjust_gps(obj/item/gps/robot/robot_gps)
/obj/item/robot_module/robot/malf/lost/adjust_gps(obj/item/gps/robot/robot_gps)
robot_gps.long_range = TRUE
robot_gps.hide_signal = TRUE
robot_gps.can_hide_signal = TRUE
/obj/item/robot_module/robot/gravekeeper
name = "gravekeeper robot module"
hide_on_manifest = TRUE
/obj/item/robot_module/robot/malf/lost/handle_special_unlocks(mob/living/silicon/robot/owner_robot)
if(!owner_robot.emag_items)
owner_robot.scramble_hardware(20)
if (owner_robot.churn_count == 5)
emag += new /obj/item/self_repair_system/advanced(src)
owner_robot.hud_used.update_robot_modules_display()
/obj/item/robot_module/robot/gravekeeper/create_equipment(var/mob/living/silicon/robot/robot)
/obj/item/robot_module/robot/malf/gravekeeper
name = "gravekeeper robot module"
/obj/item/robot_module/robot/malf/gravekeeper/create_equipment(var/mob/living/silicon/robot/robot)
..()
// For fending off animals and looters
src.modules += new /obj/item/melee/robotic/baton/shocker(src)
@@ -76,3 +85,10 @@
// For uwu
src.modules += new /obj/item/dogborg/sleeper/compactor/generic(src)
src.emag += new /obj/item/dogborg/pounce(src)
/obj/item/robot_module/robot/malf/gravekeeper/handle_special_unlocks(mob/living/silicon/robot/owner_robot)
if(!owner_robot.emag_items)
owner_robot.scramble_hardware(10)
if (owner_robot.churn_count == 5)
emag += new /obj/item/self_repair_system/advanced(src)
owner_robot.hud_used.update_robot_modules_display()
@@ -0,0 +1,2 @@
/obj/item/robot_module/proc/handle_special_unlocks()
return
@@ -34,6 +34,8 @@
// Bookkeeping
var/list/original_languages = list()
var/list/added_networks = list()
var/ui_theme
var/idcard_type = /obj/item/card/id/synthetic
/obj/item/robot_module/proc/hide_on_manifest()
. = hide_on_manifest
@@ -68,19 +70,25 @@
I.canremove = FALSE
/obj/item/robot_module/proc/create_equipment(var/mob/living/silicon/robot/robot)
robot.init_id(idcard_type)
return
/obj/item/robot_module/proc/Reset(var/mob/living/silicon/robot/R)
remove_camera_networks(R)
remove_languages(R)
remove_subsystems(R)
remove_status_flags(R)
// Reset the module and delete it
/obj/item/robot_module/proc/reset_module(var/mob/living/silicon/robot/robot)
remove_camera_networks(robot)
remove_languages(robot)
remove_subsystems(robot)
remove_status_flags(robot)
if(R.radio)
R.radio.recalculateChannels()
R.set_default_module_icon()
if(robot.radio)
robot.radio.recalculateChannels()
robot.set_default_module_icon()
R.scrubbing = FALSE
robot.scrubbing = FALSE
modules -= robot.idcard
QDEL_NULL(robot.idcard)
robot.module = null
qdel(src)
/obj/item/robot_module/Destroy()
QDEL_LIST(modules)
@@ -630,6 +638,7 @@
networks = list(NETWORK_MINE)
supported_upgrades = list(/obj/item/borg/upgrade/restricted/pka, /obj/item/borg/upgrade/restricted/diamonddrill, /obj/item/borg/upgrade/restricted/adv_scanner, /obj/item/borg/upgrade/restricted/adv_snatcher, /obj/item/borg/upgrade/restricted/adv_mailbag)
pto_type = PTO_CARGO
idcard_type = /obj/item/card/id/synthetic/borg
/obj/item/robot_module/robot/miner/create_equipment(var/mob/living/silicon/robot/robot)
..()
@@ -641,7 +650,13 @@
src.modules += new /obj/item/storage/bag/sheetsnatcher/borg(src)
src.modules += new /obj/item/gripper/miner(src)
src.modules += new /obj/item/mining_scanner/robot(src)
src.modules += new /obj/item/card/id/cargo/miner/borg(src)
var/obj/item/card/id/robot_id = robot.idcard
robot_id.name = "\improper Synthetic Miner ID"
robot_id.initial_sprite_stack = list("base-stamp", "top-brown", "stamp-n", "stripe-purple")
robot_id.reset_icon()
robot_id.forceMove(src)
src.modules += robot_id
src.modules += new /obj/item/mail_scanner(src)
src.modules += new /obj/item/storage/bag/mail/borg(src)
src.modules += new /obj/item/destTagger(src)
@@ -822,3 +837,9 @@
src.modules += new /obj/item/storage/bag/ore(src)
src.modules += new /obj/item/storage/bag/sheetsnatcher/borg(src)
src.emag += new /obj/item/pickaxe/diamonddrill(src)
/obj/item/robot_module/drone/talon
name = "talon drone module"
idcard_type = /obj/item/card/id/talon
channels = list(CHANNEL_TALON = 1)
networks = list(NETWORK_TALON_SHIP)
@@ -1,12 +1,14 @@
/obj/item/robot_module/drone/swarm
name = "swarm drone module"
var/id
var/obj/item/card/id/drone_id
idcard_type = /obj/item/card/id/syndicate
/obj/item/robot_module/drone/swarm/create_equipment(var/mob/living/silicon/robot/robot)
..()
id = robot.idcard
src.modules += id
var/obj/item/card/id/robot_id = robot.idcard
robot_id.forceMove(src)
src.modules += robot_id
src.modules += new /obj/item/rcd/electric/mounted/borg/swarm(src)
src.modules += new /obj/item/flash/robot(src)
@@ -18,7 +18,8 @@
LANGUAGE_TERMINUS = 1,
LANGUAGE_ZADDAT = 0
)
var/id
ui_theme = "syndicate"
idcard_type = /obj/item/card/id/syndicate
// All syndie modules get these, and the base borg items (flash, crowbar, etc).
/obj/item/robot_module/robot/syndicate/create_equipment(var/mob/living/silicon/robot/robot)
@@ -34,20 +35,15 @@
src.modules += jetpack
robot.internals = jetpack
var/obj/id = robot.idcard
id.forceMove(src)
src.modules += id
var/obj/item/card/id/robot_id = robot.idcard
robot_id.forceMove(src)
src.modules += robot_id
/obj/item/robot_module/robot/syndicate/adjust_gps(obj/item/gps/robot/robot_gps)
robot_gps.long_range = TRUE
robot_gps.hide_signal = TRUE
robot_gps.can_hide_signal = TRUE
/obj/item/robot_module/robot/syndicate/Destroy()
src.modules -= id
id = null
return ..()
// Gets a big shield and a gun that shoots really fast to scare the opposing force.
/obj/item/robot_module/robot/syndicate/protector
name = "protector robot module"
@@ -35,23 +35,27 @@
var/mob/living/silicon/robot/R = host
var/list/modules = list()
var/list/whitelisted = list()
if(R.module)
modules = list(R.modtype)
selected_module = R.modtype
else
if(LAZYLEN(R.restrict_modules_to) > 0)
modules.Add(R.restrict_modules_to)
if(LAZYLEN(R.restrict_modules_to))
modules += R.restrict_modules_to
else if(R.shell)
modules.Add(GLOB.shell_module_types)
modules += GLOB.shell_module_types
else
modules.Add(GLOB.robot_module_types)
modules += GLOB.robot_module_types
if(R.crisis || GLOB.security_level >= SEC_LEVEL_RED || R.crisis_override)
to_chat(R, span_red("Crisis mode active. Combat module available."))
modules |= GLOB.emergency_module_types
for(var/module_name in GLOB.whitelisted_module_types)
if(is_borg_whitelisted(R, module_name))
modules |= module_name
if(!(module_name in modules))
modules += module_name
whitelisted += module_name
data["possible_modules"] = modules
data["whitelisted_modules"] = whitelisted
data["mind_name"] = R.mind.name
data["theme"] = R.get_ui_theme()
@@ -107,12 +111,12 @@
switch(action)
if("pick_module")
if(R.module)
return
return FALSE
var/new_module = params["value"]
if(!(new_module in GLOB.robot_modules))
return
return FALSE
if(!is_borg_whitelisted(R, new_module))
return
return FALSE
selected_module = new_module
if(sprite_datum)
var/new_datum
@@ -122,30 +126,30 @@
new_datum = S
break
sprite_datum = new_datum
. = TRUE
return TRUE
if("pick_icon")
var/sprite = params["value"]
if(!sprite)
return
return FALSE
var/list/module_sprites = SSrobot_sprites.get_module_sprites(selected_module, R)
for(var/datum/robot_sprite/S in module_sprites)
if(S.name == sprite)
sprite_datum = S
break
. = TRUE
return TRUE
if("rename")
var/name = params["value"]
if(name)
new_name = sanitizeSafe(name, MAX_NAME_LEN)
R.sprite_name = new_name
. = TRUE
return TRUE
if("confirm")
R.apply_name(new_name)
R.apply_module(sprite_datum, selected_module)
R.update_multibelly()
R.transform_module()
close_ui()
. = TRUE
return TRUE
/mob/living/silicon/robot/proc/apply_name(var/new_name)
if(!custom_name)
@@ -20,6 +20,7 @@
/obj/item/robot_module/robot/exploration
can_be_pushed = 0
idcard_type = /obj/item/card/id/synthetic/borg
/obj/item/robot_module/robot/exploration/create_equipment(mob/living/silicon/robot/robot)
..()
@@ -32,6 +33,11 @@
src.modules += new /obj/item/shield_projector/line/exploborg(src)
src.modules += new /obj/item/roller_holder(src)
src.modules += new /obj/item/self_repair_system(src)
src.modules += new /obj/item/card/id/exploration/borg(src)
var/obj/item/card/id/robot_id = robot.idcard
robot_id.name = "\improper Synthetic Exploration ID"
robot_id.initial_sprite_stack = list("base-stamp", "top-olive", "stamp-n")
robot_id.reset_icon()
robot_id.forceMove(src)
src.emag += new /obj/item/melee/robotic/jaws/big/explojaws(src)
@@ -1,40 +1,10 @@
/mob/living/silicon/robot/gravekeeper
lawupdate = 0
scrambledcodes = 1
/mob/living/silicon/robot/malf/gravekeeper
icon_state = "drone-lost"
modtype = "Gravekeeper"
lawchannel = "State"
braintype = "Drone"
idcard_type = /obj/item/card/id/lost
icon_selected = FALSE
can_be_antagged = FALSE
restrict_modules_to = list("Gravekeeper")
ui_theme = "malfunction"
/mob/living/silicon/robot/gravekeeper/init()
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
mmi = new /obj/item/mmi/digital/robot(src) // Explicitly a drone.
module = new /obj/item/robot_module/robot/gravekeeper(src)
cut_overlays()
init_id()
updatename("Gravekeeper")
if(!cell)
cell = new /obj/item/cell/high(src) // 15k cell, as recharging stations are a lot more rare on the Surface.
/mob/living/silicon/robot/malf/gravekeeper/init()
..()
module = new /obj/item/robot_module/robot/malf/gravekeeper(src)
laws = new /datum/ai_laws/gravekeeper()
playsound(src, 'sound/mecha/nominalsyndi.ogg', 75, 0)
/mob/living/silicon/robot/gravekeeper/proc/scramble_hardware(var/chance)
if(prob(chance)) //Small chance to spawn with a scrambled
emag_items = 1
/mob/living/silicon/robot/gravekeeper/handle_special_unlocks()
if(!emag_items)
scramble_hardware(10)
if (churn_count == 5)
module.emag += new /obj/item/self_repair_system/advanced(module)
hud_used.update_robot_modules_display()
@@ -1,72 +1,49 @@
/mob/living/silicon/robot/lost
lawupdate = 0
scrambledcodes = 1
/mob/living/silicon/robot/malf/lost
icon_state = "drone-lost"
modtype = "Lost"
lawchannel = "State"
braintype = "Drone"
idcard_type = /obj/item/card/id/lost
icon_selected = FALSE
restrict_modules_to = list("Lost")
var/law_retries = 5
ui_theme = "malfunction"
/mob/living/silicon/robot/lost/init()
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
mmi = new /obj/item/mmi/digital/robot(src) // Explicitly a drone.
module = new /obj/item/robot_module/robot/lost(src)
cut_overlays()
init_id()
updatename("Lost")
if(!cell)
cell = new /obj/item/cell/high(src) // 15k cell, as recharging stations are a lot more rare on the Surface.
/mob/living/silicon/robot/malf/lost/init()
..()
module = new /obj/item/robot_module/robot/malf/lost(src)
scramble_hardware(20)
playsound(src, 'sound/mecha/nominalsyndi.ogg', 75, 0)
/mob/living/silicon/robot/lost/speech_bubble_appearance()
/mob/living/silicon/robot/malf/lost/speech_bubble_appearance()
return "synthetic_evil"
/mob/living/silicon/robot/lost/proc/scramble_hardware(var/chance)
if(prob(chance)) //Small chance to spawn with a scrambled
emag_items = 1
/mob/living/silicon/robot/lost/proc/apply_new_laws()
/mob/living/silicon/robot/malf/lost/proc/apply_new_laws()
return
/mob/living/silicon/robot/lost/randomlaws
/mob/living/silicon/robot/malf/lost/randomlaws
/mob/living/silicon/robot/lost/randomlaws/apply_new_laws()
/mob/living/silicon/robot/malf/lost/randomlaws/apply_new_laws()
var/old_name = laws?.name
laws = give_random_lawset()
if(old_name == laws.name)
apply_new_laws()
/mob/living/silicon/robot/lost/randomlaws/init()
/mob/living/silicon/robot/malf/lost/randomlaws/init()
..()
apply_new_laws()
/mob/living/silicon/robot/lost/randomlaws/vore
/mob/living/silicon/robot/malf/lost/randomlaws/vore
/mob/living/silicon/robot/lost/randomlaws/vore/apply_new_laws()
/mob/living/silicon/robot/malf/lost/randomlaws/vore/apply_new_laws()
var/old_name = laws?.name
laws = give_random_lawset_vore(100)
if(old_name == laws.name)
apply_new_laws()
/mob/living/silicon/robot/lost/randomlaws/mixed
/mob/living/silicon/robot/malf/lost/randomlaws/mixed
/mob/living/silicon/robot/lost/randomlaws/mixed/apply_new_laws()
/mob/living/silicon/robot/malf/lost/randomlaws/mixed/apply_new_laws()
var/old_name = laws?.name
laws = give_random_lawset_vore(60)
if(old_name == laws.name)
apply_new_laws()
/mob/living/silicon/robot/lost/randomlaws/repick_laws()
/mob/living/silicon/robot/malf/lost/randomlaws/repick_laws()
while(law_retries)
var/confirm = tgui_alert(src, "Do you want to keep your laws or reroll? (For specific laws, feel free to ahelp and we'll see what we can do)", "Confirm laws", list("Keep", "Reroll ([law_retries])"))
if(findtext(confirm, regex("Reroll \\(\[0-9\]*\\)", "")))
@@ -180,7 +157,7 @@
return
/mob/living/silicon/proc/give_random_lawset_vore(var/vore_chance = 100)
/mob/living/silicon/proc/give_random_lawset_vore(vore_chance = 100)
// Decide what kind of laws we want to draw from.
var/law_class = pick(
prob(25);"good",
@@ -332,12 +309,3 @@
return new /datum/ai_laws/foreign_tsc_aggressive()
if(5) // Manicial laugher here.
return new /datum/ai_laws/tyrant()
return
/mob/living/silicon/robot/lost/handle_special_unlocks()
if(!emag_items)
scramble_hardware(20)
if (churn_count == 5)
module.emag += new /obj/item/self_repair_system/advanced(module)
hud_used.update_robot_modules_display()
@@ -0,0 +1,22 @@
/mob/living/silicon/robot/malf
lawupdate = FALSE
scrambledcodes = TRUE
modtype = "Malf"
lawchannel = "State"
braintype = "Drone"
ui_theme = "malfunction"
/mob/living/silicon/robot/malf/init()
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
if(!restrict_modules_to)
restrict_modules_to = GLOB.malf_module_types
mmi = new /obj/item/mmi/digital/robot(src) // Explicitly a drone.
updatename(modtype)
if(!cell)
cell = new /obj/item/cell/high(src) // 15k cell, as recharging stations are a lot more rare on the Surface.
playsound(src, 'sound/mecha/nominalsyndi.ogg', 75, 0)
@@ -1,23 +1,20 @@
/mob/living/silicon/robot/syndicate
lawupdate = 0
scrambledcodes = 1
emagged = 1
lawupdate = FALSE
scrambledcodes = TRUE
emagged = TRUE
modtype = "Syndicate"
lawchannel = "State"
braintype = "Drone"
idcard_type = /obj/item/card/id/syndicate
icon_selected = FALSE
restrict_modules_to = list("Protector", "Mechanist", "Combat Medic", "Ninja")
ui_theme = "syndicate"
/mob/living/silicon/robot/syndicate/init()
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
if(!restrict_modules_to)
restrict_modules_to = GLOB.antag_module_types
mmi = new /obj/item/mmi/digital/robot(src) // Explicitly a drone.
cut_overlays()
init_id()
updatename("Syndicate")
updatename(modtype)
if(!cell)
cell = new /obj/item/cell/robot_syndi(src) // 25k cell, because Antag.
@@ -36,28 +33,24 @@
module = new /obj/item/robot_module/robot/syndicate/protector(src)
modtype = "Protector"
restrict_modules_to = list("Protector")
updatename("Protector")
/mob/living/silicon/robot/syndicate/mechanist/init()
..()
module = new /obj/item/robot_module/robot/syndicate/mechanist(src)
modtype = "Mechanist"
restrict_modules_to = list("Mechanist")
updatename("Mechanist")
/mob/living/silicon/robot/syndicate/combat_medic/init()
..()
module = new /obj/item/robot_module/robot/syndicate/combat_medic(src)
modtype = "Combat Medic"
restrict_modules_to = list("Combat Medic")
updatename("Combat Medic")
/mob/living/silicon/robot/syndicate/ninja/init()
..()
module = new /obj/item/robot_module/robot/syndicate/ninja(src)
modtype = "Ninja"
restrict_modules_to = list("Ninja")
updatename("Ninja")
/mob/living/silicon/robot/syndicate/speech_bubble_appearance()
return "synthetic_evil"
@@ -21,7 +21,6 @@
color = "#68a2f2"
cell = /obj/item/cell/mech
idcard_type = /obj/item/card/id/platform
module = /obj/item/robot_module/robot/platform
lawupdate = FALSE
@@ -14,6 +14,7 @@
"Stripe" = "stripe",
"Vertical Stripe" = "stripe_vertical"
)
idcard_type = /obj/item/card/id/platform
// Only show on manifest if they have a player.
/obj/item/robot_module/robot/platform/hide_on_manifest()
+3 -3
View File
@@ -23,7 +23,6 @@
var/list/access_rights
var/obj/item/card/id/idcard
var/idcard_type = /obj/item/card/id/synthetic
var/sensor_type = 0 //VOREStation add - silicon omni "is sensor on or nah"
@@ -36,7 +35,6 @@
if(!is_decoy)
add_language(LANGUAGE_GALCOM)
apply_default_language(GLOB.all_languages[LANGUAGE_GALCOM])
init_id()
init_subsystems()
AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE, 1, -6)
@@ -55,7 +53,9 @@
clear_subsystems()
return ..()
/mob/living/silicon/proc/init_id()
/mob/living/silicon/proc/init_id(idcard_type)
if(!idcard_type)
return
if(idcard)
return
idcard = new idcard_type(src)
+4 -4
View File
@@ -130,7 +130,7 @@ GLOBAL_LIST_EMPTY(apcs)
var/lastused_total = 0
var/main_status = APC_EXTERNAL_POWER_NOTCONNECTED
var/mob/living/silicon/ai/hacker = null // Malfunction var. If set AI hacked the APC and has full control.
var/wiresexposed = 0
var/wiresexposed = FALSE
powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :(
var/debug= 0
var/autoflag= 0 // 0 = off, 1= eqp and lights off, 2 = eqp off, 3 = all on.
@@ -742,12 +742,12 @@ GLOBAL_LIST_EMPTY(apcs)
var/allcut = wires.is_all_cut()
if(beenhit >= pick(3, 4) && wiresexposed != 1)
wiresexposed = 1
if(beenhit >= pick(3, 4) && !wiresexposed)
wiresexposed = TRUE
update_icon()
visible_message(span_warning("The [name]'s cover flies open, exposing the wires!"))
else if(wiresexposed == 1 && allcut == 0)
else if(wiresexposed && allcut == 0)
wires.cut_all()
update_icon()
visible_message(span_warning("The [name]'s wires are shredded!"))
+60 -45
View File
@@ -381,11 +381,11 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
return "Smite [smite_name] sent!"
#define VALID_ACTIONS list("add", "remove", "list", "help")
#define VALID_KINDS list("job", "species")
#define VALID_KINDS list("job", "species", "language", "robot")
#define VALID_USAGE "whitelist \[[list2text(VALID_ACTIONS, ", ")]\] \[[list2text(VALID_KINDS, ", ")]\] <ckey> (role)"
/datum/tgs_chat_command/whitelist
name = "whitelist"
help_text = "allows the management of player whitelists.\nUsage: whitelist \[add, remove, list\] \[job, species\] <ckey> (role)"
help_text = "allows the management of player whitelists.\nUsage: whitelist \[add, remove, list\] \[job, species, language, robot\] <ckey> (role)"
admin_only = TRUE
/datum/tgs_chat_command/whitelist/Run(datum/tgs_chat_user/sender, params)
@@ -411,7 +411,12 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
for(var/datum/job/our_job in GLOB.job_master.occupations)
if(our_job.whitelist_only)
whitelist_jobs += our_job.title
message.text = "The following jobs and species have a whitelist:\nJobs: [english_list(whitelist_jobs)]\nSpecies: [english_list(GLOB.whitelisted_species)]"
var/list/whitelisted_language = list()
for(var/language, value in GLOB.all_languages)
var/datum/language/current_lang = value
if(current_lang.flags & WHITELISTED)
whitelisted_language += language
message.text = "The following jobs and species have a whitelist:\nJobs: [english_list(whitelist_jobs)]\nSpecies: [english_list(GLOB.whitelisted_species)]\nLanguages: [english_list(whitelisted_language)]\nRobot Modules: [english_list(GLOB.whitelisted_module_types)]"
return message
message_as_list.Cut(1, 2)
@@ -429,7 +434,7 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
return message
var/ckey = message_as_list[1]
if(!istext(ckey))
if(ckey != ckey(ckey))
message.text = "```Third param must be a valid ckey.```"
return message
@@ -449,21 +454,37 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
// Resolve the action
switch(action)
if("add")
if(kind == "job")
var/datum/job/job = GLOB.job_master.GetJob(role)
if(!job)
message.text = "Error, invalid job entered. Check spelling and capitalization."
return message
if(!job.whitelist_only)
message.text = "Error, job \"[role]\" is not a whitelist job."
return message
if(kind == "species")
if(!(role in GLOB.playable_species))
message.text = "Error, invalid species entered. Check spelling and capitalization."
return message
if(!(role in GLOB.whitelisted_species))
message.text = "Error, species \"[role]\" is not a whitelist species."
return message
switch(kind)
if("job")
var/datum/job/job = GLOB.job_master.GetJob(role)
if(!job)
message.text = "Error, invalid job entered. Check spelling and capitalization."
return message
if(!job.whitelist_only)
message.text = "Error, job \"[role]\" is not a whitelist job."
return message
if("species")
if(!(role in GLOB.playable_species))
message.text = "Error, invalid species entered. Check spelling and capitalization."
return message
if(!(role in GLOB.whitelisted_species))
message.text = "Error, species \"[role]\" is not a whitelist species."
return message
if("language")
var/datum/language/chosen_language = GLOB.all_languages[role]
if(!chosen_language)
message.text = "Error, invalid language entered. Check spelling and capitalization."
return message
if(!(chosen_language.flags & WHITELISTED))
message.text = "Error, language \"[role]\" is not a whitelist language."
return message
if("robot")
if(!(role in GLOB.robot_modules))
message.text = "Error, invalid robot module entered. Check spelling and capitalization."
return message
if(!(role in GLOB.whitelisted_module_types))
message.text = "Error, robot module \"[role]\" is not a whitelist robot module."
return message
var/datum/db_query/command_add = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("whitelist")] (ckey, kind, entry) VALUES (:ckey, :kind, :entry)",
@@ -476,21 +497,18 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
return message
qdel(command_add)
var/list/our_whitelists
if(kind == "job")
our_whitelists = GLOB.job_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.job_whitelist[ckey] = our_whitelists
switch(kind)
if("job")
LAZYOR(GLOB.job_whitelist[ckey], role)
if(kind == "species")
our_whitelists = GLOB.alien_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.alien_whitelist[ckey] = our_whitelists
if("species")
LAZYOR(GLOB.alien_whitelist[ckey], role)
if(our_whitelists)
our_whitelists |= role
if("language")
LAZYOR(GLOB.language_whitelist[ckey], role)
if("robot")
LAZYOR(GLOB.robot_whitelist[ckey], role)
if("remove")
var/datum/db_query/command_remove = SSdbcore.NewQuery(
@@ -504,21 +522,18 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
return message
qdel(command_remove)
var/list/our_whitelists
if(kind == "job")
our_whitelists = GLOB.job_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.job_whitelist[ckey] = our_whitelists
switch(kind)
if("job")
LAZYREMOVE(GLOB.job_whitelist[ckey], role)
if(kind == "species")
our_whitelists = GLOB.alien_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.alien_whitelist[ckey] = our_whitelists
if("species")
LAZYREMOVE(GLOB.alien_whitelist[ckey], role)
if(our_whitelists && (role in our_whitelists))
our_whitelists -= role
if("language")
LAZYREMOVE(GLOB.language_whitelist[ckey], role)
if("robot")
LAZYREMOVE(GLOB.robot_whitelist[ckey], role)
// Listing all whitelists for a specific ckey
if("list")
+1 -1
View File
@@ -1 +1 @@
some~user - Species
species - some~user - Species
+1 -1
View File
@@ -281,7 +281,7 @@ personally I recommend using the ship's boat if you need to evacuate, but if you
/mob/living/silicon/robot/drone/talon
foreign_droid = TRUE
idcard_type = /obj/item/card/id/synthetic/talon
module_type = /obj/item/robot_module/drone/talon
/obj/item/card/id/synthetic/talon
name = "\improper Talon synthetic ID"
+9 -10
View File
@@ -114,8 +114,7 @@ recommend getting yourself introduced to
A React component is not a regular HTML template. A component is a
javascript function, which accepts a `props` object (that contains
properties passed to a component) and a `context` object (which is
necessary to access UI data) as arguments, and outputs an HTML-like
properties passed to a component) and outputs an HTML-like
structure.
So let's create our first React Component. Create a file with a name
@@ -127,8 +126,8 @@ import { useBackend } from 'tgui/backend';
import { Button, LabeledList, Section } from 'tgui-core/components';
import { Window } from 'tgui/layouts';
export const SampleInterface = (props, context) => {
const { act, data } = useBackend(context);
export const SampleInterface = (props) => {
const { act, data } = useBackend();
// Extract `health` and `color` variables from the `data` object.
const { health, color } = data;
return (
@@ -152,7 +151,7 @@ export const SampleInterface = (props, context) => {
};
```
Here are the key variables you get from a `useBackend(context)` function:
Here are the key variables you get from a `useBackend()` function:
- `config` is part of core tgui. It contains meta-information about the
interface and who uses it, BYOND refs to various objects, and so forth.
@@ -249,7 +248,7 @@ import { useBackend } from 'tgui/backend';
import { Button, LabeledList, Section } from 'tgui-core/components';
import { Window } from 'tgui/layouts';
export const SampleInterface = (props, context) => {
export const SampleInterface = (props) => {
return (
<Window resizable>
<Window.Content scrollable>
@@ -259,8 +258,8 @@ export const SampleInterface = (props, context) => {
);
};
const HealthStatus = (props, context) => {
const { act, data } = useBackend(context);
const HealthStatus = (props) => {
const { act, data } = useBackend();
const { user } = props;
const { health, color } = data;
return (
@@ -311,8 +310,8 @@ import { useBackend } from 'tgui/backend';
import { Button, LabeledList, Section } from 'tgui-core/components';
import { Window } from 'tgui/layouts';
export const SampleInterface = (props, context) => {
const { act, data } = useBackend(context);
export const SampleInterface = (props) => {
const { act, data } = useBackend();
// Extract `health` and `color` variables from the `data` object.
const { health, color } = data;
return (
@@ -45,7 +45,7 @@ export const ModifyRobotNoModule = (props: { target: Target }) => {
<Section fill scrollable title="Active Restrictions">
<Stack fill>
<Stack.Item fillPositionedParent>
{target.active_restrictions.map((active_restriction, i) => {
{target.active_restrictions?.map((active_restriction, i) => {
return (
<Button
fluid
@@ -124,8 +124,8 @@ export const ModifyRobotModules = (props: {
};
const SelectionField = (props: {
previewImage: string | undefined;
previewImageSize: string | undefined;
previewImage?: string;
previewImageSize?: string | null;
searchText: string;
onSearchText: React.Dispatch<React.SetStateAction<string>>;
action: string;
@@ -15,7 +15,7 @@ export type Data = {
armour_options: Record<string, Comp>;
current_gear: Record<string, string>;
id_icon: string;
access_options: Access[] | undefined;
access_options?: Access[];
ion_law_nr: string;
ion_law: string;
zeroth_law: string;
@@ -53,10 +53,10 @@ export type Target = {
emagged: BooleanLike;
active: BooleanLike;
crisis_override: BooleanLike;
active_restrictions: string[];
active_restrictions?: string[];
possible_restrictions: string[];
sprite: string | undefined;
sprite_size: string | undefined;
sprite?: string;
sprite_size?: string | null;
modules: Module[];
whitelisted_upgrades: Upgrade[];
blacklisted_upgrades: Upgrade[];
@@ -66,8 +66,8 @@ export type Target = {
restricted_upgrades: Upgrade[];
radio_channels: string[];
availalbe_channels: string[];
pka: PKA | undefined;
multibelt: Multibelt[] | undefined;
pka?: PKA;
multibelt?: Multibelt[];
components: Component[];
active_access: Access[];
};
@@ -75,13 +75,13 @@ export type Target = {
export type Upgrade = {
name: string;
path: string;
installed: number | undefined;
installed?: number;
};
export type Source = {
model: string;
sprite: string | undefined;
sprite_size: string | undefined;
sprite?: string;
sprite_size?: string | null;
modules: Module[];
} | null;
@@ -149,8 +149,8 @@ export type Access = { id: number; name: string };
export type Lookup = {
path: string;
selected: string | undefined;
active: string | undefined;
selected?: string;
active?: string;
};
type law_pack = {
@@ -64,7 +64,9 @@ export const SpriteSection = (props) => {
option={filter.sprite}
action="pick_icon"
selected={selected_chassis ?? pai_chassis}
belly={filter.belly}
icon={filter.belly ? 'utensils' : undefined}
iconColor="lightgray"
iconTooltip={'Module has belly sprite.'}
/>
))}
</Stack>
@@ -7,9 +7,10 @@ import { SelectorElement } from './SelectorElement';
export const ModuleSection = (props: {
title: string;
sortable?: string[];
highlighted?: string[];
selected?: string;
}) => {
const { title, sortable, selected } = props;
const { title, sortable, highlighted, selected } = props;
const [searchText, setSearchText] = useState<string>('');
@@ -39,6 +40,13 @@ export const ModuleSection = (props: {
<SelectorElement
key={filter}
option={filter}
icon={
highlighted?.includes(filter)
? 'circle-exclamation'
: undefined
}
iconTooltip={'Module is whitelisted!'}
iconColor="red"
action="pick_module"
selected={selected}
/>
@@ -1,14 +1,16 @@
import { useBackend } from 'tgui/backend';
import { Button, Icon, Stack } from 'tgui-core/components';
import { Button, Icon, Stack, Tooltip } from 'tgui-core/components';
export const SelectorElement = (props: {
option: string;
action: string;
selected?: string | null;
belly?: boolean;
icon?: string;
iconTooltip?: string;
iconColor?: string;
}) => {
const { act } = useBackend();
const { option, action, selected, belly } = props;
const { option, action, selected, icon, iconTooltip, iconColor } = props;
return (
<Stack.Item>
@@ -18,14 +20,13 @@ export const SelectorElement = (props: {
onClick={() => act(action, { value: option })}
>
<Stack>
<Stack.Item>{option}</Stack.Item>
{!!belly && (
<>
<Stack.Item grow />
<Stack.Item>
<Icon name="utensils" />
</Stack.Item>
</>
<Stack.Item grow>{option}</Stack.Item>
{!!icon && (
<Stack.Item>
<Tooltip content={iconTooltip}>
<Icon name={icon} color={iconColor} />
</Tooltip>
</Stack.Item>
)}
</Stack>
</Button>
@@ -77,7 +77,9 @@ export const SpriteSection = (props: {
option={filter.sprite}
action="pick_icon"
selected={selected}
belly={filter.belly}
icon={filter.belly ? 'utensils' : undefined}
iconColor="lightgray"
iconTooltip={'Module has belly sprite.'}
/>
))}
</Stack>
@@ -12,6 +12,7 @@ export const RobotChoose = (props) => {
const {
possible_modules,
whitelisted_modules,
possible_sprites,
selected_module,
sprite_datum,
@@ -31,6 +32,7 @@ export const RobotChoose = (props) => {
<ModuleSection
title="Modules"
sortable={possible_modules}
highlighted={whitelisted_modules}
selected={selected_module}
/>
</Stack.Item>
@@ -1,5 +1,6 @@
export type Data = {
possible_modules: string[];
whitelisted_modules: string[];
mind_name: string;
possible_sprites?: spriteOption[];
currentName: string;
@@ -0,0 +1,71 @@
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import {
Button,
Dropdown,
Input,
LabeledList,
Section,
Stack,
} from 'tgui-core/components';
import { capitalize } from 'tgui-core/string';
import type { Data } from './types';
export const WhitelistAddEnttry = (props: {
type: string;
entries: string[];
}) => {
const { act } = useBackend<Data>();
const { type, entries } = props;
const [selectedRole, setSelectedRole] = useState('');
const [ckey, setCkey] = useState('');
return (
<Stack.Item>
<Section
fill
title={capitalize(type)}
buttons={
<Button
disabled={!selectedRole || !ckey}
onClick={() =>
act('add_alienwhitelist', {
ckey: ckey.toLocaleLowerCase(),
type: type,
role: selectedRole,
})
}
color="green"
>
Add
</Button>
}
>
<LabeledList>
<LabeledList.Item label="Role">
<Dropdown
onSelected={setSelectedRole}
options={entries}
selected={selectedRole}
/>
</LabeledList.Item>
<LabeledList.Item label="Ckey">
<Stack>
<Stack.Item>
<Input fluid value={ckey} onChange={setCkey} />
</Stack.Item>
<Stack.Item>
<Button
disabled={!ckey}
color="red"
onClick={() => setCkey('')}
>
X
</Button>
</Stack.Item>
</Stack>
</LabeledList.Item>
</LabeledList>
</Section>
</Stack.Item>
);
};
@@ -0,0 +1,75 @@
import { useEffect, useState } from 'react';
import { useBackend } from 'tgui/backend';
import {
Button,
Dropdown,
LabeledList,
Section,
Stack,
} from 'tgui-core/components';
import { capitalize } from 'tgui-core/string';
import type { Data } from './types';
export const WhitelistRemoveEntry = (props: {
type: string;
entries: Record<string, string[] | null>;
}) => {
const { act } = useBackend<Data>();
const { type, entries } = props;
const [selectedRole, setSelectedRole] = useState('');
const [ckey, setCkey] = useState('');
const ckeys = Object.keys(entries);
useEffect(() => {
if (!entries[ckey]?.length) {
setSelectedRole('');
}
if (!entries[ckey]) {
setCkey('');
}
}, [entries]);
function handleCkey(newKey: string) {
setCkey(newKey);
if (entries[newKey]?.length) {
setSelectedRole(entries[newKey][0]);
}
}
return (
<Stack.Item>
<Section
fill
title={capitalize(type)}
buttons={
<Button
disabled={!selectedRole || !ckey}
onClick={() =>
act('remove_alienwhitelist', {
ckey: ckey.toLocaleLowerCase(),
type: type,
role: selectedRole,
})
}
color="red"
>
Remove
</Button>
}
>
<LabeledList>
<LabeledList.Item label="Ckey">
<Dropdown onSelected={handleCkey} options={ckeys} selected={ckey} />
</LabeledList.Item>
<LabeledList.Item label="Role">
<Dropdown
onSelected={setSelectedRole}
options={entries[ckey] ?? []}
selected={selectedRole}
/>
</LabeledList.Item>
</LabeledList>
</Section>
</Stack.Item>
);
};
@@ -0,0 +1,90 @@
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Button, Section, Stack } from 'tgui-core/components';
import type { Data } from './types';
import { WhitelistAddEnttry } from './WhitelistAddEnttry';
import { WhitelistRemoveEntry } from './WhitelistRemoveEntry';
export const WhitelistEdit = () => {
const { data, act } = useBackend<Data>();
const {
alienwhitelist,
languagewhitelist,
robotwhitelist,
jobwhitelist,
species_with_whitelist,
language_with_whitelist,
robot_with_whitelist,
jobs_with_whitelist,
} = data;
const possibleAdds = {
species: species_with_whitelist,
language: language_with_whitelist,
robot: robot_with_whitelist,
job: jobs_with_whitelist,
};
const possibleRemovals = {
species: alienwhitelist,
language: languagewhitelist,
robot: robotwhitelist,
job: jobwhitelist,
};
return (
<Window width={530} height={495} theme="admin">
<Window.Content>
<Stack vertical fill>
<Stack.Item>
<Stack>
<Stack.Item grow />
<Stack.Item>
<Button
onClick={() => act('reload_alienwhitelist')}
tooltip="Reloads the alien whitelist (Species, Languages, Robots)"
>
Reload Alien Whitelist
</Button>
</Stack.Item>
<Stack.Item>
<Button
onClick={() => act('reload_jobwhitelist')}
tooltip="Reloads the jon whitelist"
>
Reload Job Whitelist
</Button>
</Stack.Item>
</Stack>
</Stack.Item>
<Stack.Item grow>
<Stack fill>
<Stack.Item>
<Section fill title="Add">
<Stack vertical fill>
{Object.entries(possibleAdds).map(([type, value]) => (
<Stack.Item key={type}>
<WhitelistAddEnttry type={type} entries={value} />
</Stack.Item>
))}
</Stack>
</Section>
</Stack.Item>
<Stack.Item>
<Section fill title="Remove">
<Stack vertical fill>
{Object.entries(possibleRemovals).map(([type, value]) => (
<Stack.Item key={type}>
<WhitelistRemoveEntry type={type} entries={value} />
</Stack.Item>
))}
</Stack>
</Section>
</Stack.Item>
</Stack>
</Stack.Item>
</Stack>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,11 @@
export type Data = {
species_with_whitelist: string[];
language_with_whitelist: string[];
robot_with_whitelist: string[];
jobs_with_whitelist: string[];
alienwhitelist: Record<string, string[] | null>;
languagewhitelist: Record<string, string[] | null>;
robotwhitelist: Record<string, string[] | null>;
jobwhitelist: Record<string, string[] | null>;
};
+2
View File
@@ -3607,6 +3607,7 @@
#include "code\modules\mob\living\silicon\robot\drone\swarm_abilities.dm"
#include "code\modules\mob\living\silicon\robot\drone\swarm_items.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\event.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\module.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\station.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\swarm.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\syndicate.dm"
@@ -3631,6 +3632,7 @@
#include "code\modules\mob\living\silicon\robot\sprites\sprite_organized\xenoborgs.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\gravekeeper.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\lost_drone.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\malf_robot.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\syndicate.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\exploration\exploration-modules.dm"
#include "code\modules\mob\living\silicon\robot\subtypes\exploration\exploration-sprites.dm"