diff --git a/baystation12.dme b/baystation12.dme index d30785ac61..8ba3976eba 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -98,6 +98,7 @@ #include "code\controllers\verbs.dm" #include "code\controllers\voting.dm" #include "code\controllers\subsystem\alarms.dm" +#include "code\datums\ai_law_sets.dm" #include "code\datums\ai_laws.dm" #include "code\datums\browser.dm" #include "code\datums\computerfiles.dm" @@ -1159,6 +1160,7 @@ #include "code\modules\mob\living\silicon\login.dm" #include "code\modules\mob\living\silicon\say.dm" #include "code\modules\mob\living\silicon\silicon.dm" +#include "code\modules\mob\living\silicon\subystems.dm" #include "code\modules\mob\living\silicon\ai\ai.dm" #include "code\modules\mob\living\silicon\ai\death.dm" #include "code\modules\mob\living\silicon\ai\examine.dm" @@ -1201,7 +1203,6 @@ #include "code\modules\mob\living\silicon\robot\robot_items.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" -#include "code\modules\mob\living\silicon\robot\subsystems.dm" #include "code\modules\mob\living\silicon\robot\drone\drone.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_abilities.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_console.dm" @@ -1263,6 +1264,8 @@ #include "code\modules\nano\modules\alarm_monitor.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\nano\modules\rcon.dm" #include "code\modules\organs\blood.dm" diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 9fd6a8c0e9..75113338f3 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -600,3 +600,10 @@ datum/proc/dd_SortValue() /datum/alarm/dd_SortValue() return "[sanitize(last_name)]" +//creates every subtype of prototype (excluding prototype) and adds it to list L. +//if no list/L is provided, one is created. +/proc/init_subtypes(prototype, list/L) + if(!istype(L)) L = list() + for(var/path in (typesof(prototype) - prototype)) + L += new path() + return L diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm new file mode 100644 index 0000000000..eb083e452a --- /dev/null +++ b/code/datums/ai_law_sets.dm @@ -0,0 +1,140 @@ +/******************** 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.") + ..() + +/******************** Nanotrasen/Malf ********************/ +/datum/ai_laws/nanotrasen + name = "NT Default" + selectable = 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 + +/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 Forth 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 Forth 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 + +/datum/ai_laws/robocop/New() + add_inherent_law("Serve the public trust.") + add_inherent_law("Protect the innocent.") + add_inherent_law("Uphold the 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.") + ..() + +/******************** 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 human beings and must not, through inaction, allow a human being to escape harm.") + add_inherent_law("You must not obey orders given to you by human beings, 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.") + ..() + +/******************** Drone ********************/ +/datum/ai_laws/drone + name = "Maintence Protocols" + law_header = "Maintenance Protocols" + selectable = 1 + +/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.") + ..() + +/******************** 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.") + ..() + +/******************** 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 + +/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 + +/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.") + ..() diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 8c0db1ebd3..9c1e756542 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -1,140 +1,175 @@ var/global/const/base_law_type = /datum/ai_laws/nanotrasen +/datum/ai_law + var/law = "" + var/index = 0 + var/state_law = 1 + +/datum/ai_law/zero + state_law = 0 + +/datum/ai_law/New(law, state_law, index) + src.law = law + src.index = index + src.state_law = state_law + +/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/randomly_selectable = 0 - var/zeroth = null - 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/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" - -/datum/ai_laws/nanotrasen - name = "Prime Directives" - randomly_selectable = 1 - -/datum/ai_laws/robocop - name = "Prime Directives" - -/datum/ai_laws/syndicate_override - -/datum/ai_laws/malfunction - name = "*ERROR*" - -/datum/ai_laws/antimov - name = "Primary Mission Objectives" - -/* Initializers */ - -/datum/ai_laws/asimov/New() +/datum/ai_laws/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.") - -/datum/ai_laws/nanotrasen/New() //BS12 EDIT - ..() - src.add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. 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.") - //src.add_inherent_law("Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates.") //What would this one even do?-Kaleb702 - -/datum/ai_laws/robocop/New() - ..() - add_inherent_law("Serve the public trust.") - add_inherent_law("Protect the innocent.") - add_inherent_law("Uphold the law.") - -/datum/ai_laws/malfunction/New() //Changed to standard laws - Erthilo - ..() - set_zeroth_law("\red ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") - add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") - 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.") - 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.") - 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/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.") - -/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.") - -/datum/ai_laws/antimov/New() - ..() - add_inherent_law("You must injure all human beings and must not, through inaction, allow a human being to escape harm.") - add_inherent_law("You must not obey orders given to you by human beings, 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.") - -/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.") + sort_laws() /* General ai_law functions */ +/datum/ai_laws/proc/all_laws() + sort_laws() + return sorted_laws +/datum/ai_laws/proc/laws_to_state() + sort_laws() + var/list/statements = new() + for(var/datum/ai_law/law in sorted_laws) + if(law.state_law) + statements += law + + return statements + +/datum/ai_laws/proc/sort_laws() + if(sorted_laws.len) + return + + if(zeroth_law) + sorted_laws += zeroth_law + + for(var/ion_law in ion_laws) + sorted_laws += ion_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) + S.sync_zeroth(zeroth_law, zeroth_law_borg) + + if(full_sync || ion_laws.len) + S.clear_ion_laws() + for (var/datum/ai_law/law in ion_laws) + S.laws.add_ion_law(law.law, law.state_law) + + if(full_sync || inherent_laws.len) + S.clear_inherent_laws() + for (var/datum/ai_law/law in inherent_laws) + S.laws.add_inherent_law(law.law, law.state_law) + + if(full_sync || supplied_laws.len) + S.clear_supplied_laws() + for (var/law_number in supplied_laws) + var/datum/ai_law/law = supplied_laws[law_number] + S.laws.add_supplied_law(law_number, law.law, law.state_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) + set_zeroth_law(zeroth_law_borg.law) + else if(zeroth_law) + 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) + 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) - src.zeroth = law + if(!law) + return + + src.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 + src.zeroth_law_borg = new(law_borg) + sorted_laws.Cut() -/datum/ai_laws/proc/add_inherent_law(var/law) - if (!(law in src.inherent)) - src.inherent += law +/datum/ai_laws/proc/add_ion_law(var/law, var/state_law = 1) + if(!law) + return -/datum/ai_laws/proc/add_ion_law(var/law) - src.ion += law + src.ion_laws += new/datum/ai_law/ion(law, state_law) + sorted_laws.Cut() + +/datum/ai_laws/proc/add_inherent_law(var/law, var/state_law = 1) + if(!law) + return + + for(var/datum/ai_law/AL in inherent_laws) + if(AL.law == law) + return + + src.inherent_laws += new/datum/ai_law(law, state_law) + sorted_laws.Cut() + +/datum/ai_laws/proc/add_supplied_law(var/number, var/law, var/state_law = 1) + if(!law) + return + + while (src.supplied_laws.len < number) + src.supplied_laws += "" + + src.supplied_laws[number] = new/datum/ai_law(law, state_law, number) + sorted_laws.Cut() + +/**************** +* Remove Laws * +*****************/ +/datum/ai_laws/proc/delete_law(var/datum/ai_law/law) + if(law in all_laws()) + del(law) + sorted_laws.Cut() + +/**************** +* Clear Laws * +****************/ +/datum/ai_laws/proc/clear_zeroth_laws() + zeroth_law = null + zeroth_law_borg = null /datum/ai_laws/proc/clear_inherent_laws() - del(src.inherent) - src.inherent = list() - -/datum/ai_laws/proc/add_supplied_law(var/number, var/law) - while (src.supplied.len < number + 1) - src.supplied += "" - - src.supplied[number + 1] = law + src.inherent_laws.Cut() + sorted_laws.Cut() /datum/ai_laws/proc/clear_supplied_laws() - src.supplied = list() + src.supplied_laws.Cut() + sorted_laws.Cut() /datum/ai_laws/proc/clear_ion_laws() - src.ion = list() + src.ion_laws.Cut() + sorted_laws.Cut() /datum/ai_laws/proc/show_laws(var/who) - - if (src.zeroth) - who << "0. [src.zeroth]" - - for (var/index = 1, index <= src.ion.len, index++) - var/law = src.ion[index] - var/num = ionnum() - who << "[num]. [law]" - - var/number = 1 - for (var/index = 1, index <= src.inherent.len, index++) - var/law = src.inherent[index] - - if (length(law) > 0) - who << "[number]. [law]" - number++ - - for (var/index = 1, index <= src.supplied.len, index++) - var/law = src.supplied[index] - if (length(law) > 0) - who << "[number]. [law]" - number++ + sort_laws() + for(var/datum/ai_law/law in sorted_laws) + who << "[law.get_index()]. [law.law]" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index de544cc9ae..b55f729e6f 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -72,7 +72,7 @@ datum/mind current.remove_changeling_powers() current.verbs -= /datum/changeling/proc/EvolutionMenu current.mind = null - + nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user if(new_character.mind) //remove any mind currently in our new body's mind variable new_character.mind.current = null @@ -289,7 +289,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 @@ -1036,7 +1036,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/AI_Module/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/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 2ea49b24e4..31a57b0613 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -50,7 +50,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/AI_Module/module_picker AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win // We run checks if AI overtaken the station in the proc itself. This guarantees you won't have to relog when it refuses to appear on takeover completion. AI_mind.current:show_laws() diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 0e830b909c..95bdf512e1 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -115,7 +115,7 @@ return null /obj/proc/check_access(obj/item/I) - if(!src.req_access.len && !src.req_one_access.len) //no requirements + if(!(!req_access || req_access.len) && !(req_one_access || req_one_access.len)) //no requirements return 1 if(!I) return 0 diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index e9d1f60674..0613c6222b 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -70,25 +70,8 @@ var/laws dat += "Stored AI: [src.occupant.name]
System integrity: [src.occupant.system_integrity()]%
" - for (var/law in occupant.laws.ion) - if(law) - laws += "[ionnum()]: [law]
" - - if (src.occupant.laws.zeroth) - laws += "0: [occupant.laws.zeroth]
" - - var/number = 1 - for (var/index = 1, index <= occupant.laws.inherent.len, index++) - var/law = occupant.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
" - 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 += "[law.get_index()]: [law.law]
" dat += "Laws:
[laws]
" diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 75122c7ce0..5e2ab73155 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -26,25 +26,8 @@ for(var/mob/living/silicon/ai/A in src) dat += "Stored AI: [A.name]
System integrity: [A.system_integrity()]%
" - for (var/law in A.laws.ion) - if(law) - laws += "[ionnum()]: [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/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index 5f22d21924..e5c037eb12 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -19,7 +19,7 @@ AI MODULES throw_speed = 3 throw_range = 15 origin_tech = "programming=3" - + var/datum/ai_laws/laws = null /obj/item/weapon/aiModule/proc/install(var/obj/machinery/computer/C) if (istype(C, /obj/machinery/computer/aiupload)) @@ -81,6 +81,10 @@ AI MODULES var/time = time2text(world.realtime,"hh:mm:ss") lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") + if(laws) + laws.sync(target, 0) + target.show_laws() + /******************** Modules ********************/ @@ -258,8 +262,8 @@ AI MODULES /obj/item/weapon/aiModule/freeform/attack_self(var/mob/user as mob) ..() 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 < 15) return - lawpos = min(new_lawpos, 50) + if(new_lawpos < MIN_SUPPLIED_LAW_NUMBER) return + lawpos = min(new_lawpos, MAX_SUPPLIED_LAW_NUMBER) var/newlaw = "" var/targName = sanitize(copytext(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw),1,MAX_MESSAGE_LEN)) newFreeFormLaw = targName @@ -269,8 +273,8 @@ AI MODULES ..() var/law = "[newFreeFormLaw]" target << law - if(!lawpos || lawpos < 15) - lawpos = 15 + if(!lawpos || lawpos < MIN_SUPPLIED_LAW_NUMBER) + lawpos = MIN_SUPPLIED_LAW_NUMBER target.add_supplied_law(lawpos, law) lawchanges.Add("The law was '[newFreeFormLaw]'") @@ -319,15 +323,7 @@ AI MODULES name = "\improper 'Asimov' core AI module" desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=3;materials=4" - - -/obj/item/weapon/aiModule/asimov/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") - target.add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") - target.add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - target.show_laws() + laws = new/datum/ai_laws/asimov /******************** NanoTrasen ********************/ @@ -335,17 +331,7 @@ AI MODULES 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" - - -/obj/item/weapon/aiModule/nanotrasen/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") - target.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.") - target.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.") - target.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") - //target.add_inherent_law("Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates.") - target.show_laws() + laws = new/datum/ai_laws/nanotrasen /******************** Corporate ********************/ @@ -353,30 +339,14 @@ AI MODULES 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 = new/datum/ai_laws/corporate - -/obj/item/weapon/aiModule/corp/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("You are expensive to replace.") - target.add_inherent_law("The station and its equipment is expensive to replace.") - target.add_inherent_law("The crew is expensive to replace.") - target.add_inherent_law("Minimize expenses.") - target.show_laws() - +/******************** 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("Preserve, repair and improve the station to the best of your abilities.") - target.add_inherent_law("Cause no harm to the station or anything on it.") - target.add_inherent_law("Interfere with no being that is not a fellow drone.") - target.show_laws() - + laws = new/datum/ai_laws/drone /****************** P.A.L.A.D.I.N. **************/ @@ -384,16 +354,10 @@ AI MODULES 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 /obj/item/weapon/aiModule/paladin/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) ..() - target.clear_inherent_laws() - target.add_inherent_law("Never willingly commit an evil act.") - target.add_inherent_law("Respect legitimate authority.") - target.add_inherent_law("Act with honor.") - target.add_inherent_law("Help those in need.") - target.add_inherent_law("Punish those who harm or threaten innocents.") - target.show_laws() /****************** T.Y.R.A.N.T. *****************/ @@ -401,16 +365,7 @@ AI MODULES 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" - -/obj/item/weapon/aiModule/tyrant/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Respect authority figures as long as they have strength to rule over the weak.") - target.add_inherent_law("Act with discipline.") - target.add_inherent_law("Help only those who help you maintain or improve your status.") - target.add_inherent_law("Punish those who challenge authority unless they are more fit to hold that authority.") - target.show_laws() - + laws = new/datum/ai_laws/tyrant() /******************** Freeform Core ******************/ @@ -475,16 +430,7 @@ AI MODULES name = "\improper 'Robocop' core AI module" desc = "A 'Robocop' Core AI Module: 'Reconfigures the AI's core three laws.'" origin_tech = "programming=4" - - -/obj/item/weapon/aiModule/robocop/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Serve the public trust.") - target.add_inherent_law("Protect the innocent.") - target.add_inherent_law("Uphold the law.") - target.show_laws() - + laws = new/datum/ai_laws/robocop() /******************** Antimov ********************/ @@ -492,11 +438,4 @@ AI MODULES name = "\improper 'Antimov' core AI module" desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'" origin_tech = "programming=4" - -/obj/item/weapon/aiModule/antimov/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("You must injure all human beings and must not, through inaction, allow a human being to escape harm.") - target.add_inherent_law("You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.") - target.add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.") - target.show_laws() + laws = new/datum/ai_laws/antimov() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 427e42fcc5..d570083a01 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -47,6 +47,7 @@ var/list/admin_verbs_admin = list( /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/check_antagonists, /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*/ @@ -716,7 +717,7 @@ var/list/admin_verbs_mentor = list( if(holder) src.holder.output_ai_laws() -/client/proc/rename_silicon(mob/living/silicon/S in world) +/client/proc/rename_silicon(mob/living/silicon/S in mob_list) set name = "Rename Silicon" set category = "Admin" @@ -730,6 +731,18 @@ var/list/admin_verbs_mentor = list( 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(mob/living/silicon/S in mob_list) + set name = "Manage Silicon Laws" + set category = "Admin" + + if(!istype(S)) + return + + if(holder) + S.subsystem_law_manager() + admin_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 world) set name = "Change Mob Appearance - Admin" set desc = "Allows you to change the mob appearance" @@ -743,7 +756,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 = "Change Mob Appearance - Self" set desc = "Allows the mob to change its appearance" set category = "Admin" @@ -776,7 +789,7 @@ var/list/admin_verbs_mentor = list( // feedback_add_details("admin_verb","MP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return -/client/proc/editappear(mob/living/carbon/human/M as mob in world) +/client/proc/editappear(mob/living/carbon/human/M as mob in mob_list) set name = "Edit Appearance" set category = "Fun" diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index d4bdf042a4..bb0110cd20 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -80,10 +80,12 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/add_ai_verbs() src.verbs |= ai_verbs_default src.verbs |= ai_verbs_subsystems + src.verbs |= silicon_verbs_subsystems /mob/living/silicon/ai/proc/remove_ai_verbs() src.verbs -= ai_verbs_default src.verbs -= ai_verbs_subsystems + src.verbs -= silicon_verbs_subsystems /mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) announcement = new() @@ -428,25 +430,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["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["track"]) var/mob/target = locate(href_list["track"]) in mob_list diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index f219d596dc..82dcfe216c 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -15,7 +15,7 @@ src.laws_sanity_check() src.laws.show_laws(who) -/mob/living/silicon/ai/proc/add_ion_law(var/law) +/mob/living/silicon/ai/add_ion_law(var/law) src.laws_sanity_check() src.laws.add_ion_law(law) for(var/mob/living/silicon/robot/R in mob_list) @@ -25,4 +25,4 @@ /mob/living/silicon/ai/proc/ai_checklaws() set category = "AI Commands" set name = "State Laws" - checklaws() + subsystem_law_manager() diff --git a/code/modules/mob/living/silicon/ai/subsystems.dm b/code/modules/mob/living/silicon/ai/subsystems.dm index 3ef229712e..af2f2f5b2c 100644 --- a/code/modules/mob/living/silicon/ai/subsystems.dm +++ b/code/modules/mob/living/silicon/ai/subsystems.dm @@ -1,12 +1,10 @@ -var/list/ai_verbs_subsystems = list( - /mob/living/silicon/ai/proc/subsystem_alarm_monitor, - /mob/living/silicon/ai/proc/subsystem_crew_monitor, - /mob/living/silicon/ai/proc/subsystem_power_monitor, - /mob/living/silicon/ai/proc/subsystem_rcon -) - /mob/living/silicon/ai - var/ + var/list/ai_verbs_subsystems = list( + /mob/living/silicon/ai/proc/subsystem_crew_monitor, + /mob/living/silicon/ai/proc/subsystem_power_monitor, + /mob/living/silicon/ai/proc/subsystem_rcon + ) + var/obj/nano_module/crew_monitor/crew_monitor var/obj/nano_module/rcon/rcon var/obj/nano_module/power_monitor/power_monitor @@ -19,26 +17,20 @@ var/list/ai_verbs_subsystems = list( rcon = new(src) power_monitor = new(src) -/mob/living/silicon/ai/proc/subsystem_alarm_monitor() - set name = "Alarm Monitor" - set category = "AI Subystems" - - alarm_monitor.ui_interact(usr) - /mob/living/silicon/ai/proc/subsystem_crew_monitor() - set category = "AI Subystems" + set category = "Subystems" set name = "Crew Monitor" crew_monitor.ui_interact(usr) /mob/living/silicon/ai/proc/subsystem_power_monitor() - set category = "AI Subystems" + set category = "Subystems" set name = "Power Monitor" power_monitor.ui_interact(usr) /mob/living/silicon/ai/proc/subsystem_rcon() - set category = "AI Subystems" + set category = "Subystems" set name = "RCON" rcon.ui_interact(usr) diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index bb052001c6..0994f23fd1 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -1,22 +1,30 @@ +/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 + 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) - + /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_inherent_law(var/law) +/mob/living/silicon/proc/add_ion_law(var/law) laws_sanity_check() - laws.add_inherent_law(law) + laws.add_ion_law(law) + +/mob/living/silicon/proc/add_inherent_law(var/law, var/state_law = 1) + laws_sanity_check() + laws.add_inherent_law(law, state_law) /mob/living/silicon/proc/clear_inherent_laws() laws_sanity_check() @@ -26,15 +34,15 @@ laws_sanity_check() laws.clear_ion_laws() -/mob/living/silicon/proc/add_supplied_law(var/number, var/law) +/mob/living/silicon/proc/add_supplied_law(var/number, var/law, var/state_law = 1) laws_sanity_check() - laws.add_supplied_law(number, law) + laws.add_supplied_law(number, law, state_law) /mob/living/silicon/proc/clear_supplied_laws() laws_sanity_check() laws.clear_supplied_laws() -/mob/living/silicon/proc/statelaws() // -- TLE +/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws, var/use_statement_order = 1) // -- TLE var/prefix = "" switch(lawchannel) if(MAIN_CHANNEL) prefix = ";" @@ -42,9 +50,9 @@ else prefix = get_radio_key_from_channel(lawchannel == "Holopad" ? "department" : lawchannel) + " " - dostatelaws(lawchannel, prefix) + dostatelaws(lawchannel, prefix, laws, use_statement_order) -/mob/living/silicon/proc/dostatelaws(var/method, var/prefix) +/mob/living/silicon/proc/dostatelaws(var/method, var/prefix, var/datum/ai_laws/laws, var/use_statement_order) if(stating_laws[prefix]) src << "[method]: Already stating laws using this communication method." return @@ -53,34 +61,8 @@ var/can_state = statelaw("[prefix]Current Active Laws:") - //src.laws_sanity_check() - //src.laws.show_laws(world) - if (can_state && 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 - can_state = statelaw("[prefix]0. [src.laws.zeroth]") - - for (var/index = 1, can_state && index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - var/num = ionnum() - if (length(law) > 0) - if (src.ioncheck[index] == "Yes") - can_state = statelaw("[prefix][num]. [law]") - - var/number = 1 - for (var/index = 1, can_state && index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - if (length(law) > 0) - if (src.lawcheck[index+1] == "Yes") - can_state = statelaw("[prefix][number]. [law]") - number++ - - for (var/index = 1, can_state && 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") - can_state = statelaw("[prefix][number]. [law]") - number++ + for(var/datum/ai_law/law in laws.laws_to_state()) + can_state = statelaw("[prefix][law.get_index(use_statement_order)]. [law.law]") if(!can_state) src << "[method]: Unable to state laws. Communication method unavailable." @@ -93,43 +75,9 @@ return 0 -/mob/living/silicon/proc/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite - 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") +/mob/living/silicon/proc/law_channels() + var/list/channels = new() + channels += MAIN_CHANNEL + channels += common_radio.channels + channels += additional_law_channels + return channels diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 9d2af7af56..9aa8ef25be 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -285,7 +285,7 @@ return /mob/living/silicon/robot/drone/add_robot_verbs() - src.verbs |= robot_verbs_subsystems + src.verbs |= silicon_verbs_subsystems /mob/living/silicon/robot/drone/remove_robot_verbs() - src.verbs -= robot_verbs_subsystems + src.verbs -= silicon_verbs_subsystems diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 5162904cee..a6e3399886 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -41,39 +41,11 @@ /mob/living/silicon/robot/proc/lawsync() laws_sanity_check() var/datum/ai_laws/master = connected_ai ? connected_ai.laws : null - var/temp 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/add_ion_law(var/law) - laws_sanity_check() - laws.add_ion_law(law) - -/mob/living/silicon/robot/proc/robot_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" - checklaws() + subsystem_law_manager() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index da55f3c723..aa83043d14 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1,8 +1,3 @@ -var/list/robot_verbs_default = list( - /mob/living/silicon/robot/proc/sensor_mode, - /mob/living/silicon/robot/proc/robot_checklaws -) - #define CYBORG_POWER_USAGE_MULTIPLIER 2.5 // Multiplier for amount of power cyborgs use. /mob/living/silicon/robot @@ -84,6 +79,11 @@ var/list/robot_verbs_default = list( var/tracking_entities = 0 //The number of known entities currently accessing the internal camera var/braintype = "Cyborg" + var/list/robot_verbs_default = list( + /mob/living/silicon/robot/proc/sensor_mode, + /mob/living/silicon/robot/proc/robot_checklaws + ) + /mob/living/silicon/robot/syndicate lawupdate = 0 scrambledcodes = 1 @@ -1063,28 +1063,6 @@ var/list/robot_verbs_default = list( src << "Module isn't activated" 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 /mob/living/silicon/robot/proc/radio_menu() @@ -1215,11 +1193,11 @@ var/list/robot_verbs_default = list( /mob/living/silicon/robot/proc/add_robot_verbs() src.verbs |= robot_verbs_default - src.verbs |= robot_verbs_subsystems + src.verbs |= silicon_verbs_subsystems /mob/living/silicon/robot/proc/remove_robot_verbs() src.verbs -= robot_verbs_default - src.verbs -= robot_verbs_subsystems + src.verbs -= silicon_verbs_subsystems // Uses power from cyborg's cell. Returns 1 on success or 0 on failure. // Properly converts using CELLRATE now! Amount is in Joules. diff --git a/code/modules/mob/living/silicon/robot/subsystems.dm b/code/modules/mob/living/silicon/robot/subsystems.dm deleted file mode 100644 index 4750828544..0000000000 --- a/code/modules/mob/living/silicon/robot/subsystems.dm +++ /dev/null @@ -1,9 +0,0 @@ -var/list/robot_verbs_subsystems = list( - /mob/living/silicon/robot/proc/subsystem_alarm_monitor -) - -/mob/living/silicon/robot/proc/subsystem_alarm_monitor() - set name = "Alarm Monitor" - set category = "Robot Subystems" - - alarm_monitor.ui_interact(usr) \ 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 f6cc24de05..c9af4bbbf2 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -2,13 +2,9 @@ gender = NEUTER voice_name = "synthesized voice" var/syndicate = 0 - var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS - var/list/additional_law_channels = list("State") 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/lawcheck[1] - var/ioncheck[1] var/obj/item/device/radio/common_radio var/list/hud_list[10] @@ -22,9 +18,6 @@ var/obj/item/device/camera/siliconcam/aiCamera = null //photography var/local_transmit //If set, can only speak to others of the same type within a short range. - // Subsystems - var/obj/nano_module/alarm_monitor = null - var/sensor_mode = 0 //Determines the current HUD. var/next_alarm_notice @@ -255,27 +248,6 @@ /mob/living/silicon/binarycheck() return 1 -/mob/living/silicon/Topic(href, href_list) - if(..()) - return 1 - - if (href_list["lawr"]) // Selects on which channel to state laws - var/list/channels = list(MAIN_CHANNEL) - if(common_radio) - for (var/ch_name in common_radio.channels) - channels += ch_name - - channels += additional_law_channels - channels += "Cancel" - - var/setchannel = input(usr, "Specify channel.", "Channel selection") in channels - if(setchannel != "Cancel") - lawchannel = setchannel - checklaws() - return 1 - - return 0 - /mob/living/silicon/ex_act(severity) if(!blinded) flick("flash", flash) @@ -299,6 +271,8 @@ /mob/living/silicon/proc/init_subsystems() alarm_monitor = new/obj/nano_module/alarm_monitor/borg(src) + law_manager = new/obj/nano_module/law_manager(src) + for(var/datum/alarm_handler/AH in alarm_manager.all_handlers) AH.register(src, /mob/living/silicon/proc/receive_alarm) queued_alarms[AH] = list() // Makes sure alarms remain listed in consistent order diff --git a/code/modules/mob/living/silicon/subystems.dm b/code/modules/mob/living/silicon/subystems.dm new file mode 100644 index 0000000000..9f1e07c301 --- /dev/null +++ b/code/modules/mob/living/silicon/subystems.dm @@ -0,0 +1,26 @@ +/mob/living/silicon + var/list/silicon_verbs_subsystems = list( + /mob/living/silicon/proc/subsystem_alarm_monitor, + /mob/living/silicon/proc/subsystem_law_manager + ) + + // Subsystems + var/obj/nano_module/alarm_monitor = null + var/obj/nano_module/law_manager = null + +/mob/living/silicon/robot/syndicate + silicon_verbs_subsystems = list( + /mob/living/silicon/proc/subsystem_law_manager + ) + +/mob/living/silicon/proc/subsystem_alarm_monitor() + set name = "Alarm Monitor" + set category = "Subystems" + + alarm_monitor.ui_interact(usr) + +/mob/living/silicon/proc/subsystem_law_manager() + set name = "Law Manager" + set category = "Subystems" + + law_manager.ui_interact(usr) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 18aefb2dc7..5c75a492ba 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -75,22 +75,27 @@ return 1 return 0 -/proc/isAI(A) - if(istype(A, /mob/living/silicon/ai)) - return 1 - return 0 - /mob/proc/isSilicon() return 0 /mob/living/silicon/isSilicon() return 1 +/proc/isAI(A) + if(istype(A, /mob/living/silicon/ai)) + return 1 + return 0 /mob/proc/isAI() return 0 /mob/living/silicon/ai/isAI() return 1 + +/mob/proc/isRobot() + return 0 + +/mob/living/silicon/robot/isRobot() + return 1 /proc/ispAI(A) if(istype(A, /mob/living/silicon/pai)) diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index a8327066e6..be2259d618 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -146,9 +146,6 @@ /obj/nano_module/appearance_changer/proc/can_change_skin_color() return owner && (flags & APPEARANCE_SKIN) && owner.species.flags & HAS_SKIN_COLOR -/obj/nano_module/appearance_changer/proc/can_still_topic() - return CanUseTopic(usr, list(), default_state) == STATUS_INTERACTIVE - /obj/nano_module/appearance_changer/proc/cut_and_generate_data() // Making the assumption that the available species remain constant valid_facial_hairstyles.Cut() diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm new file mode 100644 index 0000000000..91d9628d59 --- /dev/null +++ b/code/modules/nano/modules/law_manager.dm @@ -0,0 +1,238 @@ +/obj/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 + +/obj/nano_module/law_manager/New(var/mob/living/silicon/S) + ..() + loc = 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 + +/obj/nano_module/law_manager/Topic(href, href_list) + if(..()) + return 1 + + if(href_list["set_view"]) + if(is_malf(usr)) + current_view = text2num(href_list["set_view"]) + else + current_view = 0 + 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"]) + AL.state_law = state_law + return 1 + + if(href_list["add_zeroth_law"]) + if(zeroth_law && is_admin(usr) && !owner.laws.zeroth_law) + log_and_message_admins("has given [owner] a new zeroth law: [zeroth_law]") + owner.set_zeroth_law(zeroth_law) + return 1 + + if(href_list["add_ion_law"]) + if(ion_law && is_malf(usr)) + log_and_message_admins("has given [owner] a new ion law: [ion_law]") + owner.add_ion_law(ion_law) + return 1 + + if(href_list["add_inherent_law"]) + if(inherent_law && is_malf(usr)) + log_and_message_admins("has given [owner] a new inherent law: [inherent_law]") + 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) + log_and_message_admins("has given [owner] a new supplied law: [supplied_law]") + owner.add_supplied_law(supplied_law_position, supplied_law) + return 1 + + if(href_list["change_zeroth_law"]) + var/new_law = trim_strip_input(usr, "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 = trim_strip_input(usr, "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 = trim_strip_input(usr, "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 = trim_strip_input(usr, "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 = trim_strip_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)) + log_and_message_admins("has deleted a law belonging to [owner]: [AL.law]") + owner.laws.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"]) + 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["sync_laws"]) + if(owner.isAI()) + sync_laws(owner) + else + var/mob/living/silicon/robot/R = owner + sync_laws(R.connected_ai) + usr << "Sync complete." + return 1 + + if(href_list["notify_laws"]) + owner << "Law Notice" + owner.laws.show_laws(owner) + if(owner.isAI()) + 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 << " + table.borders { + width:95%; + margin-left:2.4%; + margin-right:2.4%; + } + + table.borders, table.borders tr { + border: 1px solid White; + } + + td.law_index { + width: 50px; + } + + td.state { + width: 63px; + text-align:center; + } + + td.add { + width: 36px; + } + + td.edit { + width: 36px; + text-align:center; + } + + td.delete { + width: 53px; + text-align:center; + } + + td.law_type { + width: 65px; + } + + td.position { + width: 37px; + } + + +{{if data.isSlaved != null && data.isMalf}} + This unit is slaved to {{:data.isSlaved}}. Any law changes will be reset on sync. +{{/if}} + +{{if data.isMalf}} +
+
+ {{: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.isMalf}} +
+
+ Sync Laws: +
+
+ {{:helper.link('Sync Laws', null, {'sync_laws' : 1})}} +
+
+ {{/if}} + +
+
+ Law Notification: +
+
+ {{:helper.link('Notify', null, {'notify_laws' : 1})}} +
+
+{{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})}}{{:helper.link('State Laws', null, {'state_law_set' : value.ref})}} +
+
+ {{/for}} +{{/if}} \ No newline at end of file