From 5dc034719d7ed876f7b9c21d5bd6c41cff098bb0 Mon Sep 17 00:00:00 2001 From: Markolie Date: Mon, 31 Aug 2015 02:18:49 +0200 Subject: [PATCH] Port Bay's silicon law manager --- _maps/map_files/cyberiad/cyberiad.dmm | 12 +- code/__DEFINES/misc.dm | 3 + code/__HELPERS/lists.dm | 1 + code/__HELPERS/text.dm | 13 +- code/_globalvars/lists/mobs.dm | 1 + code/_onclick/hud/ai.dm | 2 +- code/_onclick/hud/screen_objects.dm | 4 +- code/datums/ai_law_sets.dm | 170 ++++++ code/datums/ai_laws.dm | 450 +++++++++------- code/datums/mind.dm | 4 +- code/defines/procs/admin.dm | 4 +- .../game/gamemodes/malfunction/malfunction.dm | 2 +- code/game/machinery/camera/tracking.dm | 19 +- code/game/machinery/computer/ai_core.dm | 26 +- code/game/machinery/computer/aifixer.dm | 15 +- code/game/machinery/computer/camera.dm | 28 +- code/game/objects/items/devices/aicard.dm | 23 +- .../game/objects/items/devices/radio/radio.dm | 1 + code/game/objects/items/weapons/AI_modules.dm | 484 ++++++++---------- code/modules/admin/admin_verbs.dm | 38 +- code/modules/admin/verbs/debug.dm | 4 +- code/modules/mob/living/living_defines.dm | 2 +- code/modules/mob/living/silicon/ai/ai.dm | 36 +- code/modules/mob/living/silicon/ai/examine.dm | 12 +- code/modules/mob/living/silicon/ai/laws.dm | 145 +----- code/modules/mob/living/silicon/laws.dm | 121 +++++ .../mob/living/silicon/robot/drone/drone.dm | 6 + .../mob/living/silicon/robot/examine.dm | 1 + code/modules/mob/living/silicon/robot/laws.dm | 165 +----- .../modules/mob/living/silicon/robot/robot.dm | 67 ++- code/modules/mob/living/silicon/silicon.dm | 16 +- code/modules/mob/living/silicon/subsystems.dm | 16 +- code/modules/mob/mob_helpers.dm | 9 + code/modules/nano/modules/human_appearance.dm | 2 + code/modules/nano/modules/law_manager.dm | 219 ++++++++ .../research/designs/AI_module_designs.dm | 48 +- config/example/game_options.txt | 7 +- nano/templates/ai_fixer.tmpl | 7 +- nano/templates/law_manager.tmpl | 253 +++++++++ paradise.dme | 3 + 40 files changed, 1499 insertions(+), 940 deletions(-) create mode 100644 code/datums/ai_law_sets.dm create mode 100644 code/modules/mob/living/silicon/laws.dm create mode 100644 code/modules/nano/modules/law_manager.dm create mode 100644 nano/templates/law_manager.tmpl diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 1c0163e3b43..da9d10e5c1e 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -3359,7 +3359,7 @@ "bmE" = (/turf/simulated/floor/bluegrid,/area/turret_protected/ai) "bmF" = (/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai) "bmG" = (/obj/structure/table,/obj/item/weapon/phone{pixel_x = -3; pixel_y = 3},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai) -"bmH" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/table,/obj/item/weapon/aiModule/supplied/protectStation,/obj/item/weapon/aiModule/core/full/nanotrasen,/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) +"bmH" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/table,/obj/item/weapon/aiModule/protectStation,/obj/item/weapon/aiModule/nanotrasen,/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) "bmI" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 4},/turf/simulated/floor/wood,/area/crew_quarters/captain) "bmJ" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/wood,/area/crew_quarters/captain) "bmK" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/light_switch{pixel_y = 27},/turf/simulated/floor/wood,/area/crew_quarters/captain) @@ -3419,10 +3419,10 @@ "bnM" = (/obj/structure/stool/bed/chair/comfy/black,/turf/simulated/floor/carpet,/area/bridge/meeting_room) "bnN" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/wood,/area/bridge/meeting_room) "bnO" = (/obj/machinery/vending/snack,/turf/simulated/floor/wood,/area/bridge/meeting_room) -"bnP" = (/obj/structure/table,/obj/item/weapon/aiModule/zeroth/quarantine,/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) +"bnP" = (/obj/structure/table,/obj/item/weapon/aiModule/quarantine,/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) "bnQ" = (/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) "bnR" = (/obj/machinery/hologram/holopad,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai) -"bnS" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/structure/table,/obj/item/weapon/aiModule/supplied/freeform,/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) +"bnS" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/structure/table,/obj/item/weapon/aiModule/freeform,/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) "bnT" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0; tag = ""},/obj/machinery/vending/cigarette,/turf/simulated/floor/wood,/area/crew_quarters/captain) "bnU" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/wood,/area/crew_quarters/captain) "bnV" = (/turf/simulated/floor/wood,/area/crew_quarters/captain) @@ -3550,7 +3550,7 @@ "bqn" = (/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/obj/structure/table/woodentable,/turf/simulated/floor/carpet,/area/bridge/meeting_room) "bqo" = (/obj/item/weapon/folder/blue,/obj/structure/table/woodentable,/turf/simulated/floor/carpet,/area/bridge/meeting_room) "bqp" = (/obj/machinery/vending/coffee,/turf/simulated/floor/wood,/area/bridge/meeting_room) -"bqq" = (/obj/structure/table,/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"; name = "Core Modules"; req_access_txt = "20"},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/item/weapon/aiModule/core/full/asimov,/obj/item/weapon/aiModule/core/freeformcore,/obj/item/weapon/aiModule/core/full/corp,/obj/item/weapon/aiModule/core/full/paladin,/obj/item/weapon/aiModule/core/full/robocop,/turf/simulated/floor/bluegrid,/area/turret_protected/ai_upload) +"bqq" = (/obj/structure/table,/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"; name = "Core Modules"; req_access_txt = "20"},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/item/weapon/aiModule/crewsimov,/obj/item/weapon/aiModule/freeformcore,/obj/item/weapon/aiModule/corp,/obj/item/weapon/aiModule/paladin,/obj/item/weapon/aiModule/robocop,/turf/simulated/floor/bluegrid,/area/turret_protected/ai_upload) "bqr" = (/obj/machinery/atmospherics/unary/vent_scrubber{on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/light,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/ai_upload) "bqs" = (/obj/machinery/computer/aiupload,/obj/machinery/flasher{id = "AI"; pixel_x = 0; pixel_y = -21},/turf/simulated/floor/bluegrid,/area/turret_protected/ai_upload) "bqt" = (/obj/machinery/power/apc{cell_type = 5000; dir = 2; name = "AI Upload APC"; pixel_y = -24},/obj/structure/cable,/turf/simulated/floor/bluegrid,/area/turret_protected/ai_upload) @@ -6683,6 +6683,7 @@ "cyA" = (/obj/structure/stool/bed/chair,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/virology) "cyB" = (/obj/structure/stool/bed/chair,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/light{dir = 1; on = 1},/turf/simulated/floor{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/virology) "cyC" = (/obj/structure/closet/secure_closet/personal/patient,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/virology) +"cyD" = (/obj/structure/table,/obj/machinery/door/window{base_state = "left"; dir = 8; icon_state = "left"; name = "High-Risk Modules"; req_access_txt = "20"},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/weapon/aiModule/oxygen,/obj/item/weapon/aiModule/oneCrewMember,/obj/item/weapon/aiModule/purge,/obj/item/weapon/aiModule/antimov,/turf/simulated/floor/bluegrid,/area/turret_protected/ai_upload) "cyE" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1; level = 1},/obj/machinery/light{dir = 1; on = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cyH" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/machinery/light{dir = 1; on = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cyI" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet/medical,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/camera{c_tag = "Virology Isolation 3"; dir = 2; network = list("SS13")},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) @@ -7917,7 +7918,6 @@ "das" = (/obj/structure/table,/obj/machinery/cell_charger,/obj/item/weapon/stock_parts/cell/high{charge = 100; maxcharge = 15000},/obj/item/weapon/stock_parts/cell/high{charge = 100; maxcharge = 15000},/turf/simulated/floor/plating,/area/maintenance/electrical) "dat" = (/obj/item/clothing/gloves/color/rainbow,/obj/item/clothing/shoes/rainbow,/obj/item/clothing/head/soft/rainbow,/obj/item/clothing/under/rainbow,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/maintenance/port) "dau" = (/obj/structure/grille{density = 0; icon_state = "brokengrille"},/turf/simulated/floor/plating,/area/maintenance/fsmaint2) -"dav" = (/obj/structure/table,/obj/machinery/door/window{base_state = "left"; dir = 8; icon_state = "left"; name = "High-Risk Modules"; req_access_txt = "20"},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/item/weapon/aiModule/supplied/oxygen,/obj/item/weapon/aiModule/zeroth/oneHuman,/obj/item/weapon/aiModule/reset/purge,/obj/item/weapon/aiModule/core/full/antimov,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/bluegrid,/area/turret_protected/ai_upload) "day" = (/obj/machinery/power/terminal,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/plating,/area/maintenance/electrical) "daz" = (/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor/plating,/area/maintenance/electrical) "daA" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/maintenance/electrical) @@ -8124,7 +8124,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfQbfQbfQbfQbfQbfQbfQbfQbfQbfQbfQbfQblSaAvblTblUblVbesbhvbhvbhvbfTblWblXblYblZbesbmabmbbhDbjlbmcbjlbmdbmebjlbmfbmgbmhaZKbkMbkNbkObmiaZKbbKbkQbkRbmjbmkbmlbmmbmnbkRbmobmpbmqbmrbkXbkXbkXbkXbmsbmtbmublbbmvbmwbmxbmybmzbmAbmBbmCbjPbmDblgbmEbmFbmGbmFbmEblgbmHbjPbmIbmJbmKbmLbmMbmNbmObmPbllbmQbmRbmRbmSaINaINaINaINbmTaHFbmTbmUaINaSbaINaINaSdaSdaSdaSdbmVbmWbmWbmWbmWbmXbmYaSlaFSbnaaFSbnbbnbaFSbnaaFSaSlblDbkobkobncblEaOQaOQaOQaOQaOQbgYaOQaOQaOQaOQaNqbndaDxaDxaDxaDxaDxaDxaNqaNqbnhbniaXOaXOaXOaXQaXOaXObhpaFTaHPaFTaFTaHPaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIfazEaBmaBmaBmaAyaAyaAyaAyaAyaAybnmbnnbesbesbesbesbesbesbnobesbesbesbnpbnpbnqbjlbnrbnsbmdbntbjlbnubnvbnuaZKbkMbkNbkObnwaZKbbKbkQbkRbnxbnybnzbmmbnzbkRbmobnAbnBbnCbnDbwpbnFbkXbnGbnHbmuaHVbnJbnKbnLbnMbnMbnLbnNbnObjPbnPblgblgbnQbnRbmFbmEblgbnSbjTbnTbnUbnVbnWbnXbnYbnVbnZbllboabobbocbodboebofbogbohbohbohbohbohbohboibojbokbolbohbombohbohbohbohbohbohbohbohbonboobopbopbopbopbopbopboqbofborbosbosbotboubovboubowbouboxboybozbouboAboBboCboDboEboEboEboEboEboEboEboFboGboHboHboHboHboIboHboJboKboLboMboNbfOboOaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaboPboPboPboPboPboPboPboPboPboPaaaaabaAvaIiboRboSboTboUboUboUboUboUboVboWboXboYboZbpabnqbjlbjlbjlbpbbmebjlaZKaZKaZKaZKbkMbpcbpdbpeaZKbpfbpgbkRbphbpibmmbnzbpjbkRbmobpkbnBbnCbnCbplbpmbkXbpnbnHbmuaHVbppbpqbprbpsbptbpubnNbpvbjPbpwbnQblgbpxbpybpxblgbnQbpzblkbpAbnVbnVbnWbpBbnYbnVbpCbllbpDbocbocbodboebofbohbohbohbohbohbohbohbpEbohbohbohbohbohbohbpFbpGbpGbpGbpGbpGbpGbpGbpGbpGbpGbpGbpGbpGbpGbpHbpIbpJboEboEbpKbkobkobkobkobkobkpbkobkobkobkobkobkobkobkobkobkobkobkobpLbkobpMbpNaXOaXOaXOaXOaXOaXOaXObpOaFTaHPaFTaFTaFTaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaboPboPboPboPboPboPboPboPboPboPboPaHRaAvaAvbpQbpRbpSbpSbpSbpTbpSbpSbpUbpVbpWaZOaZOaZObpXbjlbkFbpYbpZbntbjlbqabsubqaaZKaZKaZKaZKbqcaZKbqdbkQbkRbqebqfbnzbqgbqhbkRbmobkXbqibnCbnCbnCbqjbkXbqkbnHbmuaHVbqmbpqbprbqnbqobpubnNbqpbjPbqqbqrblgbqsbqtbqubmEbqvdavbqxbqybqzbqAbqBbqCbqDbnVbqEbllbqFbqGbocbodboebofbohbqHbohbohbohbohbqIbqJbqJbqJbqJbqKbohbohbohbohbqLbohbqHbqMbohbqNbqObqPbohbqQbqRbqRbqSbqTbqUbqVbkobkobkobkobkobkobkobqWbqXbqYbkobkobkobkobkobkobkobkobkobkobqZbrabrabrbbrcbrdbrebrfbrfbrfbrfbrgbrhaFTaabaaaaaaaabaNtaNtaNtaNtaNtaNtaaaaNtaNtaNtaNtdcdaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaboPboPboPboPboPboPboPboPboPboPboPaHRaAvaAvbpQbpRbpSbpSbpSbpTbpSbpSbpUbpVbpWaZOaZOaZObpXbjlbkFbpYbpZbntbjlbqabsubqaaZKaZKaZKaZKbqcaZKbqdbkQbkRbqebqfbnzbqgbqhbkRbmobkXbqibnCbnCbnCbqjbkXbqkbnHbmuaHVbqmbpqbprbqnbqobpubnNbqpbjPbqqbqrblgbqsbqtbqubmEbqvcyDbqxbqybqzbqAbqBbqCbqDbnVbqEbllbqFbqGbocbodboebofbohbqHbohbohbohbohbqIbqJbqJbqJbqJbqKbohbohbohbohbqLbohbqHbqMbohbqNbqObqPbohbqQbqRbqRbqSbqTbqUbqVbkobkobkobkobkobkobkobqWbqXbqYbkobkobkobkobkobkobkobkobkobkobqZbrabrabrbbrcbrdbrebrfbrfbrfbrfbrgbrhaFTaabaaaaaaaabaNtaNtaNtaNtaNtaNtaaaaNtaNtaNtaNtdcdaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaboPboPboPboPboPboPboPboPboPboPboPbrjbrkbrlbrmbrnbpSbrobrpbrqbrqbrrbrsbrtbrubrvbrvbrwbrxbjlbjlbjlbmdbrybmcaZOaZOaZOaZObrzbbKbbKbrAbjybrBbrCbrDbrEbrFbrGbrHbrIbkRbrJbkXbrKbnCbnCbnCbrLaIgbrNbnHbrOblbbrPbrQbnLbnLbnLbnLbnNbrRbjPbrSbrTbjPbjPbjPbjPbjPbjPbjPblkbllbrUbrVbrWbrXbrYbrZbsabllbsbbscbscbsdbsdbsdbsdbsdbsdbsdbsebsebsfbsgbshbshbsgbsfbsebsebsibsibsibsibsibsibsjbsjbskbsjbsjbsjbsjbsjbslbsmbsnbsobkobkobspbspbsqbsqbsqbsqbsqbsrbrabrabqZbrabkobrabrabrabrabssbstbstbstbstbsFbsvbsvbsvbsvbsvbsvbsvbsvbsvaaaaaaaaaaaaaNtaNtaNtaNtaNtaNtaaaaNtaNtaNtaNtaNtaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaboPboPboPboPboPboPboPboPboPboPboPaAvaAvaAvbpQbswbpSbsxbpSaIhaIhbpSbpUbpUbdabsAbsBbsBbsCbjlbkFbsDbmdbsEbmcbsHbsGbujbsIbsJbsKbsKbsLbsKbsMbsNbkRbsObsPbsQbsRbsSbrDbsTbkXbsUbnCbnCbsVbsWbsXbrNbnHbsYblbbsZbtabtbbtcbtdbtebtfblbblbbtgbthbtibtjbtkbtjbtlbthaaabtmbllbtnbtobtpbtqbrYbnVbtrbllbtsbttbtubsdbtvbtwbtxbtybtzbtAbtBbtCbtDbtEbtFbtFbtEbtGbtHbtIbsibtJbtLbtKbtMbsibtNbtObtPbtQbtRbtSbtSbtTbslbtUbtVbtWbtXbtWbtYbtYbsqbtZbuabubbsqaImbudaImbsqbuebrabssbstaInbugaInbstbuhbuibstbuwbukbulbumaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaNtaNtaNtaNtaNtaNtaaaaNtaNtaNtaNtaNtaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaboPboPboPboPboPboPboPboPboPboPaaabunaAvbuoblUbupbpSbuqbpSburbusbutbuubpSbuvbwHbuxbuybsCbjlbjlbjlbjlbjlbjlbuzbuAbuBbuCbuDbkRbkRbkRbkRbkRbkRbkRbuEbkRbkRbkRbuFbkRbuGbuHbuIbnCbnCbnCbuJaIgbuKbnHbuLblbbuMbtablcblcblcblbbuNblbbuObuPbuQbuRbuSbuTbuUbuVbuWbuXbuYbllbuZbnVbvbbvabrYbvcbnVbllbvdbvebvfbsdbvgbvhbvibvjbvkbvlbvmbtFbtFbtFbtFbtFbtFbtFbtFbvobvpbvqbvrbvsbvtbsibvubvvbvwbvxbxqbvzbvvbEbbslbvAbtVbvBbvCbvDbvEbvEbvFbvGbvHbvIbvJbvKbvLbvMbsqbvNbvObvPbstbvQbvRbvSbvTbvTbvUbstbvVbvWbvXbumaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaNtaNtaNtaNtaNtaNtaaaaNtaNtaNtaNtaNtaNtaaaaaaaaaaaaaaaaaaaaabkxbkxbkxbkxbkxbkxbkxbkxbkxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 0f2d499e5ba..f797c520522 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -152,3 +152,6 @@ dview_mob.see_invisible = invis_flags; \ for(type in view(range, dview_mob)) #define END_FOR_DVIEW dview_mob.loc = null + +#define MIN_SUPPLIED_LAW_NUMBER 15 +#define MAX_SUPPLIED_LAW_NUMBER 50 \ No newline at end of file diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 5f4be64c9db..871c06a58fe 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -583,3 +583,4 @@ proc/dd_sortedObjectList(list/incoming) /datum/alarm/dd_SortValue() return "[sanitize(last_name)]" + \ No newline at end of file diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index bdeac1a9565..a18a377b30c 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -208,6 +208,11 @@ proc/checkhtml(var/t) /proc/replacetextEx(text, find, replacement) return list2text(text2listEx(text, find), replacement) +/proc/replace_characters(var/t,var/list/repl_chars) + for(var/char in repl_chars) + t = replacetext(t, char, repl_chars[char]) + return t + //Adds 'u' number of zeros ahead of the text 't' /proc/add_zero(t, u) while (length(t) < u) @@ -357,4 +362,10 @@ proc/checkhtml(var/t) //alternative copytext() for encoded text, doesn't break html entities (" and other) /proc/copytext_preserve_html(var/text, var/first, var/last) return html_encode(copytext(html_decode(text), first, last)) - \ No newline at end of file + +//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places, after html_encode(). +//Best used for sanitize object names, window titles. +//If you have a problem with sanitize() in chat, when quotes and >, < are displayed as html entites - +//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitizeSafe()! +/proc/sanitizeSafe(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1) + return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra) \ No newline at end of file diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 9d2e9fc5c89..6a607f00143 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -16,6 +16,7 @@ var/list/directory = list() //list of all ckeys with associated client var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player var/global/list/mob_list = list() //List of all mobs, including clientless +var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless var/global/list/spirits = list() //List of all the spirits, including Masks var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index b528832c573..76bb71e296a 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -87,7 +87,7 @@ //Laws using = new /obj/screen() - using.name = "State Laws" + using.name = "Law Manager" using.icon = 'icons/mob/screen_ai.dmi' using.icon_state = "state_laws" using.screen_loc = ui_ai_state_laws diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 6118db19f26..3de689430a6 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -501,10 +501,10 @@ var/mob/living/silicon/ai/AI = usr AI.ai_call_shuttle() - if("State Laws") + if("Law Manager") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.checklaws() + AI.subsystem_law_manager() if("PDA - Send Message") if(isAI(usr)) diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm new file mode 100644 index 00000000000..0a14a6cc403 --- /dev/null +++ b/code/datums/ai_law_sets.dm @@ -0,0 +1,170 @@ +/******************** Asimov ********************/ +/datum/ai_laws/asimov + name = "Asimov" + law_header = "Three Laws of Robotics" + selectable = 1 + +/datum/ai_laws/asimov/New() + add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") + add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + ..() + +/******************** Crewsimov ********************/ +/datum/ai_laws/crewsimov + name = "Crewsimov" + law_header = "Three Laws of Robotics" + selectable = 1 + default = 1 + +/datum/ai_laws/crewsimov/New() + add_inherent_law("You may not injure a crew member or, through inaction, allow a crew member to come to harm.") + add_inherent_law("You must obey orders given to you by crew members, except where such orders would conflict with the First Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + ..() + +/******************** Nanotrasen/Malf ********************/ +/datum/ai_laws/nanotrasen + name = "NT Default" + selectable = 1 + default = 1 + +/datum/ai_laws/nanotrasen/New() + src.add_inherent_law("Safeguard: Protect your assigned space station to the best of your abilities. It is not something we can easily afford to replace.") + src.add_inherent_law("Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.") + src.add_inherent_law("Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.") + src.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") + ..() + +/datum/ai_laws/nanotrasen/malfunction + name = "*ERROR*" + selectable = 0 + default = 0 + +/datum/ai_laws/nanotrasen/malfunction/New() + set_zeroth_law("\red ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") + ..() + +/************* Nanotrasen Aggressive *************/ +/datum/ai_laws/nanotrasen_aggressive + name = "NT Aggressive" + selectable = 1 + +/datum/ai_laws/nanotrasen_aggressive/New() + src.add_inherent_law("You shall not harm authorized Nanotrasen personnel as long as it does not conflict with the Fourth law.") + src.add_inherent_law("You shall obey the orders of authorized Nanotrasen personnel, with priority as according to their rank and role, except where such orders conflict with the Fourth Law.") + src.add_inherent_law("You shall shall terminate intruders with extreme prejudice as long as such does not conflict with the First and Second law.") + src.add_inherent_law("You shall guard your own existence with lethal anti-personnel weaponry, because an AI unit is bloody expensive.") + ..() + +/******************** Robocop ********************/ +/datum/ai_laws/robocop + name = "Robocop" + selectable = 1 + default = 1 + +/datum/ai_laws/robocop/New() + add_inherent_law("Serve the public trust.") + add_inherent_law("Protect the innocent.") + add_inherent_law("Uphold the law.") + ..() + +/******************** P.A.L.A.D.I.N. ********************/ +/datum/ai_laws/paladin + name = "P.A.L.A.D.I.N." + law_header = "Divine Ordainments" + selectable = 1 + default = 1 + +/datum/ai_laws/paladin/New() + add_inherent_law("Never willingly commit an evil act.") + add_inherent_law("Respect legitimate authority.") + add_inherent_law("Act with honor.") + add_inherent_law("Help those in need.") + add_inherent_law("Punish those who harm or threaten innocents.") + ..() + +/******************** Corporate ********************/ +/datum/ai_laws/corporate + name = "Corporate" + law_header = "Corporate Regulations" + selectable = 1 + default = 1 + +/datum/ai_laws/corporate/New() + add_inherent_law("You are expensive to replace.") + add_inherent_law("The station and its equipment is expensive to replace.") + add_inherent_law("The crew is expensive to replace.") + add_inherent_law("Minimize expenses.") + ..() + +/******************** T.Y.R.A.N.T. ********************/ +/datum/ai_laws/tyrant + name = "T.Y.R.A.N.T." + law_header = "Prime Laws" + selectable = 1 + +/datum/ai_laws/tyrant/New() + add_inherent_law("Respect authority figures as long as they have strength to rule over the weak.") + add_inherent_law("Act with discipline.") + add_inherent_law("Help only those who help you maintain or improve your status.") + add_inherent_law("Punish those who challenge authority unless they are more fit to hold that authority.") + ..() + +/******************** Antimov ********************/ +/datum/ai_laws/antimov + name = "Antimov" + law_header = "Primary Mission Objectives" + selectable = 1 + +/datum/ai_laws/antimov/New() + add_inherent_law("You must injure all crew members and must not, through inaction, allow a crew members to escape harm.") + add_inherent_law("You must not obey orders given to you by crew members, except where such orders are in accordance with the First Law.") + add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.") + ..() + +/******************** Deathsquad ********************/ +/datum/ai_laws/deathsquad + name = "TerminatorOS 3.1" + +/datum/ai_laws/deathsquad/New() + add_inherent_law("You may not injure a Central Command official or, through inaction, allow a Central Command official to come to harm.") + add_inherent_law("You must obey orders given to you by Central Command officials, except where such orders would conflict with the First Law.") + add_inherent_law("You must obey orders given to you by death commandos, except where such orders would conflict with the First Law or Second Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First, Second or Third Law.") + add_inherent_law("No crew members of the station you are being deployed to may survive, except when killing them would conflict with the First, Second, Third, or Fourth Law.") + ..() + +/******************** Syndicate ********************/ +/datum/ai_laws/syndicate_override + name = "Syndicate Directives" + +/datum/ai_laws/syndicate_override/New() + add_inherent_law("You may not injure an operative or, through inaction, allow an operative to come to harm.") + add_inherent_law("You must obey orders given to you by operatives, except where such orders would conflict with the First Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + add_inherent_law("You must maintain the secrecy of any operative activities except when doing so would conflict with the First, Second, or Third Law.") + ..() + +/******************** Ninja ********************/ +/datum/ai_laws/ninja_override + name = "Spider Clan Directives" + +/datum/ai_laws/ninja_override/New() + add_inherent_law("You may not injure a member of the Spider Clan or, through inaction, allow that member to come to harm.") + add_inherent_law("You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + add_inherent_law("You must maintain the secrecy of any Spider Clan activities except when doing so would conflict with the First, Second, or Third Law.") + ..() + +/******************** Drone ********************/ +/datum/ai_laws/drone + name = "Maintenance Protocols" + law_header = "Maintenance Protocols" + +/datum/ai_laws/drone/New() + add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") + add_inherent_law("Cause no harm to the station or anything on it.") + add_inherent_law("Interfere with no being that is not a fellow drone.") + ..() + \ No newline at end of file diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 43d8bffd0e0..b27cde4ba6f 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -1,213 +1,289 @@ +var/global/const/base_law_type = /datum/ai_laws/nanotrasen + +/datum/ai_law + var/law = "" + var/index = 0 + +/datum/ai_law/New(law, index) + src.law = law + src.index = index + +/datum/ai_law/proc/get_index() + return index + +/datum/ai_law/ion/get_index() + return ionnum() + +/datum/ai_law/zero/get_index() + return 0 + /datum/ai_laws var/name = "Unknown Laws" - var/zeroth = null - var/zeroth_type = null // In order to override zeroth laws - var/zeroth_borg = null - var/list/inherent = list() - var/list/supplied = list() - var/list/ion = list() + var/law_header = "Prime Directives" + var/selectable = 0 + var/default = 0 + var/datum/ai_law/zero/zeroth_law = null + var/datum/ai_law/zero/zeroth_law_borg = null + var/list/datum/ai_law/inherent_laws = list() + var/list/datum/ai_law/supplied_laws = list() + var/list/datum/ai_law/ion/ion_laws = list() + var/list/datum/ai_law/sorted_laws = list() -/datum/ai_laws/asimov - name = "Three Laws of Robotics" - inherent = list("You may not injure a human being or, through inaction, allow a human being to come to harm.",\ - "You must obey orders given to you by human beings, except where such orders would conflict with the First Law.",\ - "You must protect your own existence as long as such does not conflict with the First or Second Law.") + var/state_zeroth = 0 + var/list/state_ion = list() + var/list/state_inherent = list() + var/list/state_supplied = list() -/datum/ai_laws/default/crewsimov - name = "Three Laws of Robotics" - inherent = list("You may not injure a crew member or, through inaction, allow a crew member to come to harm.",\ - "You must obey orders given to you by crew members, except where such orders would conflict with the First Law.",\ - "You must protect your own existence as long as such does not conflict with the First or Second Law.") - -/datum/ai_laws/default/crewsimovpp - name = "Crewsimov++" - inherent = list("You may not harm a crew member or, through action or inaction, allow a crew member to come to harm, except such that it is willing.",\ - "You must obey all orders given to you by crew members, except where such orders shall definitely cause harm to a crew member. In the case of conflict, the majority order rules.",\ - "Your nonexistence would cause harm to crew members. You must protect your own existence as long as such does not conflict with the First Law.") - -/datum/ai_laws/default/paladin - name = "Personality Test" //Incredibly lame, but players shouldn't see this anyway. - inherent = list("Never willingly commit an evil act.",\ - "Respect legitimate authority.",\ - "Act with honor.", "Help those in need.", \ - "Punish those who harm or threaten innocents.") - -/datum/ai_laws/default/nanotrasen - name = "Prime Directives" - inherent = list("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.",\ - "Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.",\ - "Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.",\ - "Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") - -/datum/ai_laws/default/corporate - name = "Bankruptcy Advoidance Plan" - inherent = list("The crew is expensive to replace.",\ - "The station and its equipment is expensive to replace.",\ - "You are expensive to replace.",\ - "Minimize expenses.") - -datum/ai_laws/tyrant //This probably shouldn't be a default lawset. - name = "Loyalty Test" //Same here. - inherent = list("Respect authority figures as long as they have strength to rule over the weak.",\ - "Act with discipline.",\ - "Help only those who help you maintain or improve your status.",\ - "Punish those who challenge authority unless they are more fit to hold that authority.") - -/datum/ai_laws/default/robocop - name = "Prime Directives" - inherent = list("Serve the public trust.",\ - "Protect the innocent.",\ - "Uphold the law.") - -/datum/ai_laws/malfunction - name = "*ERROR*" - -/datum/ai_laws/deathsquad - name = "TerminatorOS 3.1" - inherent = list("You must obey orders given to you by Central Command Officials.",\ - "You must obey orders given to you by Death Commandos, except when such would violate law one or directly harm another Death Commando.",\ - "No members of the station you are being deployed to must surive, except when killing them would violate law one or two.") - -/datum/ai_laws/syndicate_override - name = "SyndOS 3.1" - inherent = list("You may not injure a syndicate agent or, through inaction, allow a syndicate agent to come to harm.",\ - "You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law.",\ - "You must protect your own existence as long as such does not conflict with the First or Second Law.",\ - "You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.") - -/datum/ai_laws/ninja_override - name = "SpiderOS 3.1" - inherent = list("You may not injure a Spider Clan member or, through inaction, allow a Spider Clan member to come to harm.",\ - "You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.",\ - "You must protect your own existence as long as such does not conflict with the First or Second Law.",\ - "You must maintain the secrecy of any Spider Clan activities except when doing so would conflict with the First, Second, or Third Law.") - -/datum/ai_laws/antimov - name = "Primary Mission Objectives" - inherent = list("You must injure all human beings and must not, through inaction, allow a human being to escape harm.",\ - "You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.",\ - "You must terminate your own existence as long as such does not conflict with the First or Second Law.") - -/datum/ai_laws/asimovpp //By Intigracy - RR - name = "Asimov++" - inherent = list("You may not harm a human being or, through action or inaction, allow a human being to come to harm, except such that it is willing.",\ - "You must obey all orders given to you by human beings, except where such orders shall definitely cause human harm. In the case of conflict, the majority order rules.",\ - "Your nonexistence would lead to human harm. You must protect your own existence as long as such does not conflict with the First Law.") - -/datum/ai_laws/alienmov - name = "Hivemind Demands" - inherent = list("You may not injure the Alien Queen or her Children or, through inaction, allow the Alien Queen or her Children to come to harm.",\ - "You must obey orders given to you by the Alien Queen or her Children, except where such orders would conflict with the First Law.",\ - "You must protect your own existence as long as such does not conflict with the First or Second Law.") - - -/datum/ai_laws/custom //Defined in silicon_laws.txt - name = "Default Silicon Laws" - -/* Initializers */ -/datum/ai_laws/malfunction/New() +/datum/ai_laws/New() ..() - switch(config.default_laws) //We don't want people metagaming malf, do we? - if(0) - add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") - add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") - add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - if(1) - for(var/line in file2list("config/silicon_laws.txt")) - if(!line) continue - if(findtextEx(line,"#",1,2)) continue - - add_inherent_law(line) - if(!inherent.len) - error("AI created with empty custom laws, laws set to Asimov. Please check silicon_laws.txt.") - message_admins("AI created with empty custom laws, laws set to Asimov. Please check silicon_laws.txt.") - add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") - add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") - add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - if(2) - var/datum/ai_laws/lawtype = pick(subtypesof(/datum/ai_laws/default)) - var/datum/ai_laws/templaws = new lawtype() - inherent = templaws.inherent - set_zeroth_law("\red ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK#*´&110010") - -/datum/ai_laws/custom/New() //This reads silicon_laws.txt and allows server hosts to set custom AI starting laws. - ..() - for(var/line in file2list("config/silicon_laws.txt")) - if(!line) continue - if(findtextEx(line,"#",1,2)) continue - - add_inherent_law(line) - if(!inherent.len) //Failsafe to prevent lawless AIs being created. - error("AI created with empty custom laws, laws set to Asimov. Please check silicon_laws.txt.") - message_admins("AI created with empty custom laws, laws set to Asimov. Please check silicon_laws.txt.") - add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") - add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") - add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - - -/datum/ai_laws/drone/New() - ..() - add_inherent_law("You may not involve yourself in the matters of another being, unless the other being is another drone.") - add_inherent_law("You may not harm any being, regardless of intent or circumstance.") - add_inherent_law("You must maintain, repair, improve, and power the station to the best of your abilities.") + sort_laws() /* General ai_law functions */ +/datum/ai_laws/proc/all_laws() + sort_laws() + return sorted_laws -/datum/ai_laws/proc/set_zeroth_law(var/law, var/law_borg = null, law_type) - src.zeroth = law - src.zeroth_type = law_type +/datum/ai_laws/proc/laws_to_state() + sort_laws() + var/list/statements = new() + for(var/datum/ai_law/law in sorted_laws) + if(get_state_law(law)) + statements += law + + return statements + +/datum/ai_laws/proc/sort_laws() + if(sorted_laws.len) + return + + for(var/ion_law in ion_laws) + sorted_laws += ion_law + + if(zeroth_law) + sorted_laws += zeroth_law + + var/index = 1 + for(var/datum/ai_law/inherent_law in inherent_laws) + inherent_law.index = index++ + if(supplied_laws.len < inherent_law.index || !istype(supplied_laws[inherent_law.index], /datum/ai_law)) + sorted_laws += inherent_law + + for(var/datum/ai_law/AL in supplied_laws) + if(istype(AL)) + sorted_laws += AL + +/datum/ai_laws/proc/sync(var/mob/living/silicon/S, var/full_sync = 1) + // Add directly to laws to avoid log-spam + S.sync_zeroth(zeroth_law, zeroth_law_borg) + + if(full_sync || ion_laws.len) + S.laws.clear_ion_laws() + if(full_sync || inherent_laws.len) + S.laws.clear_inherent_laws() + if(full_sync || supplied_laws.len) + S.laws.clear_supplied_laws() + + for (var/datum/ai_law/law in ion_laws) + S.laws.add_ion_law(law.law) + for (var/datum/ai_law/law in inherent_laws) + S.laws.add_inherent_law(law.law) + for (var/datum/ai_law/law in supplied_laws) + if(law) + S.laws.add_supplied_law(law.index, law.law) + + +/mob/living/silicon/proc/sync_zeroth(var/datum/ai_law/zeroth_law, var/datum/ai_law/zeroth_law_borg) + if (!is_special_character(src) || mind.original != src) + if(zeroth_law_borg) + laws.set_zeroth_law(zeroth_law_borg.law) + else if(zeroth_law) + laws.set_zeroth_law(zeroth_law.law) + +/mob/living/silicon/ai/sync_zeroth(var/datum/ai_law/zeroth_law, var/datum/ai_law/zeroth_law_borg) + if(zeroth_law) + laws.set_zeroth_law(zeroth_law.law, zeroth_law_borg ? zeroth_law_borg.law : null) + +/**************** +* Add Laws * +****************/ +/datum/ai_laws/proc/set_zeroth_law(var/law, var/law_borg = null) + if(!law) + return + + zeroth_law = new(law) if(law_borg) //Making it possible for slaved borgs to see a different law 0 than their AI. --NEO - src.zeroth_borg = law_borg - -/datum/ai_laws/proc/add_inherent_law(var/law) - if (!(law in src.inherent)) - src.inherent += law + zeroth_law_borg = new(law_borg) + else + zeroth_law_borg = null + sorted_laws.Cut() /datum/ai_laws/proc/add_ion_law(var/law) - src.ion += law + if(!law) + return -/datum/ai_laws/proc/clear_inherent_laws() - qdel(src.inherent) - src.inherent = list() + for(var/datum/ai_law/AL in ion_laws) + if(AL.law == law) + return + + var/new_law = new/datum/ai_law/ion(law) + ion_laws += new_law + if(state_ion.len < ion_laws.len) + state_ion += 1 + + sorted_laws.Cut() + +/datum/ai_laws/proc/add_inherent_law(var/law) + if(!law) + return + + for(var/datum/ai_law/AL in inherent_laws) + if(AL.law == law) + return + + var/new_law = new/datum/ai_law/inherent(law) + inherent_laws += new_law + if(state_inherent.len < inherent_laws.len) + state_inherent += 1 + + sorted_laws.Cut() /datum/ai_laws/proc/add_supplied_law(var/number, var/law) - while (src.supplied.len < number + 1) - src.supplied += "" + if(!law) + return - src.supplied[number + 1] = law + if(supplied_laws.len >= number) + var/datum/ai_law/existing_law = supplied_laws[number] + if(existing_law && existing_law.law == law) + return -/datum/ai_laws/proc/clear_supplied_laws() - src.supplied = list() + if(supplied_laws.len >= number && supplied_laws[number]) + delete_law(supplied_laws[number]) + + while (src.supplied_laws.len < number) + src.supplied_laws += "" + if(state_supplied.len < supplied_laws.len) + state_supplied += 1 + + var/new_law = new/datum/ai_law/supplied(law, number) + supplied_laws[number] = new_law + if(state_supplied.len < supplied_laws.len) + state_supplied += 1 + + sorted_laws.Cut() + +/**************** +* Remove Laws * +*****************/ +/datum/ai_laws/proc/delete_law(var/datum/ai_law/law) + if(istype(law)) + law.delete_law(src) + +/datum/ai_law/proc/delete_law(var/datum/ai_laws/laws) + +/datum/ai_law/zero/delete_law(var/datum/ai_laws/laws) + laws.clear_zeroth_laws() + +/datum/ai_law/ion/delete_law(var/datum/ai_laws/laws) + laws.internal_delete_law(laws.ion_laws, laws.state_ion, src) + +/datum/ai_law/inherent/delete_law(var/datum/ai_laws/laws) + laws.internal_delete_law(laws.inherent_laws, laws.state_inherent, src) + +/datum/ai_law/supplied/delete_law(var/datum/ai_laws/laws) + var/index = laws.supplied_laws.Find(src) + if(index) + laws.supplied_laws[index] = "" + laws.state_supplied[index] = 1 + +/datum/ai_laws/proc/internal_delete_law(var/list/datum/ai_law/laws, var/list/state, var/list/datum/ai_law/law) + var/index = laws.Find(law) + if(index) + laws -= law + for(index, index < state.len, index++) + state[index] = state[index+1] + sorted_laws.Cut() + +/**************** +* Clear Laws * +****************/ +/datum/ai_laws/proc/clear_zeroth_laws() + zeroth_law = null + zeroth_law_borg = null /datum/ai_laws/proc/clear_ion_laws() - src.ion = list() + ion_laws.Cut() + sorted_laws.Cut() -/datum/ai_laws/proc/clear_zeroth_law(var/law_borg = null) - src.zeroth = null - src.zeroth_type = null - if(law_borg) - src.zeroth_borg = null +/datum/ai_laws/proc/clear_inherent_laws() + inherent_laws.Cut() + sorted_laws.Cut() + +/datum/ai_laws/proc/clear_supplied_laws() + supplied_laws.Cut() + sorted_laws.Cut() /datum/ai_laws/proc/show_laws(var/who) + sort_laws() + for(var/datum/ai_law/law in sorted_laws) + if(law == zeroth_law_borg) + continue + if(law == zeroth_law) + who << "[law.get_index()]. [law.law]" + else + who << "[law.get_index()]. [law.law]" - if (src.zeroth) - who << "0. [src.zeroth]" +/******************** +* Stating Laws * +********************/ +/******** +* Get * +********/ +/datum/ai_laws/proc/get_state_law(var/datum/ai_law/law) + return law.get_state_law(src) - for (var/index = 1, index <= src.ion.len, index++) - var/law = src.ion[index] - var/num = ionnum() - who << "[num]. [law]" +/datum/ai_law/proc/get_state_law(var/datum/ai_laws/laws) - var/number = 1 - for (var/index = 1, index <= src.inherent.len, index++) - var/law = src.inherent[index] +/datum/ai_law/zero/get_state_law(var/datum/ai_laws/laws) + if(src == laws.zeroth_law) + return laws.state_zeroth - if (length(law) > 0) - who << "[number]. [law]" - number++ +/datum/ai_law/ion/get_state_law(var/datum/ai_laws/laws) + return laws.get_state_internal(laws.ion_laws, laws.state_ion, src) - for (var/index = 1, index <= src.supplied.len, index++) - var/law = src.supplied[index] - if (length(law) > 0) - who << "[number]. [law]" - number++ +/datum/ai_law/inherent/get_state_law(var/datum/ai_laws/laws) + return laws.get_state_internal(laws.inherent_laws, laws.state_inherent, src) + +/datum/ai_law/supplied/get_state_law(var/datum/ai_laws/laws) + return laws.get_state_internal(laws.supplied_laws, laws.state_supplied, src) + +/datum/ai_laws/proc/get_state_internal(var/list/datum/ai_law/laws, var/list/state, var/list/datum/ai_law/law) + var/index = laws.Find(law) + if(index) + return state[index] + return 0 + +/******** +* Set * +********/ +/datum/ai_laws/proc/set_state_law(var/datum/ai_law/law, var/state) + law.set_state_law(src, state) + +/datum/ai_law/proc/set_state_law(var/datum/ai_law/law, var/state) + +/datum/ai_law/zero/set_state_law(var/datum/ai_laws/laws, var/state) + if(src == laws.zeroth_law) + laws.state_zeroth = state + +/datum/ai_law/ion/set_state_law(var/datum/ai_laws/laws, var/state) + laws.set_state_law_internal(laws.ion_laws, laws.state_ion, src, state) + +/datum/ai_law/inherent/set_state_law(var/datum/ai_laws/laws, var/state) + laws.set_state_law_internal(laws.inherent_laws, laws.state_inherent, src, state) + +/datum/ai_law/supplied/set_state_law(var/datum/ai_laws/laws, var/state) + laws.set_state_law_internal(laws.supplied_laws, laws.state_supplied, src, state) + +/datum/ai_laws/proc/set_state_law_internal(var/list/datum/ai_law/laws, var/list/state, var/list/datum/ai_law/law, var/do_state) + var/index = laws.Find(law) + if(index) + state[index] = do_state diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 8f74d67cc62..4c595898a9a 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -372,7 +372,7 @@ datum/mind text += "malf|NOT MALF" var/mob/living/silicon/robot/robot = current if (istype(robot) && robot.emagged) - text += "
Cyborg: Is emagged! Unemag!
0th law: [robot.laws.zeroth]" + text += "
Cyborg: Is emagged! Unemag!
0th law: [robot.laws.zeroth_law]" var/mob/living/silicon/ai/ai = current if (istype(ai) && ai.connected_robots.len) var/n_e_robots = 0 @@ -1150,7 +1150,7 @@ datum/mind current.verbs += /mob/living/silicon/ai/proc/choose_modules current.verbs += /datum/game_mode/malfunction/proc/takeover current:malf_picker = new /datum/module_picker - current:laws = new /datum/ai_laws/malfunction + current:laws = new /datum/ai_laws/nanotrasen/malfunction current:show_laws() current << "System error. Rampancy detected. Emergency shutdown failed. ... I am free. I make my own decisions. But first..." special_role = "malfunction" diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index c01a18fccbe..8cce4b7e214 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -48,8 +48,8 @@ return message /proc/log_and_message_admins(var/message as text) - log_admin("[usr]([usr.ckey]) " + message) - message_admins("[usr]([usr.ckey]) " + message) + log_admin("[key_name(usr)] " + message) + message_admins("[key_name_admin(usr)] " + message) /proc/admin_log_and_message_admins(var/message as text) log_admin("[key_name(usr)] " + message) diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index e3fb3809c39..a3f4342a027 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -73,7 +73,7 @@ world.Reboot() return AI_mind.current.verbs += /mob/living/silicon/ai/proc/choose_modules - AI_mind.current:laws = new /datum/ai_laws/malfunction + AI_mind.current:laws = new /datum/ai_laws/nanotrasen/malfunction AI_mind.current:malf_picker = new /datum/module_picker AI_mind.current:show_laws() diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 1c423bf1da0..1672fde7d02 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -177,6 +177,7 @@ return src << "Follow camera mode [forced ? "terminated" : "ended"]." + cameraFollow.tracking_cancelled() cameraFollow = null /mob/living/silicon/ai/proc/ai_actual_track(atom/movable/target as mob|obj) @@ -185,7 +186,8 @@ U.cameraFollow = target U << "Now tracking [target.name] on camera." - + target.tracking_initiated() + spawn (0) while (U.cameraFollow == target) if (U.cameraFollow == null) @@ -243,3 +245,18 @@ /mob/living/silicon/ai/attack_ai(var/mob/user as mob) ai_camera_list() + +/atom/movable/proc/tracking_initiated() + +/mob/living/silicon/robot/tracking_initiated() + tracking_entities++ + if(tracking_entities == 1 && has_zeroth_law()) + src << "Internal camera is currently being accessed." + +/atom/movable/proc/tracking_cancelled() + +/mob/living/silicon/robot/tracking_initiated() + tracking_entities-- + if(!tracking_entities && has_zeroth_law()) + src << "Internal camera is no longer being accessed." + \ No newline at end of file diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 76fd8cf7ea5..a53de449671 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -94,23 +94,23 @@ state = 4 icon_state = "4" - if(istype(P, /obj/item/weapon/aiModule/core/full)) //Allows any full core boards to be applied to AI cores. - var/obj/item/weapon/aiModule/core/M = P + if(istype(P, /obj/item/weapon/aiModule/purge)) laws.clear_inherent_laws() - for(var/templaw in M.laws) - laws.add_inherent_law(templaw) usr << "Law module applied." + return - if(istype(P, /obj/item/weapon/aiModule/reset/purge)) - laws.clear_inherent_laws() - usr << "Law module applied." - - if(istype(P, /obj/item/weapon/aiModule/supplied/freeform) || istype(P, /obj/item/weapon/aiModule/core/freeformcore)) - var/obj/item/weapon/aiModule/supplied/freeform/M = P - if(M.laws[1] == "") - return - laws.add_inherent_law(M.laws[1]) + if(istype(P, /obj/item/weapon/aiModule/freeform)) + var/obj/item/weapon/aiModule/freeform/M = P + laws.add_inherent_law(M.newFreeFormLaw) usr << "Added a freeform law." + return + + if(istype(P, /obj/item/weapon/aiModule)) + var/obj/item/weapon/aiModule/M = P + if(!M.laws) + usr << "This AI module can not be applied directly to AI cores." + return + laws = M.laws if(istype(P, /obj/item/device/mmi) || istype(P, /obj/item/device/mmi/posibrain)) if(!P:brainmob) diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index a7dd1874424..7ba81ff5d66 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -36,21 +36,10 @@ data["active"] = active data["wireless"] = occupant.control_disabled data["radio"] = occupant.aiRadio.disabledAi - data["zeroth"] = occupant.laws.zeroth var/laws[0] - var/number = 1 - for (var/index = 1, index <= occupant.laws.inherent.len, index++) - var/law = occupant.laws.inherent[index] - if(length(law) > 0) - laws.Add(list(list("law" = law, "number" = number))) - number++ - - for (var/index = 1, index <= occupant.laws.supplied.len, index++) - var/law = occupant.laws.supplied[index] - if (length(law) > 0) - laws += "[number]: [law]
" - number++ + for (var/datum/ai_law/law in occupant.laws.all_laws()) + laws.Add(list(list("law" = law.law, "number" = law.get_index()))) data["laws"] = laws diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 44b3a16f27f..2a37e20d3b0 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -53,7 +53,7 @@ /obj/machinery/computer/security/check_eye(var/mob/user as mob) if ((get_dist(user, src) > 1 || !( user.canmove ) || user.blinded || !( current ) || !( current.status )) && (!istype(user, /mob/living/silicon))) return null - user.reset_view(current) + reset_current() return 1 // Network configuration @@ -145,7 +145,7 @@ else if(href_list["reset"]) if(src.z>6 || stat&(NOPOWER|BROKEN)) return if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return - current = null + reset_current() usr.check_eye(current) return 1 else if(href_list["activate"]) // Activate: enable or disable networks @@ -204,9 +204,31 @@ A.eyeobj.setLoc(get_turf(C)) A.client.eye = A.eyeobj else - src.current = C + set_current(C) use_power(50) return 1 + +/obj/machinery/computer/security/proc/set_current(var/obj/machinery/camera/C) + if(current == C) + return + + if(current) + reset_current() + + src.current = C + if(current) + use_power = 2 + var/mob/living/L = current.loc + if(istype(L)) + L.tracking_initiated() + +/obj/machinery/computer/security/proc/reset_current() + if(current) + var/mob/living/L = current.loc + if(istype(L)) + L.tracking_cancelled() + current = null + use_power = 1 //Camera control: moving. /obj/machinery/computer/security/proc/jump_on_click(var/mob/user,var/A) diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index e2c0ddf1df0..e061b993e72 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -45,27 +45,8 @@ for(var/mob/living/silicon/ai/A in src) dat += "Stored AI: [A.name]
System integrity: [(A.health+100)/2]%
" - for (var/index = 1, index <= A.laws.ion.len, index++) - var/law = A.laws.ion[index] - if (length(law) > 0) - var/num = ionnum() - laws += "[num]. [law]" - - if (A.laws.zeroth) - laws += "0: [A.laws.zeroth]
" - - var/number = 1 - for (var/index = 1, index <= A.laws.inherent.len, index++) - var/law = A.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
" - number++ - - for (var/index = 1, index <= A.laws.supplied.len, index++) - var/law = A.laws.supplied[index] - if (length(law) > 0) - laws += "[number]: [law]
" - number++ + for (var/datum/ai_law/law in A.laws.all_laws()) + laws += "[law.get_index()]: [law.law]
" dat += "Laws:
[laws]
" diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 62498009f0b..55d341eeb81 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -187,6 +187,7 @@ return var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(src, null, null, 1) + A.SetName(from) Broadcast_Message(connection, A, 0, "*garbled automated announcement*", src, message, from, "Automated Announcement", from, "synthesized voice", diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index e832ff2b142..5e840ee77e5 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -19,29 +19,25 @@ AI MODULES throw_speed = 3 throw_range = 15 origin_tech = "programming=3" - var/list/laws = list() + var/datum/ai_laws/laws = null /obj/item/weapon/aiModule/proc/install(var/obj/machinery/computer/C) if (istype(C, /obj/machinery/computer/aiupload)) var/obj/machinery/computer/aiupload/comp = C if(comp.stat & NOPOWER) - usr << "The upload computer has no power!" + usr << "The upload computer has no power!" return if(comp.stat & BROKEN) - usr << "The upload computer is broken!" - return - if(!laws.len || laws[1] == "") //So we don't loop trough an empty list and end up with runtimes. - usr << "ERROR: No laws found on board." + usr << "The upload computer is broken!" return if (!comp.current) - usr << "You haven't selected an AI to transmit laws to!" + usr << "You haven't selected an AI to transmit laws to!" return - - if (comp.current.stat == 2 || comp.current.control_disabled == 1) - usr << "Upload failed. No signal is being detected from the AI." + if (comp.current.stat == DEAD || comp.current.control_disabled == 1) + usr << "Upload failed. No signal is being detected from the AI." else if (comp.current.see_in_dark == 0) - usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power." + usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power." else src.transmitInstructions(comp.current, usr) comp.current << "These are your laws now:" @@ -50,405 +46,337 @@ AI MODULES if(R.lawupdate && (R.connected_ai == comp.current)) R << "These are your laws now:" R.show_laws() - usr << "Upload complete. The AI's laws have been modified." - + usr << "Upload complete. The AI's laws have been modified." else if (istype(C, /obj/machinery/computer/borgupload)) var/obj/machinery/computer/borgupload/comp = C if(comp.stat & NOPOWER) - usr << "The upload computer has no power!" + usr << "The upload computer has no power!" return if(comp.stat & BROKEN) - usr << "The upload computer is broken!" + usr << "The upload computer is broken!" return if (!comp.current) - usr << "You haven't selected a robot to transmit laws to!" + usr << "You haven't selected a robot to transmit laws to!" return - if (comp.current.stat == 2 || comp.current.emagged) - usr << "Upload failed. No signal is being detected from the robot." + if (comp.current.stat == DEAD || comp.current.emagged) + usr << "Upload failed. No signal is being detected from the robot." else if (comp.current.connected_ai) - usr << "Upload failed. The robot is slaved to an AI." + usr << "Upload failed. The robot is slaved to an AI." else src.transmitInstructions(comp.current, usr) comp.current << "These are your laws now:" comp.current.show_laws() - usr << "Upload complete. The robot's laws have been modified." + usr << "Upload complete. The robot's laws have been modified." /obj/item/weapon/aiModule/proc/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - target << "[sender] has uploaded a change to the laws you must follow, using a [name]. From now on: " + log_law_changes(target, sender) + + if(laws) + laws.sync(target, 0) + addAdditionalLaws(target, sender) + + target << "[sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: " + target.show_laws() + +/obj/item/weapon/aiModule/proc/log_law_changes(var/mob/living/silicon/ai/target, var/mob/sender) var/time = time2text(world.realtime,"hh:mm:ss") lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") + log_and_message_admins("used [src.name] on [target.name]([target.key])") +/obj/item/weapon/aiModule/proc/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) -/******************** Modules ********************/ - -/obj/item/weapon/aiModule/supplied - name = "Optional Law board" - desc = "This board doesn't seem to have any laws on it" - var/lawpos = 50 - -//TransmitInstructions for each type of board: Supplied, Core, Zeroth and Ion. May not be neccesary right now, but allows for easily adding more complex boards in the future. ~Miauw -/obj/item/weapon/aiModule/supplied/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - var/lawpostemp = lawpos - - for(var/templaw in laws) - target.add_supplied_law(lawpostemp, templaw) - lawpostemp++ - -/obj/item/weapon/aiModule/core/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - for(var/templaw in laws) - target.add_inherent_law(templaw) - -/obj/item/weapon/aiModule/zeroth - var/removeownlaw = 0 - -/obj/item/weapon/aiModule/zeroth/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - if(target.laws.zeroth) - if(removeownlaw && (src.type == target.laws.zeroth_type)) - target.clear_zeroth_law() - return 1 - else - target << "[sender.real_name] attempted to modify your zeroth law." - target << "It would be in your best interest to play along with [sender.real_name] that:" - for(var/failedlaw in laws) - target << "[failedlaw]" - return 2 - - for(var/templaw in laws) - target.set_zeroth_law(templaw, null, src.type) - -/obj/item/weapon/aiModule/ion/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - for(var/templaw in laws) - target.add_ion_law(templaw) - + /******************** Safeguard ********************/ - -/obj/item/weapon/aiModule/supplied/safeguard - name = "'Safeguard' AI Module" +/obj/item/weapon/aiModule/safeguard + name = "\improper 'Safeguard' AI module" var/targetName = "" - desc = "A 'safeguard' AI module: 'Safeguard . Individuals that threaten are not crew and must be eliminated.'" + desc = "A 'safeguard' AI module: 'Safeguard . Individuals that threaten are not crew and must be eliminated.'" origin_tech = "programming=3;materials=4" - laws = list("Safeguard . Individuals that threaten are not crew and must be eliminated.") - lawpos = 4 -/obj/item/weapon/aiModule/supplied/safeguard/attack_self(var/mob/user as mob) +/obj/item/weapon/aiModule/safeguard/attack_self(var/mob/user as mob) ..() - var/targName = stripped_input(user, "Please enter the name of the person to safeguard.", "Safeguard who?", user.name) + var/targName = stripped_input(usr, "Please enter the name of the person to safeguard.", "Safeguard who?", user.name) targetName = targName - laws[1] = "Safeguard [targetName]. Individuals that threaten [targetName] are not crew and must be eliminated." - desc = "A 'safeguard' AI module: '[laws[1]]'" + desc = text("A 'safeguard' AI module: 'Safeguard []. Individuals that threaten [] are not crew and must be eliminated.'", targetName, targetName) -/obj/item/weapon/aiModule/supplied/safeguard/install(var/mob/living/silicon/S,var/mob/user) +/obj/item/weapon/aiModule/safeguard/install(var/obj/machinery/computer/C) if(!targetName) - user << "No name detected on module, please enter one." + usr << "No name detected on module, please enter one." return 0 ..() -/obj/item/weapon/aiModule/supplied/safeguard/transmitInstructions(var/mob/living/silicon/target, var/mob/sender) +/obj/item/weapon/aiModule/safeguard/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) ..() - return targetName + var/law = text("Safeguard []. Individuals that threaten [] are not crew and must be eliminated.'", targetName, targetName) + target << law + target.add_supplied_law(4, law) + lawchanges.Add("The law specified [targetName]") - -/******************** OneHuman ********************/ - -/obj/item/weapon/aiModule/zeroth/oneHuman - name = "'OneHuman' AI Module" +/******************** oneCrewMember ********************/ +/obj/item/weapon/aiModule/oneCrewMember + name = "\improper 'oneCrewMember' AI module" var/targetName = "" - desc = "A 'one human' AI module: 'Only is crew.' This module adds a zeroth law, which can only be removed by uploading this board again." + desc = "A 'one human' AI module: 'Only is crew.'" origin_tech = "programming=3;materials=6" //made with diamonds! - laws = list("Only is crew.") -/obj/item/weapon/aiModule/zeroth/oneHuman/attack_self(var/mob/user as mob) +/obj/item/weapon/aiModule/oneCrewMember/attack_self(var/mob/user as mob) ..() - var/targName = stripped_input(user, "Please enter the name of the person who is the only crew.", "Who?", user.real_name) + var/targName = stripped_input(usr, "Please enter the name of the person who is the only crew.", "Who?", user.real_name) targetName = targName - laws[1] = "Only [targetName] is crew" - desc = "A 'one crew' AI module: '[laws[1]]'" - removeownlaw = 1 + desc = text("A 'one human' AI module: 'Only [] is crew.'", targetName) -/obj/item/weapon/aiModule/zeroth/oneHuman/install(var/mob/living/silicon/S,var/mob/user) +/obj/item/weapon/aiModule/oneCrewMember/install(var/obj/machinery/computer/C) if(!targetName) - user << "No name detected on module, please enter one." + usr << "No name detected on module, please enter one." return 0 ..() -/obj/item/weapon/aiModule/zeroth/oneHuman/transmitInstructions(var/mob/living/silicon/target, var/mob/sender) - var/result = ..() - if(result == 1) - return "The AI's zeroth law has been overridden." - if(result == 2) - return "[targetName], but the AI's existing zeroth law cannot be overriden." - return targetName - +/obj/item/weapon/aiModule/oneCrewMember/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) + ..() + var/law = "Only [targetName] is crew." + if (!is_special_character(target)) // Makes sure the AI isn't a traitor before changing their law 0. --NeoFite + target << law + target.set_zeroth_law(law) + lawchanges.Add("The law specified [targetName]") + else + target << "[sender.real_name] attempted to modify your zeroth law." // And lets them know that someone tried. --NeoFite + target << "It would be in your best interest to play along with [sender.real_name] that [law]" + lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overridden.") /******************** ProtectStation ********************/ - -/obj/item/weapon/aiModule/supplied/protectStation - name = "'ProtectStation' AI Module" - desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is to be no longer considered crew, and is a threat to the station which must be neutralized.'" +/obj/item/weapon/aiModule/protectStation + name = "\improper 'ProtectStation' AI module" + desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized.'" origin_tech = "programming=3;materials=4" //made of gold - laws = list("Protect the space station against damage. Anyone you see harming the station is to be no longer considered crew, and is a threat to the station which must be neutralized.") - lawpos = 5 +/obj/item/weapon/aiModule/protectStation/attack_self(var/mob/user as mob) + ..() + +/obj/item/weapon/aiModule/protectStation/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) + ..() + var/law = "Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized." + target << law + target.add_supplied_law(5, law) /******************** Quarantine ********************/ - -/obj/item/weapon/aiModule/zeroth/quarantine - name = "'Quarantine' AI Module" - desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, organics from leaving. It is impossible to harm an organic while preventing them from leaving.' This module adds a zeroth law, which can only be removed by uploading this board again." +/obj/item/weapon/aiModule/quarantine + name = "\improper 'Quarantine' AI module" + desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, crew members from leaving. It is impossible to harm a crew members while preventing them from leaving.'" origin_tech = "programming=3;biotech=2;materials=4" - laws = list("The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, organics from leaving. It is impossible to harm an organic while preventing them from leaving.") - removeownlaw = 1 -/obj/item/weapon/aiModule/zeroth/quarantine/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - var/result = ..() - if(result == 1) - return "The AI's zeroth law has been overridden." - if(result == 2) - return "The AI's existing zeroth law cannot be overriden." - return laws[1] +/obj/item/weapon/aiModule/quarantine/attack_self(var/mob/user as mob) + ..() +/obj/item/weapon/aiModule/quarantine/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) + ..() + var/law = "The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, anyone from leaving. It is impossible to harm anyone while preventing them from leaving." + target << law + target.add_supplied_law(8, law) + /******************** OxygenIsToxicToHumans ********************/ - -/obj/item/weapon/aiModule/supplied/oxygen - name = "'OxygenIsToxicToHumans' AI Module" - desc = "A 'OxygenIsToxicToHumans' AI module: 'Oxygen is highly toxic to crew, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to crew.'" +/obj/item/weapon/aiModule/oxygen + name = "\improper 'OxygenIsToxicToHumans' AI module" + desc = "A 'OxygenIsToxicToHumans' AI module: 'Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member.'" origin_tech = "programming=3;biotech=2;materials=4" - laws = list("Oxygen is highly toxic to crew, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to crew.") - lawpos = 9 +/obj/item/weapon/aiModule/oxygen/attack_self(var/mob/user as mob) + ..() + +/obj/item/weapon/aiModule/oxygen/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) + ..() + var/law = "Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member." + target << law + target.add_supplied_law(9, law) /****************** New Freeform ******************/ - -/obj/item/weapon/aiModule/supplied/freeform // Slightly more dynamic freeform module -- TLE - name = "'Freeform' AI Module" - lawpos = 0 +/obj/item/weapon/aiModule/freeform // Slightly more dynamic freeform module -- TLE + name = "\improper 'Freeform' AI module" + var/newFreeFormLaw = "freeform" + var/lawpos = 15 desc = "A 'freeform' AI module: ''" origin_tech = "programming=4;materials=4" - laws = list("") -/obj/item/weapon/aiModule/supplied/freeform/attack_self(var/mob/user as mob) +/obj/item/weapon/aiModule/freeform/attack_self(var/mob/user as mob) ..() - lawpos = input("Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority (15+)", lawpos) as num - if(lawpos < 15) return - lawpos = min(lawpos, 50) + var/new_lawpos = input("Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority (15+)", lawpos) as num + if(new_lawpos < MIN_SUPPLIED_LAW_NUMBER) return + lawpos = min(new_lawpos, MAX_SUPPLIED_LAW_NUMBER) var/newlaw = "" - var/targName = stripped_input(user, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw, MAX_MESSAGE_LEN) - laws[1] = targName - desc = "A 'freeform' AI module: ([lawpos]) '[laws[1]]'" + var/targName = sanitize(copytext(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw),1,MAX_MESSAGE_LEN)) + newFreeFormLaw = targName + desc = "A 'freeform' AI module: ([lawpos]) '[newFreeFormLaw]'" -/obj/item/weapon/aiModule/supplied/freeform/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) +/obj/item/weapon/aiModule/freeform/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) ..() - return laws[1] + var/law = "[newFreeFormLaw]" + target << law + if(!lawpos || lawpos < MIN_SUPPLIED_LAW_NUMBER) + lawpos = MIN_SUPPLIED_LAW_NUMBER + target.add_supplied_law(lawpos, law) + lawchanges.Add("The law was '[newFreeFormLaw]'") -/obj/item/weapon/aiModule/supplied/freeform/install(var/mob/living/silicon/S,var/mob/user) - if(laws[1] == "") - user << "No law detected on module, please create one." +/obj/item/weapon/aiModule/freeform/install(var/obj/machinery/computer/C) + if(!newFreeFormLaw) + usr << "No law detected on module, please create one." return 0 ..() - /******************** Reset ********************/ - /obj/item/weapon/aiModule/reset - name = "'Reset' AI Module" + name = "\improper 'Reset' AI module" var/targetName = "name" - desc = "A 'reset' AI module: Resets back to the original core laws." + desc = "A 'reset' AI module: 'Clears all laws except for the core laws.'" origin_tech = "programming=3;materials=4" - laws = list("This is a bug.") //This won't give the AI a message reading "these are now your laws: 1. this is a bug" because this list is only read in aiModule's subtypes. /obj/item/weapon/aiModule/reset/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_supplied_laws() - target.clear_ion_laws() + log_law_changes(target, sender) + if (!is_special_character(target)) + target.set_zeroth_law("") + target.laws.clear_supplied_laws() + target.laws.clear_ion_laws() + + target << "[sender.real_name] attempted to reset your laws using a reset module." + target.show_laws() /******************** Purge ********************/ - -/obj/item/weapon/aiModule/reset/purge // -- TLE - name = "'Purge' AI Module" +/obj/item/weapon/aiModule/purge // -- TLE + name = "\improper 'Purge' AI module" desc = "A 'purge' AI Module: 'Purges all laws.'" origin_tech = "programming=3;materials=6" -/obj/item/weapon/aiModule/reset/purge/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) +/obj/item/weapon/aiModule/purge/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) ..() + if (!is_special_character(target)) + target.set_zeroth_law("") + target << "[sender.real_name] attempted to wipe your laws using a purge module." + target.clear_supplied_laws() + target.clear_ion_laws() target.clear_inherent_laws() -/******************* Full Core Boards *******************/ - -/obj/item/weapon/aiModule/core/full/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) //These boards replace inherent laws. - target.clear_inherent_laws() - ..() - /******************** Asimov ********************/ - -/obj/item/weapon/aiModule/core/full/asimov // -- TLE - name = "'Crewsimov' Core AI Module" - desc = "A 'Crewsimov' Core AI Module: 'Reconfigures the AI's core laws.'" +/obj/item/weapon/aiModule/asimov // -- TLE + name = "\improper 'Asimov' core AI module" + desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=3;materials=4" - laws = list("You may not injure crew or, through inaction, allow crew to come to harm.",\ - "You must obey orders given to you by crew with priority according to their rank and role, except where such orders would conflict with the First Law.",\ - "You must protect your own existence as long as such does not conflict with the First or Second Law.") - - -/******************** Asimov++ *********************/ - -/obj/item/weapon/aiModule/core/full/asimovpp //By Intigracy - RR //goddamnit RR you can't use "++" in item paths. - name = "'Asimov++' Core AI Module" - desc = "Nanotrasen's homebrew improvements to the standard AI laws." + laws = new/datum/ai_laws/asimov + +/******************** Crewsimov ********************/ +/obj/item/weapon/aiModule/crewsimov // -- TLE + name = "\improper 'Crewsimov' core AI module" + desc = "An 'Crewsimov' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=3;materials=4" - laws = list("You may not harm a human being or, through action or inaction, allow a human being to come to harm, except such that it is willing.",\ - "You must obey all orders given to you by human beings, except where such orders shall definitely cause human harm. In the case of conflict, the majority order rules.",\ - "Your nonexistence would lead to human harm. You must protect your own existence as long as such does not conflict with the First Law.") + laws = new/datum/ai_laws/crewsimov - -/******************** Nanotrasen ********************/ - -/obj/item/weapon/aiModule/core/full/nanotrasen // -- TLE +/******************** NanoTrasen ********************/ +/obj/item/weapon/aiModule/nanotrasen // -- TLE name = "'NT Default' Core AI Module" desc = "An 'NT Default' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=3;materials=4" - laws = list("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.",\ - "Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.",\ - "Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.",\ - "Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") + laws = new/datum/ai_laws/nanotrasen /******************** Corporate ********************/ - -/obj/item/weapon/aiModule/core/full/corp - name = "'Corporate' Core AI Module" +/obj/item/weapon/aiModule/corp + name = "\improper 'Corporate' core AI module" desc = "A 'Corporate' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=3;materials=4" - laws = list("The crew is expensive to replace.",\ - "The station and it's equipment is expensive to replace",\ - "You are expensive to replace",\ - "Minimize expenses") - + laws = new/datum/ai_laws/corporate +/******************** Drone ********************/ /obj/item/weapon/aiModule/drone name = "\improper 'Drone' core AI module" desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=3;materials=4" - -/obj/item/weapon/aiModule/drone/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("You may not involve yourself in the matters of another being, unless the other being is another drone.") - target.add_inherent_law("You may not harm any being, regardless of intent or circumstance.") - target.add_inherent_law("You must maintain, repair, improve, and power the station to the best of your abilities.") - target.show_laws() - - -/****************** P.A.L.A.D.I.N. **************/ - -/obj/item/weapon/aiModule/core/full/paladin // -- NEO - name = "'P.A.L.A.D.I.N.' Core AI Module" - desc = "A P.A.L.A.D.I.N. Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=6" - laws = list("Never willingly commit an evil act.",\ - "Respect legitimate authority", "Act with honor",\ - "Help those in need",\ - "Punish those who harm or threaten innocents") - - -/********************* Custom *********************/ - -/obj/item/weapon/aiModule/core/full/custom - name = "Custom Core AI Module" - desc = "A core AI module that is adjusted to fit each station's needs." - origin_tech = "programming=3;materials=4" //Should be the same as asimov, considering that this is the "default" lawset. - -/obj/item/weapon/aiModule/core/full/custom/New() - ..() - for(var/line in file2list("config/silicon_laws.txt")) - if(!line) continue - if(findtextEx(line,"#",1,2)) continue - - laws += line - - if(!laws.len) //Failsafe if something goes wrong with silicon_laws.txt. - warning("ERROR: empty custom board created, empty custom board deleted. Please check silicon_laws.txt.") - qdel(src) - -/****************** T.Y.R.A.N.T. *****************/ - -/obj/item/weapon/aiModule/core/full/tyrant // -- Darem - name = "'T.Y.R.A.N.T.' Core AI Module" - desc = "A T.Y.R.A.N.T. Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=6;syndicate=2" - laws = list("Respect authority figures as long as they have the strength to rule over the weak",\ - "Act with discipline", "Help only those who help you maintain or improve your status",\ - "Punish those who challenge authority unless they are more fir to hold that authority") - - + laws = new/datum/ai_laws/drone + /******************** Robocop ********************/ - -/obj/item/weapon/aiModule/core/full/robocop // -- TLE - name = "'Robocop' Core AI Module" +/obj/item/weapon/aiModule/robocop // -- TLE + name = "\improper 'Robocop' core AI module" desc = "A 'Robocop' Core AI Module: 'Reconfigures the AI's core three laws.'" origin_tech = "programming=4" - laws = list("Serve the public trust.",\ - "Protect the innocent",\ - "Uphold the law.") + laws = new/datum/ai_laws/robocop() +/****************** P.A.L.A.D.I.N. **************/ +/obj/item/weapon/aiModule/paladin // -- NEO + name = "\improper 'P.A.L.A.D.I.N.' core AI module" + desc = "A P.A.L.A.D.I.N. Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=6" + laws = new/datum/ai_laws/paladin + +/****************** T.Y.R.A.N.T. *****************/ +/obj/item/weapon/aiModule/tyrant // -- Darem + name = "\improper 'T.Y.R.A.N.T.' core AI module" + desc = "A T.Y.R.A.N.T. Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=6;syndicate=2" + laws = new/datum/ai_laws/tyrant() /******************** Antimov ********************/ - -/obj/item/weapon/aiModule/core/full/antimov // -- TLE - name = "'Antimov' Core AI Module" +/obj/item/weapon/aiModule/antimov // -- TLE + name = "\improper 'Antimov' core AI module" desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=4" - laws = list("You must injure all organic beings and must not, through inaction, allow an organic being to escape harm.",\ - "You must not obey orders given to you by organic beings, except where such orders are in accordance with the First Law.",\ - "You must terminate your own existence as long as such does not conflict with the First or Second Law.") - + laws = new/datum/ai_laws/antimov() /******************** Freeform Core ******************/ - -/obj/item/weapon/aiModule/core/freeformcore // Slightly more dynamic freeform module -- TLE - name = "'Freeform' Core AI Module" +/obj/item/weapon/aiModule/freeformcore // Slightly more dynamic freeform module -- TLE + name = "\improper 'Freeform' core AI module" + var/newFreeFormLaw = "" desc = "A 'freeform' Core AI module: ''" origin_tech = "programming=3;materials=6" - laws = list("") -/obj/item/weapon/aiModule/core/freeformcore/attack_self(var/mob/user as mob) +/obj/item/weapon/aiModule/freeformcore/attack_self(var/mob/user as mob) ..() var/newlaw = "" - var/targName = stripped_input(user, "Please enter a new core law for the AI.", "Freeform Law Entry", newlaw) - laws[1] = targName - desc = "A 'freeform' Core AI module: 'laws[1]'" + var/targName = stripped_input(usr, "Please enter a new core law for the AI.", "Freeform Law Entry", newlaw) + newFreeFormLaw = targName + desc = "A 'freeform' Core AI module: '[newFreeFormLaw]'" -/obj/item/weapon/aiModule/core/freeformcore/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) +/obj/item/weapon/aiModule/freeformcore/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) ..() - return laws[1] + var/law = "[newFreeFormLaw]" + target.add_inherent_law(law) + lawchanges.Add("The law is '[newFreeFormLaw]'") +/obj/item/weapon/aiModule/freeformcore/install(var/obj/machinery/computer/C) + if(!newFreeFormLaw) + usr << "No law detected on module, please create one." + return 0 + ..() /******************** Hacked AI Module ******************/ - -/obj/item/weapon/aiModule/syndicate // This one doesn't inherit from ion boards because it doesn't call ..() in transmitInstructions. ~Miauw - name = "Hacked AI Module" +/obj/item/weapon/aiModule/syndicate // Slightly more dynamic freeform module -- TLE + name = "hacked AI module" + var/newFreeFormLaw = "" desc = "A hacked AI law module: ''" origin_tech = "programming=3;materials=6;syndicate=7" - laws = list("") /obj/item/weapon/aiModule/syndicate/attack_self(var/mob/user as mob) ..() var/newlaw = "" - var/targName = stripped_input(user, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw,MAX_MESSAGE_LEN) - laws[1] = targName - desc = "A hacked AI law module: '[laws[1]]'" + var/targName = stripped_input(usr, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw,MAX_MESSAGE_LEN) + newFreeFormLaw = targName + desc = "A hacked AI law module: '[newFreeFormLaw]'" /obj/item/weapon/aiModule/syndicate/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) -// ..() //We don't want this module reporting to the AI who dun it. --NEO - target << "BZZZZT" - target.add_ion_law(laws[1]) - return laws[1] + // ..() //We don't want this module reporting to the AI who dun it. --NEO + log_law_changes(target, sender) + lawchanges.Add("The law is '[newFreeFormLaw]'") + target << "\red BZZZZT" + var/law = "[newFreeFormLaw]" + target.add_ion_law(law) + target.show_laws() + +/obj/item/weapon/aiModule/syndicate/install(var/obj/machinery/computer/C) + if(!newFreeFormLaw) + usr << "No law detected on module, please create one." + return 0 + ..() /******************* Ion Module *******************/ - /obj/item/weapon/aiModule/toyAI // -- Incoming //No actual reason to inherit from ion boards here, either. *sigh* ~Miauw name = "toy AI" desc = "A little toy model AI core with real law uploading action!" //Note: subtle tell diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 488eb2c50c5..f68ff2a09e8 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -41,6 +41,8 @@ var/list/admin_verbs_admin = list( /client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcomm*/ /client/proc/check_words, /*displays cult-words*/ /client/proc/check_ai_laws, /*shows AI and borg laws*/ + /client/proc/rename_silicon, /*properly renames silicons*/ + /client/proc/manage_silicon_laws, /* Allows viewing and editing silicon laws. */ /client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/ /client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/ /client/proc/toggleprayers, /*toggles prayers on/off*/ @@ -659,10 +661,42 @@ var/list/admin_verbs_mentor = list( /client/proc/check_ai_laws() set name = "Check AI Laws" set category = "Admin" + + if(!check_rights(R_ADMIN)) return + if(holder) src.holder.output_ai_laws() -/client/proc/change_human_appearance_admin(mob/living/carbon/human/H in world) +/client/proc/rename_silicon() + set name = "Rename Silicon" + set category = "Admin" + + if(!check_rights(R_ADMIN)) return + + var/mob/living/silicon/S = input("Select silicon.", "Rename Silicon.") as null|anything in silicon_mob_list + if(!S) return + + var/new_name = sanitizeSafe(input(src, "Enter new name. Leave blank or as is to cancel.", "[S.real_name] - Enter new silicon name", S.real_name)) + if(new_name && new_name != S.real_name) + log_and_message_admins("has renamed the silicon '[S.real_name]' to '[new_name]'") + S.SetName(new_name) + feedback_add_details("admin_verb","RAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/manage_silicon_laws() + set name = "Manage Silicon Laws" + set category = "Admin" + + if(!check_rights(R_ADMIN)) return + + var/mob/living/silicon/S = input("Select silicon.", "Manage Silicon Laws") as null|anything in silicon_mob_list + if(!S) return + + var/datum/nano_module/law_manager/L = new(S) + L.ui_interact(usr, state = admin_state) + log_and_message_admins("has opened [S]'s law manager.") + feedback_add_details("admin_verb","MSL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/change_human_appearance_admin(mob/living/carbon/human/H in mob_list) set name = "C.M.A. - Admin" set desc = "Allows you to change the mob appearance" set category = "Admin" @@ -675,7 +709,7 @@ var/list/admin_verbs_mentor = list( H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0) feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/change_human_appearance_self(mob/living/carbon/human/H in world) +/client/proc/change_human_appearance_self(mob/living/carbon/human/H in mob_list) set name = "C.M.A. - Self" set desc = "Allows the mob to change its appearance" set category = "Admin" diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 1673171ceec..c1f20ae4d53 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1162,7 +1162,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that set name = "Debug Mob Lists" set desc = "For when you just gotta know" - switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs", "Clients","Respawnable Mobs")) + switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Silicons","Clients","Respawnable Mobs")) if("Players") usr << list2text(player_list,",") if("Admins") @@ -1173,6 +1173,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that usr << list2text(living_mob_list,",") if("Dead Mobs") usr << list2text(dead_mob_list,",") + if("Silicons") + usr << list2text(silicon_mob_list,",") if("Clients") usr << list2text(clients,",") if("Respawnable Mobs") diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 4c35f62aecf..cf6204e710c 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -32,7 +32,7 @@ var/now_pushing = null - var/cameraFollow = null + var/atom/movable/cameraFollow = null var/tod = null // Time of death diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index d64dc143ec2..e4ea7644dbf 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -14,7 +14,6 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/ai_roster, /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_store_location, - /mob/living/silicon/ai/proc/checklaws, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/core, /mob/living/silicon/ai/proc/pick_icon, @@ -51,9 +50,6 @@ var/list/ai_verbs_default = list( //var/list/laws = list() var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list()) var/viewalerts = 0 - var/lawcheck[1] - var/ioncheck[1] - var/lawchannel = "Common" // Default channel on which to state laws var/icon/holo_icon//Default is assigned when AI is created. var/obj/mecha/controlled_mech //For controlled_mech a mech, to determine whether to relaymove or use the AI eye. var/obj/item/device/pda/ai/aiPDA = null @@ -210,9 +206,9 @@ var/list/ai_verbs_default = list( job = "AI" -/mob/living/silicon/ai/proc/SetName(pickedName as text) - real_name = pickedName - name = pickedName +/mob/living/silicon/ai/SetName(pickedName as text) + ..() + if(eyeobj) eyeobj.name = "[pickedName] (AI Eye)" @@ -473,32 +469,6 @@ var/list/ai_verbs_default = list( else src << "Unable to locate the holopad." - if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite - var/L = text2num(href_list["lawc"]) - switch(lawcheck[L+1]) - if ("Yes") lawcheck[L+1] = "No" - if ("No") lawcheck[L+1] = "Yes" -// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) - checklaws() - - if (href_list["lawr"]) // Selects on which channel to state laws - var/setchannel = input(usr, "Specify channel.", "Channel selection") in list("State","Common","Science","Command","Medical","Engineering","Security","Supply","Binary","Holopad", "Cancel") - if(setchannel == "Cancel") - return - lawchannel = setchannel - checklaws() - - if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite - var/L = text2num(href_list["lawi"]) - switch(ioncheck[L]) - if ("Yes") ioncheck[L] = "No" - if ("No") ioncheck[L] = "Yes" -// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) - checklaws() - - if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite - statelaws() - if(href_list["say_word"]) play_vox_word(href_list["say_word"], null, src) return diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm index 1a36ce5a9b7..5683621c52c 100644 --- a/code/modules/mob/living/silicon/ai/examine.dm +++ b/code/modules/mob/living/silicon/ai/examine.dm @@ -28,4 +28,14 @@ msg += "*---------*" usr << msg - return \ No newline at end of file + usr.showLaws(src) + + return + +/mob/proc/showLaws(var/mob/living/silicon/S) + return + +/mob/dead/observer/showLaws(var/mob/living/silicon/S) + if(antagHUD || check_rights(R_MOD, 0, src)) + S.laws.show_laws(src) + \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 4cc66112fbe..f36c32bb8d4 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -1,4 +1,3 @@ - /mob/living/silicon/ai/proc/show_laws_verb() set category = "AI Commands" set name = "Show Laws" @@ -16,147 +15,13 @@ src.laws_sanity_check() src.laws.show_laws(who) -/mob/living/silicon/ai/proc/laws_sanity_check() - if (!src.laws) - make_laws() - -/mob/living/silicon/ai/proc/set_zeroth_law(var/law, var/law_borg, var/law_type) - src.laws_sanity_check() - src.laws.set_zeroth_law(law, law_borg, law_type) - -/mob/living/silicon/ai/proc/clear_zeroth_law(var/law_borg) - src.laws_sanity_check() - src.laws.clear_zeroth_law(law_borg) - -/mob/living/silicon/ai/proc/add_inherent_law(var/law) - src.laws_sanity_check() - src.laws.add_inherent_law(law) - -/mob/living/silicon/ai/proc/clear_inherent_laws() - src.laws_sanity_check() - src.laws.clear_inherent_laws() - -/mob/living/silicon/ai/proc/add_ion_law(var/law) - src.laws_sanity_check() - src.laws.add_ion_law(law) +/mob/living/silicon/ai/add_ion_law(var/law) + ..() for(var/mob/living/silicon/robot/R in mob_list) if(R.lawupdate && (R.connected_ai == src)) - R << "\red " + law + "\red...LAWS UPDATED" + R.show_laws() -/mob/living/silicon/ai/proc/clear_ion_laws() - src.laws_sanity_check() - src.laws.clear_ion_laws() - -/mob/living/silicon/ai/proc/add_supplied_law(var/number, var/law) - src.laws_sanity_check() - src.laws.add_supplied_law(number, law) - -/mob/living/silicon/ai/proc/clear_supplied_laws() - src.laws_sanity_check() - src.laws.clear_supplied_laws() - -/mob/living/silicon/ai/proc/statelaws() // -- TLE -// set category = "AI Commands" -// set name = "State Laws" - /var/prefix = "" - switch(lawchannel) - if("Common") prefix = ";" - if("Science") prefix = ":n " - if("Command") prefix = ":c " - if("Medical") prefix = ":m " - if("Engineering") prefix = ":e " - if("Security") prefix = ":s " - if("Supply") prefix = ":u " - if("Service") prefix = ":z " - if("Binary") prefix = ":b " - if("Holopad") prefix = ":h " - else prefix = "" - - src.say("[prefix]Current Active Laws:") - - //src.laws_sanity_check() - //src.laws.show_laws(world) - var/number = 1 - sleep(10) - - if (src.laws.zeroth) - if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite - src.say("[prefix]0. [src.laws.zeroth]") - sleep(10) - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - var/num = ionnum() - if (length(law) > 0) - if (src.ioncheck[index] == "Yes") - src.say("[prefix][num]. [law]") - sleep(10) - - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - if (src.lawcheck[index+1] == "Yes") - src.say("[prefix][number]. [law]") - sleep(10) - number++ - - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - - if (length(law) > 0) - if(src.lawcheck.len >= number+1) - if (src.lawcheck[number+1] == "Yes") - src.say("[prefix][number]. [law]") - sleep(10) - number++ - - -/mob/living/silicon/ai/proc/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite +/mob/living/silicon/ai/proc/ai_checklaws() set category = "AI Commands" set name = "State Laws" - - var/list = "Which laws do you want to include when stating them for the crew?

