mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
MOD Remote Control module (#4328)
## About The Pull Request Adds a MOD remote module that can control a modsuit remotely. ## Why It's Good For The Game Eventually I want to transition Proteans to this system where you access all your abilities via the UI of your modsuit. But I think it'll be fun to allow these interactions with all mods and a framework to expand on it. ## Proof Of Testing <img width="686" height="379" alt="image" src="https://github.com/user-attachments/assets/fe83beb8-4c99-45be-a19e-77b6bdfaa856" />  ## Changelog 🆑 add: MODsuit Remote Module that allows you to remotely control other people's modsuits /🆑
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
/datum/design/modlink_scryer
|
||||
// use the loaded modlink scryer object to have the frequency set to NT upon creation
|
||||
build_path = /obj/item/clothing/neck/link_scryer/loaded
|
||||
|
||||
/datum/design/module/mod_remote
|
||||
name = "MODsuit Remote Module"
|
||||
id = "mod_remote_module"
|
||||
build_path = /obj/item/mod/module/remote_control
|
||||
materials = list(
|
||||
/datum/material/iron = SHEET_MATERIAL_AMOUNT *3 ,
|
||||
/datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.5,
|
||||
)
|
||||
research_icon_state = "module_remote"
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
/obj/item/mind_controller/Destroy(force)
|
||||
collar?.remote = null
|
||||
collar = null
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/obj/item/mind_controller/attack_self(mob/user)
|
||||
if(!collar)
|
||||
@@ -274,7 +274,7 @@
|
||||
inhand_icon_state = null
|
||||
kink_collar = TRUE
|
||||
/// Reference to the mind control remote
|
||||
var/obj/item/mind_controller/remote = null
|
||||
var/obj/item/mind_controller/remote
|
||||
var/emoting = "Shivers."
|
||||
|
||||
/obj/item/clothing/neck/mind_collar/Initialize(mapload)
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
"products" = list(
|
||||
/obj/item/mod/construction/plating/lustwish = 5,
|
||||
/obj/item/mod/module/hypno_visor = 5,
|
||||
/obj/item/mod/module/remote_control = 5,
|
||||
)
|
||||
),
|
||||
list(
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
var/datum/mod_theme/the_theme = GLOB.mod_themes[plates.theme]
|
||||
|
||||
name = initial(name)
|
||||
name = initial(desc)
|
||||
desc = initial(desc)
|
||||
|
||||
for(var/obj/item/part as anything in get_parts())
|
||||
part.name = initial(name)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
theme = /datum/mod_theme/lustwish
|
||||
|
||||
/obj/item/mod/module/hypno_visor
|
||||
name = "Hypnosis Module"
|
||||
name = "hypnosis module"
|
||||
desc = "A module inserted into the visor of a suit in which commands can be processed. Use on self to set directives."
|
||||
icon = 'modular_zubbers/icons/mob/clothing/modsuit/mod_modules.dmi'
|
||||
icon_state = "module_hypno"
|
||||
@@ -47,3 +47,89 @@
|
||||
. = ..()
|
||||
if(isnull(overlay_state_inactive))
|
||||
overlay_state_inactive = initial(overlay_state_inactive)
|
||||
|
||||
/datum/storage/pockets/small/remote_module
|
||||
max_slots = 1
|
||||
|
||||
/datum/storage/pockets/small/remote_module/New(atom/parent, max_slots, max_specific_storage, max_total_storage, rustle_sound, remove_rustle_sound)
|
||||
. = ..()
|
||||
set_holdable(can_hold_list = list(/obj/item/remote_controller))
|
||||
|
||||
/obj/item/mod/module/remote_control
|
||||
name = "modsuit remote module"
|
||||
desc = "A module, once inserted, will allow anyone with its linked remote to control all functionality of the suit."
|
||||
icon = 'modular_zubbers/icons/mob/clothing/modsuit/mod_modules.dmi'
|
||||
icon_state = "module_remote"
|
||||
module_type = MODULE_PASSIVE
|
||||
complexity = 0
|
||||
idle_power_cost = DEFAULT_CHARGE_DRAIN * 0
|
||||
incompatible_modules = list(/obj/item/mod/module/remote_control)
|
||||
required_slots = list(ITEM_SLOT_OCLOTHING)
|
||||
overlay_state_inactive = "module_remote_overlay"
|
||||
overlay_icon_file = 'modular_zubbers/icons/mob/clothing/modsuit/mod_modules.dmi'
|
||||
|
||||
/obj/item/mod/module/remote_control/Initialize(mapload)
|
||||
. = ..()
|
||||
create_storage(storage_type = /datum/storage/pockets/small/remote_module)
|
||||
var/obj/item/remote_controller/remote = new /obj/item/remote_controller()
|
||||
remote.module = src
|
||||
remote.forceMove(src)
|
||||
|
||||
/obj/item/mod/module/remote_control/can_install(obj/item/mod/control/mod)
|
||||
if(locate(/obj/item/remote_controller) in contents)
|
||||
balloon_alert(usr, "remove remote from storage")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/remote_control/attack_self(mob/user)
|
||||
. = ..()
|
||||
atom_storage?.open_storage(user)
|
||||
|
||||
/obj/item/remote_controller
|
||||
name = "modsuit remote"
|
||||
desc = "A remote that allows control of a modsuit once its paired module is inserted."
|
||||
icon = 'modular_zubbers/icons/mob/clothing/modsuit/mod_modules.dmi'
|
||||
icon_state = "remote_item"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/obj/item/mod/module/remote_control/module
|
||||
|
||||
/obj/item/remote_controller/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "MODsuitremote")
|
||||
ui.open()
|
||||
|
||||
/obj/item/remote_controller/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["linked_suit"] = !!module?.mod
|
||||
data["wearer"] = !!module.mod?.wearer
|
||||
data["erp_pref_check"] = module.mod?.wearer?.client?.prefs.read_preference(/datum/preference/toggle/erp/sex_toy)
|
||||
if(module.mod)
|
||||
data += module.mod.ui_data()
|
||||
return data
|
||||
|
||||
/obj/item/remote_controller/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("emote")
|
||||
module.mod.wearer.emote("me", 1, params["emote"], TRUE)
|
||||
|
||||
/obj/item/remote_controller/proc/forced_emote(emoter, user)
|
||||
|
||||
/obj/item/remote_controller/Initialize(mapload, module_init)
|
||||
. = ..()
|
||||
src.module = module_init
|
||||
|
||||
/obj/item/remote_controller/ui_static_data(mob/user)
|
||||
return module?.mod?.ui_static_data()
|
||||
|
||||
/obj/item/remote_controller/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
return module?.mod?.ui_act(action, params, ui, state)
|
||||
|
||||
/obj/item/remote_controller/Destroy(force)
|
||||
module = null
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -146,6 +146,11 @@
|
||||
design_ids += "mod_mind_transfer"
|
||||
. = ..()
|
||||
|
||||
// Modsuit tech
|
||||
/datum/techweb_node/mod_equip/New()
|
||||
. = ..()
|
||||
design_ids += list("mod_remote_module")
|
||||
|
||||
/datum/techweb_node/nerd
|
||||
id = TECHWEB_NODE_NERD
|
||||
display_name = "Theoretical Physics"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 973 B After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,84 @@
|
||||
// BUBBER UI FILE
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Icon, Input, LabeledList, Modal, Section } from 'tgui-core/components';
|
||||
|
||||
import { useBackend } from '../backend';
|
||||
import { Window } from '../layouts';
|
||||
import { MODsuitContent } from './MODsuit';
|
||||
|
||||
type Data = {
|
||||
ui_theme?: string;
|
||||
linked_suit?: boolean;
|
||||
wearer?: boolean;
|
||||
erp_pref_check?: boolean;
|
||||
};
|
||||
export const MODsuitremote = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
const { ui_theme } = data;
|
||||
return (
|
||||
<Window
|
||||
theme={ui_theme}
|
||||
width={600}
|
||||
height={600}
|
||||
title="MOD Remote Interface"
|
||||
>
|
||||
<Window.Content scrollable>
|
||||
<RemoteMODsuitContent />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const RemoteSection = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
const { erp_pref_check } = data;
|
||||
const [emote, setEmote] = useState('');
|
||||
return (
|
||||
<Section title="Remote Control">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Force Emote">
|
||||
<Input
|
||||
fluid
|
||||
selfClear
|
||||
onChange={setEmote}
|
||||
disabled={!erp_pref_check}
|
||||
onEnter={() => act('emote', { emote: emote })}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
const RemoteMODsuitContent = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
const { linked_suit, wearer } = data;
|
||||
if (!linked_suit) {
|
||||
return (
|
||||
<Modal>
|
||||
<center>
|
||||
<Icon size={5} name="triangle-exclamation" />
|
||||
</center>
|
||||
<br />
|
||||
Not installed
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
if (!wearer) {
|
||||
return (
|
||||
<Modal>
|
||||
<center>
|
||||
<Icon size={5} name="triangle-exclamation" />
|
||||
</center>
|
||||
<br />
|
||||
MODsuit Not Worn
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<RemoteSection />
|
||||
<MODsuitContent />
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user