diff --git a/archive/maps/submaps/depreciated_vr/talon.dm b/archive/maps/submaps/depreciated_vr/talon.dm index 54f7417742..4b428ed54b 100644 --- a/archive/maps/submaps/depreciated_vr/talon.dm +++ b/archive/maps/submaps/depreciated_vr/talon.dm @@ -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) diff --git a/code/__defines/admin_verb.dm b/code/__defines/admin_verb.dm index 5ef574a7b3..3cb2af3313 100644 --- a/code/__defines/admin_verb.dm +++ b/code/__defines/admin_verb.dm @@ -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" diff --git a/code/_global_vars/__unsorted.dm b/code/_global_vars/__unsorted.dm index 22c08dbb20..a7747ab662 100644 --- a/code/_global_vars/__unsorted.dm +++ b/code/_global_vars/__unsorted.dm @@ -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) diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 3847eb2035..03c4c07ba1 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -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, diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm index 05aceaf4fb..c3cc6dcf68 100644 --- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm @@ -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 diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index 34f4de0430..3fdcf0a625 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -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 diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm index f0e2bbf99c..f300cf1f39 100644 --- a/code/game/objects/items/devices/geiger.dm +++ b/code/game/objects/items/devices/geiger.dm @@ -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) diff --git a/code/game/objects/items/weapons/id cards/cards.dm b/code/game/objects/items/weapons/id cards/cards.dm index 8544313afb..09ed94244c 100644 --- a/code/game/objects/items/weapons/id cards/cards.dm +++ b/code/game/objects/items/weapons/id cards/cards.dm @@ -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 diff --git a/code/game/objects/items/weapons/id cards/id_stacks.dm b/code/game/objects/items/weapons/id cards/id_stacks.dm index 162c1d8354..1f414ca479 100644 --- a/code/game/objects/items/weapons/id cards/id_stacks.dm +++ b/code/game/objects/items/weapons/id cards/id_stacks.dm @@ -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 diff --git a/code/game/objects/structures/ghost_pods/silicon.dm b/code/game/objects/structures/ghost_pods/silicon.dm index 8c29869134..959b383f79 100644 --- a/code/game/objects/structures/ghost_pods/silicon.dm +++ b/code/game/objects/structures/ghost_pods/silicon.dm @@ -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. diff --git a/code/game/objects/structures/ghost_pods/silicon_vr.dm b/code/game/objects/structures/ghost_pods/silicon_vr.dm index 1039349f2e..507eded1c5 100644 --- a/code/game/objects/structures/ghost_pods/silicon_vr.dm +++ b/code/game/objects/structures/ghost_pods/silicon_vr.dm @@ -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) diff --git a/code/modules/admin/modify_robot.dm b/code/modules/admin/modify_robot.dm index 9f7a91bf0a..84387d8234 100644 --- a/code/modules/admin/modify_robot.dm +++ b/code/modules/admin/modify_robot.dm @@ -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 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index a866f05a9d..50764dbcbd 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -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 diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index b5fe9edd71..41325f371b 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -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)) diff --git a/code/modules/mob/living/silicon/robot/custom_sprites.dm b/code/modules/mob/living/silicon/robot/custom_sprites.dm index bed5a984fc..09ddf117b2 100644 --- a/code/modules/mob/living/silicon/robot/custom_sprites.dm +++ b/code/modules/mob/living/silicon/robot/custom_sprites.dm @@ -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 diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index dd11882c7c..7e09edc5a9 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -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() diff --git a/code/modules/mob/living/silicon/robot/drone/swarm.dm b/code/modules/mob/living/silicon/robot/drone/swarm.dm index 4aa4878149..306a1697c7 100644 --- a/code/modules/mob/living/silicon/robot/drone/swarm.dm +++ b/code/modules/mob/living/silicon/robot/drone/swarm.dm @@ -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 diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index a41b5d9a32..d10a7c3e1f 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -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() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 9633e34069..cff54de75a 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -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 diff --git a/code/modules/mob/living/silicon/robot/robot_modules/event.dm b/code/modules/mob/living/silicon/robot/robot_modules/event.dm index 04a5e5020d..acf6a7b1f2 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/event.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/event.dm @@ -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() diff --git a/code/modules/mob/living/silicon/robot/robot_modules/module.dm b/code/modules/mob/living/silicon/robot/robot_modules/module.dm new file mode 100644 index 0000000000..1bc663ae93 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_modules/module.dm @@ -0,0 +1,2 @@ +/obj/item/robot_module/proc/handle_special_unlocks() + return diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index 679369a8d6..2fa352d3a2 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -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) diff --git a/code/modules/mob/living/silicon/robot/robot_modules/swarm.dm b/code/modules/mob/living/silicon/robot/robot_modules/swarm.dm index 9928777ebb..9b364ccd78 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/swarm.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/swarm.dm @@ -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) diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm index bccf32c0db..a18ab78693 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -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" diff --git a/code/modules/mob/living/silicon/robot/robot_ui_module.dm b/code/modules/mob/living/silicon/robot/robot_ui_module.dm index 6548a8672f..60aee48c88 100644 --- a/code/modules/mob/living/silicon/robot/robot_ui_module.dm +++ b/code/modules/mob/living/silicon/robot/robot_ui_module.dm @@ -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) diff --git a/code/modules/mob/living/silicon/robot/subtypes/exploration/exploration-modules.dm b/code/modules/mob/living/silicon/robot/subtypes/exploration/exploration-modules.dm index 0c8d639a7b..1faf620338 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/exploration/exploration-modules.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/exploration/exploration-modules.dm @@ -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) diff --git a/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm b/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm index 0a1bc88dcc..26396f587c 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm @@ -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() diff --git a/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm b/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm index 845ac56f43..8c0910b469 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm @@ -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() diff --git a/code/modules/mob/living/silicon/robot/subtypes/malf_robot.dm b/code/modules/mob/living/silicon/robot/subtypes/malf_robot.dm new file mode 100644 index 0000000000..8f3a27c161 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/subtypes/malf_robot.dm @@ -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) diff --git a/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm b/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm index 7f66815e2d..e5288c342e 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm @@ -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" diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/_thinktank.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/_thinktank.dm index 47b6252434..72d7bbc54d 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/thinktank/_thinktank.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/_thinktank.dm @@ -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 diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm index fca4a2d3f1..ab24b6fe9e 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm @@ -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() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index a4e3d1a51c..6226fb465b 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -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) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index d057dc9240..276571489c 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -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!")) diff --git a/code/modules/tgs_commands/vorestation.dm b/code/modules/tgs_commands/vorestation.dm index e406822538..3f036f4068 100644 --- a/code/modules/tgs_commands/vorestation.dm +++ b/code/modules/tgs_commands/vorestation.dm @@ -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, ", ")]\] (role)" /datum/tgs_chat_command/whitelist name = "whitelist" - help_text = "allows the management of player whitelists.\nUsage: whitelist \[add, remove, list\] \[job, species\] (role)" + help_text = "allows the management of player whitelists.\nUsage: whitelist \[add, remove, list\] \[job, species, language, robot\] (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") diff --git a/config/example/alienwhitelist.txt b/config/example/alienwhitelist.txt index 01acc82de9..19c5ca3b46 100644 --- a/config/example/alienwhitelist.txt +++ b/config/example/alienwhitelist.txt @@ -1 +1 @@ -some~user - Species \ No newline at end of file +species - some~user - Species diff --git a/maps/offmap_vr/talon/talon_v2.dm b/maps/offmap_vr/talon/talon_v2.dm index e893587cfa..512569c571 100644 --- a/maps/offmap_vr/talon/talon_v2.dm +++ b/maps/offmap_vr/talon/talon_v2.dm @@ -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" diff --git a/tgui/docs/tutorial-and-examples.md b/tgui/docs/tutorial-and-examples.md index 8a690d19b4..b62116acce 100644 --- a/tgui/docs/tutorial-and-examples.md +++ b/tgui/docs/tutorial-and-examples.md @@ -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 ( @@ -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 ( diff --git a/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx b/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx index 9f7dc2a02e..51121ce5ec 100644 --- a/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx +++ b/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx @@ -45,7 +45,7 @@ export const ModifyRobotNoModule = (props: { target: Target }) => {
- {target.active_restrictions.map((active_restriction, i) => { + {target.active_restrictions?.map((active_restriction, i) => { return ( diff --git a/tgui/packages/tgui/interfaces/RobotChoose/SpriteSection.tsx b/tgui/packages/tgui/interfaces/RobotChoose/SpriteSection.tsx index d7329d61c3..d067821980 100644 --- a/tgui/packages/tgui/interfaces/RobotChoose/SpriteSection.tsx +++ b/tgui/packages/tgui/interfaces/RobotChoose/SpriteSection.tsx @@ -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.'} /> ))} diff --git a/tgui/packages/tgui/interfaces/RobotChoose/index.tsx b/tgui/packages/tgui/interfaces/RobotChoose/index.tsx index 9810ba788e..1969c54f57 100644 --- a/tgui/packages/tgui/interfaces/RobotChoose/index.tsx +++ b/tgui/packages/tgui/interfaces/RobotChoose/index.tsx @@ -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) => { diff --git a/tgui/packages/tgui/interfaces/RobotChoose/types.ts b/tgui/packages/tgui/interfaces/RobotChoose/types.ts index adfe7cd320..55acce3985 100644 --- a/tgui/packages/tgui/interfaces/RobotChoose/types.ts +++ b/tgui/packages/tgui/interfaces/RobotChoose/types.ts @@ -1,5 +1,6 @@ export type Data = { possible_modules: string[]; + whitelisted_modules: string[]; mind_name: string; possible_sprites?: spriteOption[]; currentName: string; diff --git a/tgui/packages/tgui/interfaces/WhitelistEdit/WhitelistAddEnttry.tsx b/tgui/packages/tgui/interfaces/WhitelistEdit/WhitelistAddEnttry.tsx new file mode 100644 index 0000000000..68b23d09ef --- /dev/null +++ b/tgui/packages/tgui/interfaces/WhitelistEdit/WhitelistAddEnttry.tsx @@ -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(); + const { type, entries } = props; + const [selectedRole, setSelectedRole] = useState(''); + const [ckey, setCkey] = useState(''); + return ( + +
+ act('add_alienwhitelist', { + ckey: ckey.toLocaleLowerCase(), + type: type, + role: selectedRole, + }) + } + color="green" + > + Add + + } + > + + + + + + + + + + + + + + + +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/WhitelistEdit/WhitelistRemoveEntry.tsx b/tgui/packages/tgui/interfaces/WhitelistEdit/WhitelistRemoveEntry.tsx new file mode 100644 index 0000000000..cda8f06ee4 --- /dev/null +++ b/tgui/packages/tgui/interfaces/WhitelistEdit/WhitelistRemoveEntry.tsx @@ -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; +}) => { + const { act } = useBackend(); + 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 ( + +
+ act('remove_alienwhitelist', { + ckey: ckey.toLocaleLowerCase(), + type: type, + role: selectedRole, + }) + } + color="red" + > + Remove + + } + > + + + + + + + + +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/WhitelistEdit/index.tsx b/tgui/packages/tgui/interfaces/WhitelistEdit/index.tsx new file mode 100644 index 0000000000..7b1656b50c --- /dev/null +++ b/tgui/packages/tgui/interfaces/WhitelistEdit/index.tsx @@ -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(); + 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 ( + + + + + + + + + + + + + + + + + +
+ + {Object.entries(possibleAdds).map(([type, value]) => ( + + + + ))} + +
+
+ +
+ + {Object.entries(possibleRemovals).map(([type, value]) => ( + + + + ))} + +
+
+
+
+
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/WhitelistEdit/types.ts b/tgui/packages/tgui/interfaces/WhitelistEdit/types.ts new file mode 100644 index 0000000000..d74eec76af --- /dev/null +++ b/tgui/packages/tgui/interfaces/WhitelistEdit/types.ts @@ -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; + languagewhitelist: Record; + robotwhitelist: Record; + jobwhitelist: Record; +}; diff --git a/vorestation.dme b/vorestation.dme index 775587edf9..d6ca415e47 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -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"