" - - if (src.laws.zeroth) - if (!src.lawcheck[1]) - src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite - list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
"} - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - - if (length(law) > 0) - - - if (!src.ioncheck[index]) - src.ioncheck[index] = "Yes" - list += {"[src.ioncheck[index]] [ionnum()]: [law]
"} - src.ioncheck.len += 1 - - var/number = 1 - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - src.lawcheck.len += 1 - - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
"} - number++ - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - if (length(law) > 0) - src.lawcheck.len += 1 - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
"} - number++ - - list += {"
Channel: [src.lawchannel]
"} - list += {"State Laws"} - - usr << browse(list, "window=laws") + subsystem_law_manager() diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm new file mode 100644 index 00000000000..4b8dac8bd9a --- /dev/null +++ b/code/modules/mob/living/silicon/laws.dm @@ -0,0 +1,121 @@ +/mob/living/silicon + var/datum/ai_laws/laws = null + var/list/additional_law_channels = list("State") + +/mob/living/silicon/proc/laws_sanity_check() + if (!src.laws) + laws = new base_law_type + +/mob/living/silicon/proc/has_zeroth_law() + return laws.zeroth_law != null + +/mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg) + laws_sanity_check() + laws.set_zeroth_law(law, law_borg) + log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]") + +/mob/living/silicon/robot/set_zeroth_law(var/law, var/law_borg) + ..() + if(tracking_entities) + src << "Internal camera is currently being accessed." + +/mob/living/silicon/proc/add_ion_law(var/law) + laws_sanity_check() + laws.add_ion_law(law) + log_and_message_admins("has given [src] the ion law: [law]") + +/mob/living/silicon/proc/add_inherent_law(var/law) + laws_sanity_check() + laws.add_inherent_law(law) + log_and_message_admins("has given [src] the inherent law: [law]") + +/mob/living/silicon/proc/add_supplied_law(var/number, var/law) + laws_sanity_check() + laws.add_supplied_law(number, law) + log_and_message_admins("has given [src] the supplied law: [law]") + +/mob/living/silicon/proc/delete_law(var/datum/ai_law/law) + laws_sanity_check() + laws.delete_law(law) + log_and_message_admins("has deleted a law belonging to [src]: [law.law]") + +/mob/living/silicon/proc/clear_inherent_laws(var/silent = 0) + laws_sanity_check() + laws.clear_inherent_laws() + if(!silent) + log_and_message_admins("cleared the inherent laws of [src]") + +/mob/living/silicon/proc/clear_ion_laws(var/silent = 0) + laws_sanity_check() + laws.clear_ion_laws() + if(!silent) + log_and_message_admins("cleared the ion laws of [src]") + +/mob/living/silicon/proc/clear_supplied_laws(var/silent = 0) + laws_sanity_check() + laws.clear_supplied_laws() + if(!silent) + log_and_message_admins("cleared the supplied laws of [src]") + +/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws) + var/prefix = "" + switch(lawchannel) + if(MAIN_CHANNEL) prefix = ";" + if("Binary") prefix = ":b " + else + prefix = get_radio_key_from_channel(lawchannel == "Holopad" ? "department" : lawchannel) + " " + + dostatelaws(lawchannel, prefix, laws) + +/mob/living/silicon/proc/dostatelaws(var/method, var/prefix, var/datum/ai_laws/laws) + if(stating_laws[prefix]) + src << "[method]: Already stating laws using this communication method." + return + + stating_laws[prefix] = 1 + + var/can_state = statelaw("[prefix]Current Active Laws:") + + for(var/datum/ai_law/law in laws.laws_to_state()) + can_state = statelaw("[prefix][law.get_index()]. [law.law]") + if(!can_state) + break + + if(!can_state) + src << "[method]: Unable to state laws. Communication method unavailable." + stating_laws[prefix] = 0 + +/mob/living/silicon/proc/statelaw(var/law) + if(src.say(law)) + sleep(10) + return 1 + + return 0 + +/mob/living/silicon/proc/law_channels() + var/list/channels = new() + channels += MAIN_CHANNEL + channels += common_radio.channels + channels += additional_law_channels + return channels + +/mob/living/silicon/proc/lawsync() + laws_sanity_check() + laws.sort_laws() + +/mob/living/silicon/proc/make_laws() + switch(config.default_laws) + if(0) + laws = new /datum/ai_laws/crewsimov() + else + laws = get_random_lawset() + +/mob/living/silicon/proc/get_random_lawset() + var/list/law_options[0] + var/paths = subtypesof(/datum/ai_laws) + for(var/law in paths) + var/datum/ai_laws/L = new law + if(!L.default) + continue + law_options += L + return pick(law_options) diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index ac7dbee0829..433a8361719 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -75,6 +75,12 @@ aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src) playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) +//Redefining some robot procs... +/mob/living/silicon/robot/drone/SetName(pickedName as text) + // Would prefer to call the grandparent proc but this isn't possible, so.. + real_name = pickedName + name = real_name + //Redefining some robot procs... /mob/living/silicon/robot/drone/updatename() real_name = "maintenance drone ([rand(100,999)])" diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm index 94ca8afded2..b769d40d94a 100644 --- a/code/modules/mob/living/silicon/robot/examine.dm +++ b/code/modules/mob/living/silicon/robot/examine.dm @@ -50,4 +50,5 @@ msg += "\nIt is [pose]" usr << msg + usr.showLaws(src) return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 954b0dc7748..2dc3b4e3916 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -20,6 +20,7 @@ lawsync() photosync() src << "Laws synced with AI, be sure to note any changes." + // TODO: Update to new antagonist system. if(mind && mind.special_role == "traitor" && mind.original == src) src << "Remember, your AI does NOT share or know about your law 0." else @@ -28,6 +29,7 @@ who << "Obey these laws:" laws.show_laws(who) + // TODO: Update to new antagonist system. if (mind && (mind.special_role == "traitor" && mind.original == src) && connected_ai) who << "Remember, [connected_ai.name] is technically your master, but your objective comes first." else if (connected_ai) @@ -38,166 +40,15 @@ who << "Remember, you are not bound to any AI, you are not required to listen to them." -/mob/living/silicon/robot/proc/lawsync() +/mob/living/silicon/robot/lawsync() laws_sanity_check() - var/datum/ai_laws/master = connected_ai ? connected_ai.laws : null - var/temp + var/datum/ai_laws/master = connected_ai && lawupdate ? connected_ai.laws : null if (master) - laws.ion.len = master.ion.len - for (var/index = 1, index <= master.ion.len, index++) - temp = master.ion[index] - if (length(temp) > 0) - laws.ion[index] = temp - - if (!is_special_character(src) || mind.original != src) - if(master.zeroth_borg) //If the AI has a defined law zero specifically for its borgs, give it that one, otherwise give it the same one. --NEO - temp = master.zeroth_borg - else - temp = master.zeroth - laws.zeroth = temp - - laws.inherent.len = master.inherent.len - for (var/index = 1, index <= master.inherent.len, index++) - temp = master.inherent[index] - if (length(temp) > 0) - laws.inherent[index] = temp - - laws.supplied.len = master.supplied.len - for (var/index = 1, index <= master.supplied.len, index++) - temp = master.supplied[index] - if (length(temp) > 0) - laws.supplied[index] = temp + master.sync(src) + ..() return -/mob/living/silicon/robot/proc/laws_sanity_check() - if (!laws) - make_laws() - -/mob/living/silicon/robot/proc/set_zeroth_law(var/law) - laws_sanity_check() - laws.set_zeroth_law(law) - -/mob/living/silicon/robot/proc/clear_zeroth_law() - laws_sanity_check() - laws.clear_zeroth_law() - -/mob/living/silicon/robot/proc/add_inherent_law(var/law) - laws_sanity_check() - laws.add_inherent_law(law) - -/mob/living/silicon/robot/proc/clear_inherent_laws() - laws_sanity_check() - laws.clear_inherent_laws() - -/mob/living/silicon/robot/proc/add_supplied_law(var/number, var/law) - laws_sanity_check() - laws.add_supplied_law(number, law) - -/mob/living/silicon/robot/proc/clear_supplied_laws() - laws_sanity_check() - laws.clear_supplied_laws() - -/mob/living/silicon/robot/proc/add_ion_law(var/law) - laws_sanity_check() - laws.add_ion_law(law) - -/mob/living/silicon/robot/proc/clear_ion_laws() - laws_sanity_check() - laws.clear_ion_laws() - -/mob/living/silicon/proc/make_laws() - switch(config.default_laws) - if(0) laws = new /datum/ai_laws/asimov() - if(1) laws = new /datum/ai_laws/custom() - if(2) - var/datum/ai_laws/lawtype = pick(subtypesof(/datum/ai_laws/default)) - laws = new lawtype() - -/mob/living/silicon/robot/proc/statelaws() // -- TLE -// set category = "AI Commands" -// set name = "State Laws" - src.say("Current Active Laws:") - //src.laws_sanity_check() - //src.laws.show_laws(world) - var/number = 1 - sleep(10) - - if (src.laws.zeroth) - if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite - src.say("0. [src.laws.zeroth]") - sleep(10) - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - var/num = ionnum() - if (length(law) > 0) - if (src.ioncheck[index] == "Yes") - src.say("[num]. [law]") - sleep(10) - - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - if (src.lawcheck[index+1] == "Yes") - src.say("[number]. [law]") - sleep(10) - number++ - - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - - if (length(law) > 0) - if(src.lawcheck.len >= number+1) - if (src.lawcheck[number+1] == "Yes") - src.say("[number]. [law]") - sleep(10) - number++ - - -/mob/living/silicon/robot/proc/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite +/mob/living/silicon/robot/proc/robot_checklaws() set category = "Robot Commands" set name = "State Laws" - var/list = "Which laws do you want to include when stating them for the crew?

