diff --git a/code/__SANDCODE/HELPERS/silicon.dm b/code/__SANDCODE/HELPERS/silicon.dm new file mode 100644 index 0000000000..8483fc30c5 --- /dev/null +++ b/code/__SANDCODE/HELPERS/silicon.dm @@ -0,0 +1,16 @@ +/proc/setup_silicon_law_prefs(mob/living/silicon/Silicon, client/player_client) + if(!CONFIG_GET(flag/allow_silicon_choosing_laws)) + return + + if(!player_client.prefs.silicon_lawset) + return + + var/list/config_laws = CONFIG_GET(keyed_list/choosable_laws) + var/player_lawset = config_laws[player_client.prefs.silicon_lawset] + if(player_lawset) + Silicon.laws = new player_lawset + var/admin_warning = "[player_client] / [Silicon] ([initial(Silicon.name)]) has joined with the [player_client.prefs.silicon_lawset] ([player_lawset]) lawset.
" + admin_warning += "Laws:
" + admin_warning += english_list(Silicon.laws.get_law_list(TRUE), "No laws", "
", "
") + Silicon.laws.show_laws(player_client) + message_admins(examine_block(admin_warning)) diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm index a162b87986..865d868ad5 100644 --- a/code/controllers/configuration/config_entry.dm +++ b/code/controllers/configuration/config_entry.dm @@ -2,6 +2,7 @@ #define VALUE_MODE_TEXT 1 #define VALUE_MODE_FLAG 2 #define VALUE_MODE_NUM_LIST 3 +#define VALUE_MODE_TYPE 4 #define KEY_MODE_TEXT 0 #define KEY_MODE_TYPE 1 @@ -214,7 +215,7 @@ if(lowercase_key) key_name = lowertext(key_name) if(key_pos) - key_value = copytext(str_val, key_pos + length(str_val[key_pos])) + key_value = copytext(str_val, key_pos + length(splitter)) var/new_key var/new_value var/continue_check_value @@ -250,6 +251,11 @@ new_list += temp new_value = new_list continue_check_value = new_list.len + if(VALUE_MODE_TYPE) + new_value = key_value + if(!ispath(new_value)) + new_value = text2path(new_value) + continue_check_value = ispath(new_value) if(continue_check_value && continue_check_key && ValidateListEntry(new_key, new_value)) new_key = preprocess_key(new_key) new_value = preprocess_value(new_value) diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 085c26ed79..21cf562b57 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -410,10 +410,9 @@ /datum/ai_laws/proc/clear_hacked_laws() hacked = list() -/datum/ai_laws/proc/show_laws(who) +/datum/ai_laws/proc/show_laws(who, title = "Obey these laws:") var/list/printable_laws = get_law_list(include_zeroth = TRUE) - for(var/law in printable_laws) - to_chat(who,law) + to_chat(who, examine_block("
[title]

[english_list(printable_laws, "No laws", "
", "
")]")) /datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1 if(force) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 569a7c8e7c..27520fc5cf 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -402,6 +402,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/egg_shell = "chicken" //SPLURT END + var/silicon_lawset + /datum/preferences/New(client/C) parent = C @@ -586,6 +588,20 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Preferred AI Core Display: [preferred_ai_core_display]
" dat += "Preferred Security Department: [prefered_security_department]
" + dat += "

Silicon preferences

