integrate law manager

This commit is contained in:
Kashargul
2024-09-21 03:46:20 +02:00
parent e76f8a2fa2
commit 4178550198
4 changed files with 422 additions and 37 deletions
+139
View File
@@ -12,9 +12,18 @@
/datum/eventkit/modify_robot
var/mob/living/silicon/robot/target
var/mob/living/silicon/robot/source
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/list/datum/ai_laws/law_list
/datum/eventkit/modify_robot/New()
. = ..()
law_list = new()
init_subtypes(/datum/ai_laws, law_list)
law_list = dd_sortedObjectList(law_list)
/datum/eventkit/modify_robot/tgui_close()
if(source)
@@ -97,6 +106,27 @@
continue
all_robots += list(list("displayText" = "[R]", "value" = "\ref[R]"))
.["all_robots"] = all_robots
// Law data
.["ion_law_nr"] = ionnum()
.["ion_law"] = ion_law
.["zeroth_law"] = zeroth_law
.["inherent_law"] = inherent_law
.["supplied_law"] = supplied_law
.["supplied_law_position"] = supplied_law_position
package_laws(., "zeroth_laws", list(target.laws.zeroth_law))
package_laws(., "ion_laws", target.laws.ion_laws)
package_laws(., "inherent_laws", target.laws.inherent_laws)
package_laws(., "supplied_laws", target.laws.supplied_laws)
.["isAI"] = isAI(target)
var/list/channels = list()
for(var/ch_name in target.law_channels())
channels[++channels.len] = list("channel" = ch_name)
.["channel"] = target.lawchannel
.["channels"] = channels
.["law_sets"] = package_multiple_laws(law_list)
/datum/eventkit/modify_robot/tgui_state(mob/user)
@@ -356,6 +386,96 @@
target.idcard.access -= get_all_station_access()
target.idcard.access -= access_synth
return TRUE
if("law_channel")
if(params["law_channel"] in target.law_channels())
target.lawchannel = params["law_channel"]
return TRUE
if("state_law")
var/datum/ai_law/AL = locate(params["ref"]) in target.laws.all_laws()
if(AL)
var/state_law = text2num(params["state_law"])
target.laws.set_state_law(AL, state_law)
return TRUE
if("add_zeroth_law")
if(zeroth_law && !target.laws.zeroth_law)
target.set_zeroth_law(zeroth_law)
return TRUE
if("add_ion_law")
if(ion_law)
target.add_ion_law(ion_law)
return TRUE
if("add_inherent_law")
if(inherent_law)
target.add_inherent_law(inherent_law)
return TRUE
if("add_supplied_law")
if(supplied_law && supplied_law_position >= 1 && MIN_SUPPLIED_LAW_NUMBER <= MAX_SUPPLIED_LAW_NUMBER)
target.add_supplied_law(supplied_law_position, supplied_law)
return TRUE
if("change_zeroth_law")
var/new_law = sanitize(params["val"])
if(new_law && new_law != zeroth_law)
zeroth_law = new_law
return TRUE
if("change_ion_law")
var/new_law = sanitize(params["val"])
if(new_law && new_law != ion_law)
ion_law = new_law
return TRUE
if("change_inherent_law")
var/new_law = sanitize(params["val"])
if(new_law && new_law != inherent_law)
inherent_law = new_law
return TRUE
if("change_supplied_law")
var/new_law = sanitize(params["val"])
if(new_law && new_law != supplied_law)
supplied_law = new_law
return TRUE
if("change_supplied_law_position")
var/new_position = tgui_input_number(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, MAX_SUPPLIED_LAW_NUMBER, 1)
if(isnum(new_position))
supplied_law_position = CLAMP(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
return TRUE
if("edit_law")
var/datum/ai_law/AL = locate(params["edit_law"]) in target.laws.all_laws()
if(AL)
var/new_law = sanitize(tgui_input_text(usr, "Enter new law. Leaving the field blank will cancel the edit.", "Edit Law", AL.law))
if(new_law && new_law != AL.law)
log_and_message_admins("has changed a law of [target] from '[AL.law]' to '[new_law]'")
AL.law = new_law
return TRUE
if("delete_law")
var/datum/ai_law/AL = locate(params["delete_law"]) in target.laws.all_laws()
if(AL)
target.delete_law(AL)
return TRUE
if("state_laws")
target.statelaws(target.laws)
return TRUE
if("state_law_set")
var/datum/ai_laws/ALs = locate(params["state_law_set"]) in law_list
if(ALs)
target.statelaws(ALs)
return TRUE
if("transfer_laws")
var/datum/ai_laws/ALs = locate(params["transfer_laws"]) in law_list
if(ALs)
log_and_message_admins("has transfered the [ALs.name] laws to [target].")
ALs.sync(target, 0)
return TRUE
if("notify_laws")
to_chat(target, "<span class='danger'>Law Notice</span>")
target.laws.show_laws(target)
if(isAI(target))
var/mob/living/silicon/ai/AI = target
for(var/mob/living/silicon/robot/R in AI.connected_robots)
to_chat(R, "<span class='danger'>Law Notice</span>")
R.laws.show_laws(R)
if(usr != target)
to_chat(usr, "<span class='notice'>Laws displayed.</span>")
return TRUE
/datum/eventkit/modify_robot/proc/get_target_items(var/mob/user)
var/list/target_items = list()
@@ -490,3 +610,22 @@
var/datum/robot_component/C = target.components[entry]
components += list(list("name" = C.name, "ref" = "\ref[C]", "brute_damage" = C.brute_damage, "electronics_damage" = C.electronics_damage, "max_damage" = C.max_damage, "installed" = C.installed, "exists" = (C.wrapped ? TRUE : FALSE)))
return components
/datum/eventkit/modify_robot/proc/package_laws(var/list/data, var/field, var/list/datum/ai_law/laws)
var/list/packaged_laws = list()
for(var/datum/ai_law/AL in laws)
packaged_laws[++packaged_laws.len] = list("law" = AL.law, "index" = AL.get_index(), "state" = target.laws.get_state_law(AL), "ref" = "\ref[AL]")
data[field] = packaged_laws
data["has_[field]"] = packaged_laws.len
/datum/eventkit/modify_robot/proc/package_multiple_laws(var/list/datum/ai_laws/laws)
var/list/law_sets = list()
for(var/datum/ai_laws/ALs in laws)
var/list/packaged_laws = list()
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
+183 -34
View File
@@ -1,4 +1,7 @@
import { filter } from 'common/collections';
import { flow } from 'common/fp';
import { BooleanLike } from 'common/react';
import { createSearch } from 'common/string';
import { useBackend, useSharedState } from '../backend';
import {
@@ -76,30 +79,12 @@ export const LawManager = (props) => {
};
const LawManagerContent = (props) => {
const { data } = useBackend<Data>();
const [tabIndex, setTabIndex] = useSharedState<number>('lawsTabIndex', 0);
const tab: React.JSX.Element[] = [];
tab[0] = <LawManagerLaws />;
tab[1] = <LawManagerLawSets />;
return (
<>
<Tabs>
<Tabs.Tab selected={tabIndex === 0} onClick={() => setTabIndex(0)}>
Law Management
</Tabs.Tab>
<Tabs.Tab selected={tabIndex === 1} onClick={() => setTabIndex(1)}>
Law Sets
</Tabs.Tab>
</Tabs>
{tab[tabIndex]}
</>
const [searchLawName, setSearchLawName] = useSharedState<string>(
'searchLawName',
'',
);
};
const LawManagerLaws = (props) => {
const { act, data } = useBackend<Data>();
const {
ion_law_nr,
@@ -121,8 +106,108 @@ const LawManagerLaws = (props) => {
isAdmin,
channel,
channels,
law_sets,
} = data;
const tab: React.JSX.Element[] = [];
tab[0] = (
<LawManagerLaws
ion_law_nr={ion_law_nr}
ion_law={ion_law}
zeroth_law={zeroth_law}
inherent_law={inherent_law}
supplied_law={supplied_law}
supplied_law_position={supplied_law_position}
zeroth_laws={zeroth_laws}
has_zeroth_laws={has_zeroth_laws}
ion_laws={ion_laws}
has_ion_laws={has_ion_laws}
inherent_laws={inherent_laws}
has_inherent_laws={has_inherent_laws}
supplied_laws={supplied_laws}
has_supplied_laws={has_supplied_laws}
isAI={isAI}
isMalf={isMalf}
isAdmin={isAdmin}
channel={channel}
channels={channels}
/>
);
tab[1] = (
<LawManagerLawSets
isMalf={isMalf}
isAdmin={isAdmin}
law_sets={law_sets}
ion_law_nr={ion_law_nr}
searchLawName={searchLawName}
onSearchLawName={setSearchLawName}
/>
);
return (
<>
<Tabs>
<Tabs.Tab selected={tabIndex === 0} onClick={() => setTabIndex(0)}>
Law Management
</Tabs.Tab>
<Tabs.Tab selected={tabIndex === 1} onClick={() => setTabIndex(1)}>
Law Sets
</Tabs.Tab>
</Tabs>
{tab[tabIndex]}
</>
);
};
export const LawManagerLaws = (props: {
ion_law_nr: string;
ion_law: string;
zeroth_law: string;
inherent_law: string;
supplied_law: string;
supplied_law_position: number;
zeroth_laws: law[];
ion_laws: law[];
inherent_laws: law[];
supplied_laws: law[];
has_zeroth_laws: number;
has_ion_laws: number;
has_inherent_laws: number;
has_supplied_laws: number;
isAI: BooleanLike;
isMalf: BooleanLike;
isAdmin: BooleanLike;
channel: string;
channels: { channel: string }[];
hasScroll?: boolean;
sectionHeight?: string;
}) => {
const { act } = useBackend();
const {
ion_law_nr,
ion_law,
zeroth_law,
inherent_law,
supplied_law,
supplied_law_position,
zeroth_laws,
has_zeroth_laws,
ion_laws,
has_ion_laws,
inherent_laws,
has_inherent_laws,
supplied_laws,
has_supplied_laws,
isAI,
isMalf,
isAdmin,
channel,
channels,
hasScroll,
sectionHeight,
} = props;
let allLaws = zeroth_laws
.map((law) => {
law.zero = true;
@@ -131,19 +216,37 @@ const LawManagerLaws = (props) => {
.concat(inherent_laws);
return (
<Section>
<Section scrollable={hasScroll} fill={hasScroll} height={sectionHeight}>
{has_ion_laws ? (
<LawsTable laws={ion_laws} title={ion_law_nr + ' Laws:'} mt={-2} />
<LawsTable
laws={ion_laws}
title={ion_law_nr + ' Laws:'}
isAdmin={isAdmin}
isMalf={isMalf}
mt={-2}
/>
) : (
''
)}
{has_zeroth_laws || has_inherent_laws ? (
<LawsTable laws={allLaws} title="Inherent Laws" mt={-2} />
<LawsTable
laws={allLaws}
title="Inherent Laws"
isAdmin={isAdmin}
isMalf={isMalf}
mt={-2}
/>
) : (
''
)}
{has_supplied_laws ? (
<LawsTable laws={supplied_laws} title="Supplied Laws" mt={-2} />
<LawsTable
laws={supplied_laws}
title="Supplied Laws"
isAdmin={isAdmin}
isMalf={isMalf}
mt={-2}
/>
) : (
''
)}
@@ -283,12 +386,12 @@ const LawsTable = (props: {
title: string;
noButtons?: BooleanLike;
[rest: string]: any;
isMalf: BooleanLike;
isAdmin: BooleanLike;
}) => {
const { act, data } = useBackend<Data>();
const { act } = useBackend();
const { isMalf, isAdmin } = data;
const { laws, title, noButtons, ...rest } = props;
const { laws, title, noButtons, isMalf, isAdmin, ...rest } = props;
return (
<Section title={title} {...rest}>
@@ -360,10 +463,24 @@ const LawsTable = (props: {
);
};
const LawManagerLawSets = (props) => {
const { act, data } = useBackend<Data>();
export const LawManagerLawSets = (props: {
law_sets: law_pack[];
ion_law_nr: string;
searchLawName: string;
onSearchLawName: Function;
isAdmin: BooleanLike;
isMalf: BooleanLike;
}) => {
const { act } = useBackend();
const { isMalf, law_sets, ion_law_nr } = data;
const {
law_sets,
ion_law_nr,
searchLawName,
onSearchLawName,
isMalf,
isAdmin,
} = props;
return (
<>
@@ -371,8 +488,14 @@ const LawManagerLawSets = (props) => {
Remember: Stating laws other than those currently loaded may be grounds
for decommissioning! - NanoTrasen
</NoticeBox>
<Input
fluid
value={searchLawName}
placeholder="Search for laws..."
onInput={(e, value: string) => onSearchLawName(value)}
/>
{law_sets.length
? law_sets.map((laws) => (
? prepareSearch(law_sets, searchLawName).map((laws) => (
<Section
key={laws.name}
title={laws.name}
@@ -403,6 +526,8 @@ const LawManagerLawSets = (props) => {
noButtons
laws={laws.laws.ion_laws}
title={ion_law_nr + ' Laws:'}
isAdmin={isAdmin}
isMalf={isMalf}
/>
) : (
''
@@ -412,6 +537,8 @@ const LawManagerLawSets = (props) => {
noButtons
laws={laws.laws.zeroth_laws.concat(laws.laws.inherent_laws)}
title={laws.header}
isAdmin={isAdmin}
isMalf={isMalf}
/>
) : (
''
@@ -421,6 +548,8 @@ const LawManagerLawSets = (props) => {
noButtons
laws={laws.laws.supplied_laws}
title="Supplied Laws"
isAdmin={isAdmin}
isMalf={isMalf}
/>
) : (
''
@@ -431,3 +560,23 @@ const LawManagerLawSets = (props) => {
</>
);
};
const prepareSearch = (
laws: law_pack[],
searchText: string = '',
): law_pack[] => {
const testSearch = createSearch(
searchText,
(law: law_pack) => law.name + law.header,
);
return flow([
(laws: law_pack[]) => {
// Optional search term
if (!searchText) {
return laws;
} else {
return filter(laws, testSearch);
}
},
])(laws);
};
@@ -1,18 +1,19 @@
import { useEffect, useState } from 'react';
import { useBackend } from 'tgui/backend';
import {
Box,
Button,
Divider,
Dropdown,
Input,
LabeledList,
NoticeBox,
Section,
Stack,
Tabs,
} from 'tgui/components';
import { Window } from 'tgui/layouts';
import { LawManagerLaws, LawManagerLawSets } from '../LawManager';
import { ModifyRobotNoModule } from './ModifyRobotNoModule';
import { ModifyRobotAccess } from './ModifyRobotTabs/ModifyRobotAccess';
import { ModifyRobotComponent } from './ModifyRobotTabs/ModifyRobotComponent';
@@ -34,10 +35,29 @@ export const ModifyRobot = (props) => {
cell_options,
id_icon,
access_options,
ion_law_nr,
ion_law,
zeroth_law,
inherent_law,
supplied_law,
supplied_law_position,
zeroth_laws,
ion_laws,
inherent_laws,
supplied_laws,
has_zeroth_laws,
has_ion_laws,
has_inherent_laws,
has_supplied_laws,
isAI,
channel,
channels,
law_sets,
} = data;
const [tab, setTab] = useState<number>(0);
const [robotName, setRobotName] = useState<string>(target ? target.name : '');
const [searchLawName, setSearchLawName] = useState<string>('');
useEffect(() => {
if (target?.name) {
@@ -67,8 +87,43 @@ export const ModifyRobot = (props) => {
all_access={access_options!}
/>
);
tabs[6] = <Box />;
tabs[7] = <Box />;
tabs[6] = (
<LawManagerLaws
isAdmin
isMalf
hasScroll
sectionHeight="85%"
ion_law_nr={ion_law_nr}
ion_law={ion_law}
zeroth_law={zeroth_law}
inherent_law={inherent_law}
supplied_law={supplied_law}
supplied_law_position={supplied_law_position}
zeroth_laws={zeroth_laws}
ion_laws={ion_laws}
inherent_laws={inherent_laws}
supplied_laws={supplied_laws}
has_zeroth_laws={has_zeroth_laws}
has_ion_laws={has_ion_laws}
has_inherent_laws={has_inherent_laws}
has_supplied_laws={has_supplied_laws}
isAI={isAI}
channel={channel}
channels={channels}
/>
);
tabs[7] = (
<Section scrollable fill height="85%">
<LawManagerLawSets
isAdmin
isMalf
law_sets={law_sets}
ion_law_nr={ion_law_nr}
searchLawName={searchLawName}
onSearchLawName={setSearchLawName}
/>
</Section>
);
return (
<Window width={target?.module ? 900 : 400} height={700}>
@@ -9,6 +9,24 @@ export type Data = {
cell_options: Record<string, Cell>;
id_icon: string;
access_options: Access[] | undefined;
ion_law_nr: string;
ion_law: string;
zeroth_law: string;
inherent_law: string;
supplied_law: string;
supplied_law_position: number;
zeroth_laws: law[];
ion_laws: law[];
inherent_laws: law[];
supplied_laws: law[];
has_zeroth_laws: number;
has_ion_laws: number;
has_inherent_laws: number;
has_supplied_laws: number;
isAI: BooleanLike;
channel: string;
channels: { channel: string }[];
law_sets: law_pack[];
};
export type DropdownEntry = {
@@ -89,3 +107,27 @@ export type Cell = {
};
export type Access = { id: number; name: string };
type law_pack = {
name: string;
header: string;
ref: string;
laws: {
zeroth_laws: law[];
has_zeroth_laws: number;
ion_laws: law[];
has_ion_laws: number;
inherent_laws: law[];
has_inherent_laws: number;
supplied_laws: law[];
has_supplied_laws: number;
};
};
type law = {
law: string;
index: number;
state: number;
ref: string;
zero: boolean; // Local UI var
};