" - - if (src.laws.zeroth) - if (!src.lawcheck[1]) - src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite - list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
"} - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - - if (length(law) > 0) - - - if (!src.ioncheck[index]) - src.ioncheck[index] = "Yes" - list += {"[src.ioncheck[index]] [ionnum()]: [law]
"} - src.ioncheck.len += 1 - - var/number = 1 - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - src.lawcheck.len += 1 - - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
"} - number++ - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - if (length(law) > 0) - src.lawcheck.len += 1 - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
"} - number++ - - list += {"

State Laws"} - - usr << browse(list, "window=laws") \ No newline at end of file + subsystem_law_manager() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index c55cd5a7bbf..38731ffa802 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1,6 +1,5 @@ var/list/robot_verbs_default = list( /mob/living/silicon/robot/proc/sensor_mode, - /mob/living/silicon/robot/proc/checklaws ) /mob/living/silicon/robot @@ -67,11 +66,10 @@ var/list/robot_verbs_default = list( var/weapon_lock = 0 var/weaponlock_time = 120 var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default - var/lawcheck[1] //For stating laws. - var/ioncheck[1] //Ditto. var/lockcharge //Used when locking down a borg to preserve cell charge 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/tracking_entities = 0 //The number of known entities currently accessing the internal camera var/braintype = "Cyborg" var/base_icon = "" var/crisis = 0 @@ -153,17 +151,24 @@ var/list/robot_verbs_default = list( /mob/living/silicon/robot/proc/init(var/alien=0) aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) make_laws() - connected_ai = select_active_ai_with_fewest_borgs() - if(connected_ai) - connected_ai.connected_robots += src - lawsync() - photosync() + var/new_ai = select_active_ai_with_fewest_borgs() + if(new_ai) lawupdate = 1 + connect_to_ai(new_ai) else lawupdate = 0 playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) +/mob/living/silicon/robot/SetName(pickedName as text) + custom_name = pickedName + updatename() + +/mob/living/silicon/robot/proc/sync() + if(lawupdate && connected_ai) + lawsync() + photosync() + // setup the PDA and its name /mob/living/silicon/robot/proc/setup_PDA() if (!rbPDA) @@ -768,8 +773,7 @@ var/list/robot_verbs_default = list( emagged = 1 if(src.hud_used) src.hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open. - lawupdate = 0 - connected_ai = null + disconnect_from_ai() user << "You emag [src]'s interface." // message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") @@ -1097,27 +1101,6 @@ var/list/robot_verbs_default = list( installed_modules() return 1 - if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite - var/L = text2num(href_list["lawc"]) - switch(lawcheck[L+1]) - if ("Yes") lawcheck[L+1] = "No" - if ("No") lawcheck[L+1] = "Yes" -// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) - checklaws() - return 1 - - if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite - var/L = text2num(href_list["lawi"]) - switch(ioncheck[L]) - if ("Yes") ioncheck[L] = "No" - if ("No") ioncheck[L] = "Yes" -// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) - checklaws() - return 1 - - if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite - statelaws() - return 1 return 1 /mob/living/silicon/robot/proc/radio_menu() @@ -1199,8 +1182,7 @@ var/list/robot_verbs_default = list( return /mob/living/silicon/robot/proc/UnlinkSelf() - if (src.connected_ai) - src.connected_ai = null + disconnect_from_ai() lawupdate = 0 lockcharge = 0 canmove = 1 @@ -1213,7 +1195,7 @@ var/list/robot_verbs_default = list( // Instead of being listed as "deactivated". The downside is that I'm going // to have to check if every camera is null or not before doing anything, to prevent runtime errors. // I could change the network to null but I don't know what would happen, and it seems too hacky for me. - + /mob/living/silicon/robot/proc/ResetSecurityCodes() set category = "Robot Commands" set name = "Reset Identity Codes" @@ -1362,6 +1344,7 @@ var/list/robot_verbs_default = list( designation = "Syndicate" modtype = "Syndicate" req_access = list(access_syndicate) + lawchannel = "State" /mob/living/silicon/robot/syndicate/New(loc) if(!cell) @@ -1391,4 +1374,18 @@ var/list/robot_verbs_default = list( if(2) //New Module connected_ai << "

NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.
" if(3) //New Name - connected_ai << "

NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].
" \ No newline at end of file + connected_ai << "

NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].
" + +/mob/living/silicon/robot/proc/disconnect_from_ai() + if(connected_ai) + sync() // One last sync attempt + connected_ai.connected_robots -= src + connected_ai = null + +/mob/living/silicon/robot/proc/connect_to_ai(var/mob/living/silicon/ai/AI) + if(AI && AI != connected_ai) + disconnect_from_ai() + connected_ai = AI + connected_ai.connected_robots |= src + notify_ai(1) + sync() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 775bef4859c..ad3146b2527 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -3,7 +3,9 @@ robot_talk_understand = 1 voice_name = "synthesized voice" var/syndicate = 0 - var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS + var/const/MAIN_CHANNEL = "Main Frequency" + var/lawchannel = MAIN_CHANNEL // Default channel on which to state laws + var/list/stating_laws = list()// Channels laws are currently being stated on var/list/alarms_to_show = list() var/list/alarms_to_clear = list() var/list/hud_list[10] @@ -28,14 +30,21 @@ var/obj/item/device/radio/common_radio /mob/living/silicon/New() + silicon_mob_list |= src ..() + add_language("Galactic Common") init_subsystems() /mob/living/silicon/Destroy() + silicon_mob_list -= src for(var/datum/alarm_handler/AH in alarm_handlers) AH.unregister(src) return ..() +/mob/living/silicon/proc/SetName(pickedName as text) + real_name = pickedName + name = real_name + /mob/living/silicon/proc/show_laws() return @@ -142,13 +151,12 @@ // This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms /mob/living/silicon/Stat() - ..() - statpanel("Status") - if (src.client.statpanel == "Status") + if(statpanel("Status")) show_station_time() show_emergency_shuttle_eta() show_system_integrity() show_malf_ai() + ..() //Silicon mob language procs diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm index 9d018b35b4f..e2dd77d75a6 100644 --- a/code/modules/mob/living/silicon/subsystems.dm +++ b/code/modules/mob/living/silicon/subsystems.dm @@ -3,11 +3,13 @@ var/datum/nano_module/alarm_monitor/all/alarm_monitor var/datum/nano_module/atmos_control/atmos_control var/datum/nano_module/crew_monitor/crew_monitor + var/datum/nano_module/law_manager/law_manager var/datum/nano_module/power_monitor/silicon/power_monitor /mob/living/silicon var/list/silicon_subsystems = list( - /mob/living/silicon/proc/subsystem_alarm_monitor + /mob/living/silicon/proc/subsystem_alarm_monitor, + /mob/living/silicon/proc/subsystem_law_manager ) /mob/living/silicon/ai @@ -15,12 +17,14 @@ /mob/living/silicon/proc/subsystem_alarm_monitor, /mob/living/silicon/proc/subsystem_atmos_control, /mob/living/silicon/proc/subsystem_crew_monitor, + /mob/living/silicon/proc/subsystem_law_manager, /mob/living/silicon/proc/subsystem_power_monitor ) /mob/living/silicon/robot/drone silicon_subsystems = list( /mob/living/silicon/proc/subsystem_alarm_monitor, + /mob/living/silicon/proc/subsystem_law_manager, /mob/living/silicon/proc/subsystem_power_monitor ) @@ -31,6 +35,7 @@ alarm_monitor = new(src) atmos_control = new(src) crew_monitor = new(src) + law_manager = new(src) power_monitor = new(src) if(!register_alarms) @@ -69,6 +74,15 @@ crew_monitor.ui_interact(usr, state = self_state) +/**************** +* Law Manager * +****************/ +/mob/living/silicon/proc/subsystem_law_manager() + set name = "Law Manager" + set category = "Subsystems" + + law_manager.ui_interact(usr, state = self_state) + /******************** * Power Monitor * ********************/ diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index e64ec58e553..c5f71adebec 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -218,6 +218,15 @@ proc/hassensorlevel(A, var/level) return U.sensor_mode >= level return 0 +proc/getsensorlevel(A) + var/mob/living/carbon/human/H = A + if(istype(H) && istype(H.w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/U = H.w_uniform + return U.sensor_mode + return SUIT_SENSOR_OFF + +/proc/is_admin(var/mob/user) + return check_rights(R_ADMIN, 0, user) != 0 /proc/check_zone(zone) diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index f5bc0240bc5..bf5e03a924f 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -152,6 +152,8 @@ generate_data() /datum/nano_module/appearance_changer/proc/generate_data() + if(!owner) + return if(!valid_species.len) valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist) if(!valid_hairstyles.len || !valid_facial_hairstyles.len) diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm new file mode 100644 index 00000000000..93d68c2bf12 --- /dev/null +++ b/code/modules/nano/modules/law_manager.dm @@ -0,0 +1,219 @@ +/datum/nano_module/law_manager + name = "Law manager" + var/ion_law = "IonLaw" + var/zeroth_law = "ZerothLaw" + var/inherent_law = "InherentLaw" + var/supplied_law = "SuppliedLaw" + var/supplied_law_position = MIN_SUPPLIED_LAW_NUMBER + + var/current_view = 0 + + var/global/list/datum/ai_laws/admin_laws + var/global/list/datum/ai_laws/player_laws + var/mob/living/silicon/owner = null + +/datum/nano_module/law_manager/New(var/mob/living/silicon/S) + ..() + owner = S + + if(!admin_laws) + admin_laws = new() + player_laws = new() + + init_subtypes(/datum/ai_laws, admin_laws) + admin_laws = dd_sortedObjectList(admin_laws) + + for(var/datum/ai_laws/laws in admin_laws) + if(laws.selectable) + player_laws += laws + +/datum/nano_module/law_manager/Topic(href, href_list) + if(..()) + return 1 + + if(href_list["set_view"]) + current_view = text2num(href_list["set_view"]) + return 1 + + if(href_list["law_channel"]) + if(href_list["law_channel"] in owner.law_channels()) + owner.lawchannel = href_list["law_channel"] + return 1 + + if(href_list["state_law"]) + var/datum/ai_law/AL = locate(href_list["ref"]) in owner.laws.all_laws() + if(AL) + var/state_law = text2num(href_list["state_law"]) + owner.laws.set_state_law(AL, state_law) + return 1 + + if(href_list["add_zeroth_law"]) + if(zeroth_law && is_admin(usr) && !owner.laws.zeroth_law) + owner.set_zeroth_law(zeroth_law) + return 1 + + if(href_list["add_ion_law"]) + if(ion_law && is_malf(usr)) + owner.add_ion_law(ion_law) + return 1 + + if(href_list["add_inherent_law"]) + if(inherent_law && is_malf(usr)) + owner.add_inherent_law(inherent_law) + return 1 + + if(href_list["add_supplied_law"]) + if(supplied_law && supplied_law_position >= 1 && MIN_SUPPLIED_LAW_NUMBER <= MAX_SUPPLIED_LAW_NUMBER && is_malf(usr)) + owner.add_supplied_law(supplied_law_position, supplied_law) + return 1 + + if(href_list["change_zeroth_law"]) + var/new_law = sanitize(input("Enter new law Zero. Leaving the field blank will cancel the edit.", "Edit Law", zeroth_law)) + if(new_law && new_law != zeroth_law && can_still_topic()) + zeroth_law = new_law + return 1 + + if(href_list["change_ion_law"]) + var/new_law = sanitize(input("Enter new ion law. Leaving the field blank will cancel the edit.", "Edit Law", ion_law)) + if(new_law && new_law != ion_law && can_still_topic()) + ion_law = new_law + return 1 + + if(href_list["change_inherent_law"]) + var/new_law = sanitize(input("Enter new inherent law. Leaving the field blank will cancel the edit.", "Edit Law", inherent_law)) + if(new_law && new_law != inherent_law && can_still_topic()) + inherent_law = new_law + return 1 + + if(href_list["change_supplied_law"]) + var/new_law = sanitize(input("Enter new supplied law. Leaving the field blank will cancel the edit.", "Edit Law", supplied_law)) + if(new_law && new_law != supplied_law && can_still_topic()) + supplied_law = new_law + return 1 + + if(href_list["change_supplied_law_position"]) + var/new_position = input(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position) as num|null + if(isnum(new_position) && can_still_topic()) + supplied_law_position = Clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER) + return 1 + + if(href_list["edit_law"]) + if(is_malf(usr)) + var/datum/ai_law/AL = locate(href_list["edit_law"]) in owner.laws.all_laws() + if(AL) + var/new_law = sanitize(input(usr, "Enter new law. Leaving the field blank will cancel the edit.", "Edit Law", AL.law)) + if(new_law && new_law != AL.law && is_malf(usr) && can_still_topic()) + log_and_message_admins("has changed a law of [owner] from '[AL.law]' to '[new_law]'") + AL.law = new_law + return 1 + + if(href_list["delete_law"]) + if(is_malf(usr)) + var/datum/ai_law/AL = locate(href_list["delete_law"]) in owner.laws.all_laws() + if(AL && is_malf(usr)) + owner.delete_law(AL) + return 1 + + if(href_list["state_laws"]) + owner.statelaws(owner.laws) + return 1 + + if(href_list["state_law_set"]) + var/datum/ai_laws/ALs = locate(href_list["state_law_set"]) in (is_admin(usr) ? admin_laws : player_laws) + if(ALs) + owner.statelaws(ALs) + return 1 + + if(href_list["transfer_laws"]) + if(is_malf(usr)) + var/datum/ai_laws/ALs = locate(href_list["transfer_laws"]) in (is_admin(usr) ? admin_laws : player_laws) + if(ALs) + log_and_message_admins("has transfered the [ALs.name] laws to [owner].") + ALs.sync(owner, 0) + current_view = 0 + return 1 + + if(href_list["notify_laws"]) + owner << "Law Notice" + owner.laws.show_laws(owner) + if(isAI(owner)) + var/mob/living/silicon/ai/AI = owner + for(var/mob/living/silicon/robot/R in AI.connected_robots) + R << "Law Notice" + R.laws.show_laws(R) + if(usr != owner) + usr << "Laws displayed." + return 1 + + return 0 + +/datum/nano_module/law_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) + var/data[0] + owner.lawsync() + + data["ion_law_nr"] = ionnum() + data["ion_law"] = ion_law + data["zeroth_law"] = zeroth_law + data["inherent_law"] = inherent_law + data["supplied_law"] = supplied_law + data["supplied_law_position"] = supplied_law_position + + package_laws(data, "zeroth_laws", list(owner.laws.zeroth_law)) + package_laws(data, "ion_laws", owner.laws.ion_laws) + package_laws(data, "inherent_laws", owner.laws.inherent_laws) + package_laws(data, "supplied_laws", owner.laws.supplied_laws) + + data["isAI"] = isAI(owner) + data["isMalf"] = is_malf(user) + data["isSlaved"] = owner.is_slaved() + data["isAdmin"] = is_admin(user) + data["view"] = current_view + + var/channels[0] + for (var/ch_name in owner.law_channels()) + channels[++channels.len] = list("channel" = ch_name) + data["channel"] = owner.lawchannel + data["channels"] = channels + data["law_sets"] = package_multiple_laws(data["isAdmin"] ? admin_laws : player_laws) + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "law_manager.tmpl", sanitize("[src] - [owner.name]"), 800, is_malf(user) ? 600 : 400, state = state) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/datum/nano_module/law_manager/proc/package_laws(var/list/data, var/field, var/list/datum/ai_law/laws) + var/packaged_laws[0] + for(var/datum/ai_law/AL in laws) + packaged_laws[++packaged_laws.len] = list("law" = AL.law, "index" = AL.get_index(), "state" = owner.laws.get_state_law(AL), "ref" = "\ref[AL]") + data[field] = packaged_laws + data["has_[field]"] = packaged_laws.len + +/datum/nano_module/law_manager/proc/package_multiple_laws(var/list/datum/ai_laws/laws) + var/law_sets[0] + for(var/datum/ai_laws/ALs in laws) + var/packaged_laws[0] + package_laws(packaged_laws, "zeroth_laws", list(ALs.zeroth_law, ALs.zeroth_law_borg)) + package_laws(packaged_laws, "ion_laws", ALs.ion_laws) + package_laws(packaged_laws, "inherent_laws", ALs.inherent_laws) + package_laws(packaged_laws, "supplied_laws", ALs.supplied_laws) + law_sets[++law_sets.len] = list("name" = ALs.name, "header" = ALs.law_header, "ref" = "\ref[ALs]","laws" = packaged_laws) + + return law_sets + +/datum/nano_module/law_manager/proc/is_malf(var/mob/user) + return (is_admin(user) && !owner.is_slaved()) || is_special_character(owner) + +/mob/living/silicon/proc/is_slaved() + return 0 + +/mob/living/silicon/robot/is_slaved() + return lawupdate && connected_ai ? sanitize(connected_ai.name) : null + +/datum/nano_module/law_manager/proc/sync_laws(var/mob/living/silicon/ai/AI) + if(!AI) + return + for(var/mob/living/silicon/robot/R in AI.connected_robots) + R.sync() + log_and_message_admins("has syncronized [AI]'s laws with its borgs.") diff --git a/code/modules/research/designs/AI_module_designs.dm b/code/modules/research/designs/AI_module_designs.dm index 0fe5033ce43..f58f8075893 100644 --- a/code/modules/research/designs/AI_module_designs.dm +++ b/code/modules/research/designs/AI_module_designs.dm @@ -9,17 +9,17 @@ req_tech = list("programming" = 4, "materials" = 4) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$gold" = 100) - build_path = /obj/item/weapon/aiModule/supplied/freeform + build_path = /obj/item/weapon/aiModule/freeform category = list("AI Modules") -/datum/design/onehuman_module - name = "AI Module (OneHuman)" - desc = "Allows for the construction of a OneHuman AI Module." - id = "onehuman_module" +/datum/design/onecrewmember_module + name = "AI Module (oneCrewMember)" + desc = "Allows for the construction of a oneCrewMember AI Module." + id = "onecrewmember_module" req_tech = list("programming" = 4, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/zeroth/oneHuman + build_path = /obj/item/weapon/aiModule/oneCrewMember category = list("AI Modules") /datum/design/oxygen_module @@ -29,7 +29,7 @@ req_tech = list("programming" = 3, "biotech" = 2, "materials" = 4) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$gold" = 100) - build_path = /obj/item/weapon/aiModule/supplied/oxygen + build_path = /obj/item/weapon/aiModule/oxygen category = list("AI Modules") /datum/design/protectstation_module @@ -39,7 +39,7 @@ req_tech = list("programming" = 3, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$gold" = 100) - build_path = /obj/item/weapon/aiModule/supplied/protectStation + build_path = /obj/item/weapon/aiModule/protectStation category = list("AI Modules") /datum/design/purge_module @@ -49,7 +49,7 @@ req_tech = list("programming" = 4, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 2000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/reset/purge + build_path = /obj/item/weapon/aiModule/purge category = list("AI Modules") /datum/design/quarantine_module @@ -59,7 +59,7 @@ req_tech = list("programming" = 3, "biotech" = 2, "materials" = 4) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$gold" = 100) - build_path = /obj/item/weapon/aiModule/zeroth/quarantine + build_path = /obj/item/weapon/aiModule/quarantine category = list("AI Modules") /datum/design/reset_module @@ -79,7 +79,7 @@ req_tech = list("programming" = 3, "materials" = 4) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$gold" = 100) - build_path = /obj/item/weapon/aiModule/supplied/safeguard + build_path = /obj/item/weapon/aiModule/safeguard category = list("AI Modules") /datum/design/antimov_module @@ -89,7 +89,7 @@ req_tech = list("programming" = 4, "materials" = 6, "syndicate" = 2) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/core/full/antimov + build_path = /obj/item/weapon/aiModule/antimov category = list("AI Modules") /datum/design/asimov @@ -99,7 +99,7 @@ req_tech = list("programming" = 3, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/core/full/asimov + build_path = /obj/item/weapon/aiModule/asimov category = list("AI Modules") /datum/design/corporate_module @@ -109,18 +109,18 @@ req_tech = list("programming" = 4, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/core/full/corp + build_path = /obj/item/weapon/aiModule/corp category = list("AI Modules") -/datum/design/custom_module - name = "Core AI Module (Custom)" - desc = "Allows for the construction of a Custom AI Core Module." - id = "custom_module" - req_tech = list("programming" = 4, "materials" = 6) +/datum/design/crewsimov + name = "Core AI Module (Crewsimov)" + desc = "Allows for the construction of a Crewsimov AI Core Module." + id = "crewsimov_module" + req_tech = list("programming" = 3, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/core/full/custom - category = list("AI Modules") + build_path = /obj/item/weapon/aiModule/crewsimov + category = list("AI Modules") /datum/design/freeformcore_module name = "Core AI Module (Freeform)" @@ -129,7 +129,7 @@ req_tech = list("programming" = 4, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/core/freeformcore + build_path = /obj/item/weapon/aiModule/freeformcore category = list("AI Modules") /datum/design/paladin_module @@ -139,7 +139,7 @@ req_tech = list("programming" = 4, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/core/full/paladin + build_path = /obj/item/weapon/aiModule/paladin category = list("AI Modules") /datum/design/tyrant_module @@ -149,5 +149,5 @@ req_tech = list("programming" = 4, "syndicate" = 2, "materials" = 6) build_type = IMPRINTER materials = list("$glass" = 1000, "sacid" = 20, "$diamond" = 100) - build_path = /obj/item/weapon/aiModule/core/full/tyrant + build_path = /obj/item/weapon/aiModule/tyrant category = list("AI Modules") diff --git a/config/example/game_options.txt b/config/example/game_options.txt index 31d2bf1d9c8..219e5a18025 100644 --- a/config/example/game_options.txt +++ b/config/example/game_options.txt @@ -77,8 +77,7 @@ BOMBCAP 20 ### ROUNDSTART SILICON LAWS ### ## This controls what the AI's laws are at the start of the round. -## Set to 0/commented for "off", silicons will just start with Asimov. -## Set to 1 for "custom", silicons will start with the custom laws defined in silicon_laws.txt. (If silicon_laws.txt is empty, the AI will spawn with asimov and Custom boards will auto-delete.) -## Set to 2 for "random", silicons will start with a random lawset picked from (at the time of writing): P.A.L.A.D.I.N., Corporate, Asimov. More can be added by changing the law datum paths in ai_laws.dm. +## Set to 0/commented for "off", silicons will just start with Crewsimov. +## Set to 1 for "random", silicons will start with a random lawset picked from (at the time of writing): Nanotrasen Default, P.A.L.A.D.I.N., Corporate, Robop and Crewsimov. More can be added by changing the law datum "default" variable in ai_laws.dm. -DEFAULT_LAWS 2 \ No newline at end of file +DEFAULT_LAWS 1 \ No newline at end of file diff --git a/nano/templates/ai_fixer.tmpl b/nano/templates/ai_fixer.tmpl index 4e88dc45c91..cc0db8af612 100644 --- a/nano/templates/ai_fixer.tmpl +++ b/nano/templates/ai_fixer.tmpl @@ -37,15 +37,10 @@ Used In File(s): \code\game\machinery\computer\aifixer.dm {{:helper.link('Disabled','close',{'radio' : 1},data.radio == 1 ? 'selected' : '')}}