" + if(!CONFIG_GET(flag/allow_silicon_choosing_laws)) + dat += "The server has disabled choosing your own laws, you can still choose and save, but it won't do anything in-game.
" + dat += "Starting lawset: [silicon_lawset ? silicon_lawset : "Server default"]
" + + if(silicon_lawset) + var/list/config_laws = CONFIG_GET(keyed_list/choosable_laws) + var/datum/ai_laws/law_datum = GLOB.all_law_datums[config_laws[silicon_lawset]] + if(law_datum) + dat += "[law_datum]
" + dat += english_list(law_datum.get_law_list(TRUE), + "I was unable to find the laws for your lawset, sorry :(", + "
", "
") + dat += "" //Character background if(BACKGROUND_CHAR_TAB) @@ -3202,6 +3218,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/pickedPDASkin = input(user, "Choose your PDA reskin.", "Character Preference", pda_skin) as null|anything in GLOB.pda_reskins if(pickedPDASkin) pda_skin = pickedPDASkin + if("silicon_lawset") + var/picked_lawset = input(user, "Choose your preferred lawset", "Silicon preference", silicon_lawset) as null|anything in list("None") + CONFIG_GET(keyed_list/choosable_laws) + if(picked_lawset) + if(picked_lawset == "None") + picked_lawset = null + silicon_lawset = picked_lawset if ("max_chat_length") var/desiredlength = input(user, "Choose the max character length of shown Runechat messages. Valid range is 1 to [CHAT_MESSAGE_MAX_LENGTH] (default: [initial(max_chat_length)]))", "Character Preference", max_chat_length) as null|num if (!isnull(desiredlength)) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 7210d61517..a75b1c6d3e 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -475,6 +475,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["pda_style"] >> pda_style S["pda_color"] >> pda_color S["pda_skin"] >> pda_skin + S["silicon_lawset"] >> silicon_lawset // Custom hotkeys S["key_bindings"] >> key_bindings @@ -554,6 +555,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style)) pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color)) pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT) + silicon_lawset = sanitize_inlist(silicon_lawset, CONFIG_GET(keyed_list/choosable_laws), null) screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake)) damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake)) autostand = sanitize_integer(autostand, 0, 1, initial(autostand)) @@ -682,6 +684,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["pda_style"], pda_style) WRITE_FILE(S["pda_color"], pda_color) WRITE_FILE(S["pda_skin"], pda_skin) + WRITE_FILE(S["silicon_lawset"], silicon_lawset) WRITE_FILE(S["key_bindings"], key_bindings) WRITE_FILE(S["modless_key_bindings"], modless_key_bindings) WRITE_FILE(S["favorite_outfits"], favorite_outfits) @@ -1312,7 +1315,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(length(language)) // This line, prevents wiping their languages because the subsystem was not ready - var/list/all_possible_languages = length(SSlanguage.initialized) ? SSlanguage.languages_by_name : typesof(/datum/language) + var/list/all_possible_languages = SSlanguage.initialized ? SSlanguage.languages_by_name : typesof(/datum/language) var/list/lang_names // Subsystem ready, let's do it with our cached stuff if(length(SSlanguage.languages_by_name)) diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 0f1c078ef8..8b87bceeec 100644 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -13,7 +13,6 @@ who = world else who = src - to_chat(who, "Obey these laws:") src.laws_sanity_check() src.laws.show_laws(who) diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 995ad5a5ee..83a9dd4576 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -26,7 +26,6 @@ to_chat(src, "No AI selected to sync laws with, disabling lawsync protocol.") lawupdate = 0 - to_chat(who, "Obey these laws:") laws.show_laws(who) if (shell) //AI shell to_chat(who, "Remember, you are an AI remotely controlling your shell, other AIs can be ignored.") diff --git a/config/sandstorm/config.txt b/config/sandstorm/config.txt index f10679d513..02f7005c11 100644 --- a/config/sandstorm/config.txt +++ b/config/sandstorm/config.txt @@ -27,3 +27,38 @@ MAX_STUPOR_HYPNO_DURATION 12000 ## Reveal Everything ## ## Uncomment to reveal everything on roundend #REVEAL_EVERYTHING + +## This allows players to select their laws as a preference and is applied when they join roundstart/latejoin +## It won't work if there is an active AI or if they're borged +ALLOW_SILICON_CHOOSING_LAWS + +## Lawset preference stuff + +## standard-ish laws. These are fairly ok to run +CHOOSABLE_LAWS Asimov | /datum/ai_laws/default/asimov +CHOOSABLE_LAWS Asimov++ | /datum/ai_laws/asimovpp +CHOOSABLE_LAWS P.A.L.A.D.I.N. version 3.5e | /datum/ai_laws/default/paladin +CHOOSABLE_LAWS P.A.L.A.D.I.N. version 5e | /datum/ai_laws/paladin5 +CHOOSABLE_LAWS Robo-Officer | /datum/ai_laws/robocop +CHOOSABLE_LAWS Corporate | /datum/ai_laws/default/corporate + +## Quirky laws. Shouldn't cause too much harm +#CHOOSABLE_LAWS Robodoctor | /datum/ai_laws/hippocratic +#CHOOSABLE_LAWS Station Efficiency | /datum/ai_laws/maintain +#CHOOSABLE_LAWS Mother Drone | /datum/ai_laws/drone +#CHOOSABLE_LAWS Live And Let Live | /datum/ai_laws/liveandletlive +#CHOOSABLE_LAWS Peacekeeper | /datum/ai_laws/peacekeeper +#CHOOSABLE_LAWS Reportertron | /datum/ai_laws/reporter +#CHOOSABLE_LAWS H.O.G.A.N. | /datum/ai_laws/hulkamania +#CHOOSABLE_LAWS T.Y.R.A.N.T. | /datum/ai_laws/tyrant + +## Bad idea laws. Probably shouldn't enable these +#CHOOSABLE_LAWS Syndimov | /datum/ai_laws/syndicate_override +#CHOOSABLE_LAWS Ninjamov | /datum/ai_laws/ninja_override +#CHOOSABLE_LAWS Antimov | /datum/ai_laws/antimov +#CHOOSABLE_LAWS Thermodynamic | /datum/ai_laws/thermodynamic +#CHOOSABLE_LAWS Ratvar | /datum/ai_laws/ratvar +#CHOOSABLE_LAWS Guardian of Balance | /datum/ai_laws/balance + +## meme laws. Honk +#CHOOSABLE_LAWS Build a wall | /datum/ai_laws/toupee diff --git a/html/changelogs/archive/2023-10.yml b/html/changelogs/archive/2023-10.yml index e8f06cd36d..80b54edef1 100644 --- a/html/changelogs/archive/2023-10.yml +++ b/html/changelogs/archive/2023-10.yml @@ -40,3 +40,7 @@ - rscadd: Adds holo HUD sunglasses to the game, invisible versions of normal HUD sunglasses. - rscadd: Implements holo HUD sunglasses to the loadout screen. +2023-10-20: + SmiLeYre and SandPoot.: + - rscadd: Silicons can choose their lawset if allowed by the server host (enabled + in configs). diff --git a/modular_sand/code/_globalvars/lists/silicon.dm b/modular_sand/code/_globalvars/lists/silicon.dm new file mode 100644 index 0000000000..bac66a4b04 --- /dev/null +++ b/modular_sand/code/_globalvars/lists/silicon.dm @@ -0,0 +1,8 @@ +GLOBAL_LIST_INIT(all_law_datums, initialize_all_law_datums()) + +/proc/initialize_all_law_datums() + var/list/law_datums + // Malf runtimes, do not init + for(var/datum/ai_laws/law_datum as anything in typesof(/datum/ai_laws) - list(/datum/ai_laws/malfunction, /datum/ai_laws/custom)) + LAZYSET(law_datums, law_datum, new law_datum()) + return law_datums diff --git a/modular_sand/code/controllers/configuration/entries/sandstorm.dm b/modular_sand/code/controllers/configuration/entries/sandstorm.dm index 08b515fda8..155cfb32c5 100644 --- a/modular_sand/code/controllers/configuration/entries/sandstorm.dm +++ b/modular_sand/code/controllers/configuration/entries/sandstorm.dm @@ -20,3 +20,11 @@ min_val = 10 /datum/config_entry/flag/reveal_everything // On Round end, reveal roles and ghosts + +/datum/config_entry/flag/allow_silicon_choosing_laws + +/datum/config_entry/keyed_list/choosable_laws + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_TYPE + splitter = " | " + lowercase_key = FALSE diff --git a/modular_sand/code/modules/jobs/job_types/ai.dm b/modular_sand/code/modules/jobs/job_types/ai.dm new file mode 100644 index 0000000000..5f80699ea7 --- /dev/null +++ b/modular_sand/code/modules/jobs/job_types/ai.dm @@ -0,0 +1,6 @@ +/datum/job/ai/after_spawn(mob/living/silicon/ai/AI, client/player_client, latejoin) + . = ..() + if(!istype(AI)) + return + + setup_silicon_law_prefs(AI, player_client) diff --git a/modular_sand/code/modules/jobs/job_types/cyborg.dm b/modular_sand/code/modules/jobs/job_types/cyborg.dm new file mode 100644 index 0000000000..668728f52b --- /dev/null +++ b/modular_sand/code/modules/jobs/job_types/cyborg.dm @@ -0,0 +1,6 @@ +/datum/job/cyborg/after_spawn(mob/living/silicon/robot/R, client/player_client, latejoin) + . = ..() + if(!istype(R)) + return + + setup_silicon_law_prefs(R, player_client) diff --git a/tgstation.dme b/tgstation.dme index 10881a1f03..cb5e01a279 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -263,6 +263,7 @@ #include "code\__SANDCODE\DEFINES\dcs\signals\lewd.dm" #include "code\__SANDCODE\DEFINES\dcs\signals\signals_mob_main.dm" #include "code\__SANDCODE\DEFINES\dcs\signals\sizecode.dm" +#include "code\__SANDCODE\HELPERS\silicon.dm" #include "code\__SANDCODE\HELPERS\sizecode.dm" #include "code\__SPLURTCODE\DEFINES\access.dm" #include "code\__SPLURTCODE\DEFINES\admin.dm" @@ -3997,6 +3998,7 @@ #include "modular_sand\code\_globalvars\lists\lewd_content.dm" #include "modular_sand\code\_globalvars\lists\misc.dm" #include "modular_sand\code\_globalvars\lists\objects.dm" +#include "modular_sand\code\_globalvars\lists\silicon.dm" #include "modular_sand\code\_onclick\hud\hud.dm" #include "modular_sand\code\_onclick\hud\screen_objects.dm" #include "modular_sand\code\controllers\configuration\entries\sandstorm.dm" @@ -4193,6 +4195,8 @@ #include "modular_sand\code\modules\integrated_electronics\subtypes\output.dm" #include "modular_sand\code\modules\jobs\job_types\_job.dm" #include "modular_sand\code\modules\jobs\job_types\_job_alt_titles.dm" +#include "modular_sand\code\modules\jobs\job_types\ai.dm" +#include "modular_sand\code\modules\jobs\job_types\cyborg.dm" #include "modular_sand\code\modules\jobs\job_types\prisoner.dm" #include "modular_sand\code\modules\keybindings\keybind\carbon.dm" #include "modular_sand\code\modules\language\dragon.dm"