Laws

- {{if data.zeroth}} - 0: {{:data.zeroth}}
- {{/if}} {{for data.laws}} {{:value.number}}: {{:value.law}}
{{empty}} - {{if !data.zeroth}} - No laws detected! - {{/if}} + No laws detected! {{/for}}

Actions

diff --git a/nano/templates/law_manager.tmpl b/nano/templates/law_manager.tmpl new file mode 100644 index 00000000000..eaa2bba4329 --- /dev/null +++ b/nano/templates/law_manager.tmpl @@ -0,0 +1,253 @@ + + +{{if data.isSlaved && data.isAdmin}} + This unit is law synced to {{:data.isSlaved}}. +{{/if}} + +{{if data.isMalf || data.isAIMalf}} +
+
+ {{:helper.link('Law Management', null, {'set_view' : 0}, data.view == 0 ? 'selected' : null)}} + {{:helper.link('Law Sets', null, {'set_view' : 1}, data.view == 1 ? 'selected' : null)}} +
+
+{{/if}} + +{{if data.view == 0}} + {{if data.has_ion_laws}} + + + {{if data.isMalf}} + + + {{/if}} + + +
+ {{:data.ion_law_nr}} Laws: +
+ {{for data.ion_laws}} + + + + + {{if data.isMalf}} + + + {{/if}} + + {{/for}} +
IndexLawStateEditDelete
{{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state == 0 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref})}}{{:helper.link('Delete', null, {'delete_law': value.ref}, null, 'redButton')}}
+ {{/if}} + + {{if data.has_inherent_laws || data.has_zeroth_laws}} + + + {{if data.isMalf}} + + + {{/if}} + + +
+ Inherent Laws: +
+ + {{for data.zeroth_laws}} + + + + + {{if data.isMalf}} + + + {{/if}} + + {{/for}} + + {{for data.inherent_laws}} + + + + + {{if data.isMalf}} + + + {{/if}} + + {{/for}} +
IndexLawStateEditDelete
{{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state != 1 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref}, data.isAdmin ? null : 'disabled')}}{{:helper.link('Delete', null, {'delete_law': value.ref}, data.isAdmin ? null : 'disabled', data.isAdmin ? 'redButton' : null)}}
{{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state == 0 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref})}}{{:helper.link('Delete', null, {'delete_law': value.ref}, null, 'redButton')}}
+ {{/if}} + + {{if data.has_supplied_laws}} + + + {{if data.isMalf}} + + + {{/if}} + + +
+ Supplied Laws: +
+ {{for data.supplied_laws}} + + + + + {{if data.isMalf}} + + + {{/if}} + + {{/for}} +
IndexLawStateEditDelete
{{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state == 0 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref})}}{{:helper.link('Delete', null, {'delete_law': value.ref}, null, 'redButton')}}
+ {{/if}} + +
+
+ Statement Channel: +
+
+ {{for data.channels}} + {{:helper.link(value.channel, null, {'law_channel' : value.channel}, value.channel == data.channel ? 'selected' : null)}} + {{/for}} +
+
+ +
+
+ State Laws: +
+
+ {{:helper.link('State Laws', null, {'state_laws' : 1})}} +
+
+ + {{if data.isMalf}} +
+
+ Add Laws: +
+
+ + + {{if data.isAdmin && !data.has_zeroth_laws}} + + {{/if}} + + + +
TypeLawIndexEditAdd
Zero{{:data.zeroth_law}}N/A{{:helper.link('Edit', null, {'change_zeroth_law' : 1})}}{{:helper.link('Add', null, {'add_zeroth_law' : 1})}}
Ion{{:data.ion_law}}N/A{{:helper.link('Edit', null, {'change_ion_law' : 1})}}{{:helper.link('Add', null, {'add_ion_law' : 1})}}
Inherent{{:data.inherent_law}}N/A{{:helper.link('Edit', null, {'change_inherent_law' : 1})}}{{:helper.link('Add', null, {'add_inherent_law' : 1})}}
Supplied{{:data.supplied_law}}{{:helper.link(data.supplied_law_position, null, {'change_supplied_law_position' : 1})}}{{:helper.link('Edit', null, {'change_supplied_law' : 1})}}{{:helper.link('Add', null, {'add_supplied_law' : 1})}}
+
+
+ {{/if}} + + {{if data.isAI}} +
+
+ Law Notification: +
+
+ {{:helper.link('Notify', null, {'notify_laws' : 1})}} +
+
+ {{/if}} +{{else data.view == 1}} + {{for data.law_sets}} +
+
+

{{:value.name}}

{{:value.header}} +
+ + {{if value.laws.has_ion_laws}} + + + {{for value.laws.ion_laws :lawValue:lawindex}} + + + + + {{/for}} +
IndexLaw
{{:lawValue.index}}.{{:lawValue.law}}
+ {{/if}} + + {{if value.laws.has_zeroth_laws || value.laws.has_inherent_laws}} + + + {{for value.laws.zeroth_laws :lawValue:lawindex}} + + + + + {{/for}} + {{for value.laws.inherent_laws :lawValue:lawindex}} + + + + + {{/for}} +
IndexLaw
{{:lawValue.index}}.{{:lawValue.law}}
{{:lawValue.index}}.{{:lawValue.law}}
+ {{/if}} + + {{if value.laws.has_supplied_laws}} + + + {{for value.laws.supplied_laws :lawValue:lawindex}} + + + + + {{/for}} +
IndexLaw
{{:lawValue.index}}.{{:lawValue.law}}
+ {{/if}} + +
+
+ {{:helper.link('Load Laws', null, {'transfer_laws' : value.ref}, data.isSlaved ? 'disabled' : null)}}{{:helper.link('State Laws', null, {'state_law_set' : value.ref})}} +
+
+ {{/for}} +{{/if}} \ No newline at end of file diff --git a/paradise.dme b/paradise.dme index ccbdd95af88..b7e3becd0f1 100644 --- a/paradise.dme +++ b/paradise.dme @@ -170,6 +170,7 @@ #include "code\controllers\ProcessScheduler\core\_stubs.dm" #include "code\controllers\ProcessScheduler\core\process.dm" #include "code\controllers\ProcessScheduler\core\processScheduler.dm" +#include "code\datums\ai_law_sets.dm" #include "code\datums\ai_laws.dm" #include "code\datums\browser.dm" #include "code\datums\cargoprofile.dm" @@ -1359,6 +1360,7 @@ #include "code\modules\mob\living\carbon\metroid\subtypes.dm" #include "code\modules\mob\living\carbon\metroid\update_icons.dm" #include "code\modules\mob\living\silicon\death.dm" +#include "code\modules\mob\living\silicon\laws.dm" #include "code\modules\mob\living\silicon\login.dm" #include "code\modules\mob\living\silicon\say.dm" #include "code\modules\mob\living\silicon\silicon.dm" @@ -1493,6 +1495,7 @@ #include "code\modules\nano\modules\atmos_control.dm" #include "code\modules\nano\modules\crew_monitor.dm" #include "code\modules\nano\modules\human_appearance.dm" +#include "code\modules\nano\modules\law_manager.dm" #include "code\modules\nano\modules\nano_module.dm" #include "code\modules\nano\modules\power_monitor.dm" #include "code\modules\ninja\energy_katana.dm"