mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-12 03:02:54 +00:00
[MIRROR] Add Multishock integration (#11003)
Co-authored-by: ShadowLarkens <shadowlarkens@gmail.com>
This commit is contained in:
committed by
GitHub
parent
76c9d5e08a
commit
74d886613b
4
code/__defines/shock.dm
Normal file
4
code/__defines/shock.dm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// KEEP THIS UP TO DATE WITH tgui/packages/tgui/interfaces/ShockConfigurator.tsx
|
||||||
|
#define SHOCKFLAG_BURNDAMAGE 0x1
|
||||||
|
#define SHOCKFLAG_DIGESTION 0x2
|
||||||
|
#define SHOCKFLAG_TEST "test"
|
||||||
@@ -256,6 +256,7 @@
|
|||||||
|
|
||||||
// Instantiate tgui panel
|
// Instantiate tgui panel
|
||||||
tgui_say = new(src, "tgui_say")
|
tgui_say = new(src, "tgui_say")
|
||||||
|
tgui_shocker = new(src, "tgui_shock")
|
||||||
initialize_commandbar_spy()
|
initialize_commandbar_spy()
|
||||||
tgui_panel = new(src, "browseroutput")
|
tgui_panel = new(src, "browseroutput")
|
||||||
|
|
||||||
@@ -304,6 +305,7 @@
|
|||||||
|
|
||||||
// Initialize tgui panel
|
// Initialize tgui panel
|
||||||
tgui_say.initialize()
|
tgui_say.initialize()
|
||||||
|
tgui_shocker.initialize()
|
||||||
|
|
||||||
connection_time = world.time
|
connection_time = world.time
|
||||||
connection_realtime = world.realtime
|
connection_realtime = world.realtime
|
||||||
|
|||||||
149
code/modules/client/shock.dm
Normal file
149
code/modules/client/shock.dm
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/client/var/datum/tgui_shock/tgui_shocker
|
||||||
|
|
||||||
|
/client/verb/configure_shocker()
|
||||||
|
set name = "Configure MultiShock Integration"
|
||||||
|
set category = "OOC.Game Settings"
|
||||||
|
|
||||||
|
if(tgui_shocker)
|
||||||
|
tgui_shocker.tgui_interact(mob)
|
||||||
|
|
||||||
|
/mob/proc/attempt_multishock(flag)
|
||||||
|
client?.attempt_multishock(flag)
|
||||||
|
|
||||||
|
/client/proc/attempt_multishock(flag)
|
||||||
|
tgui_shocker?.shock(flag)
|
||||||
|
|
||||||
|
// NOTE: This datum controls TWO UIs, `window` is hidden and provides all of the WebSocket shit, `tgui_interact` is a
|
||||||
|
// normal configuration UI!
|
||||||
|
/datum/tgui_shock
|
||||||
|
/// The user who opened the window
|
||||||
|
var/client/client
|
||||||
|
/// The modal window
|
||||||
|
var/datum/tgui_window/window
|
||||||
|
|
||||||
|
var/port = 8765
|
||||||
|
var/enabled_flags = 0
|
||||||
|
var/intensity = 15
|
||||||
|
var/duration = 1
|
||||||
|
|
||||||
|
var/connected = FALSE
|
||||||
|
var/selected_device = -1
|
||||||
|
var/list/available_devices
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
// SHOCK.JS UI //
|
||||||
|
//////////////////////////////////////////
|
||||||
|
/datum/tgui_shock/New(client/client, id)
|
||||||
|
src.client = client
|
||||||
|
window = new(client, id)
|
||||||
|
window.subscribe(src, PROC_REF(on_message))
|
||||||
|
window.is_browser = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_shock/proc/initialize()
|
||||||
|
set waitfor = FALSE
|
||||||
|
window.initialize(
|
||||||
|
inline_js = file2text('html/shock.js')
|
||||||
|
)
|
||||||
|
|
||||||
|
/datum/tgui_shock/proc/connect()
|
||||||
|
window.send_message("connect", list(
|
||||||
|
"port" = port,
|
||||||
|
))
|
||||||
|
|
||||||
|
/datum/tgui_shock/proc/request_devices()
|
||||||
|
if(!connected)
|
||||||
|
return
|
||||||
|
window.send_message("enumerateShockers")
|
||||||
|
|
||||||
|
/datum/tgui_shock/proc/shock(flag)
|
||||||
|
if(!connected || !selected_device)
|
||||||
|
return
|
||||||
|
|
||||||
|
if(flag != SHOCKFLAG_TEST)
|
||||||
|
if(!(enabled_flags & flag))
|
||||||
|
return
|
||||||
|
|
||||||
|
window.send_message("shock", list(
|
||||||
|
"intensity" = intensity,
|
||||||
|
"duration" = duration,
|
||||||
|
"shocker_ids" = list(
|
||||||
|
selected_device
|
||||||
|
),
|
||||||
|
"warning" = FALSE,
|
||||||
|
))
|
||||||
|
|
||||||
|
/datum/tgui_shock/proc/estop()
|
||||||
|
window.send_message("estop")
|
||||||
|
|
||||||
|
/datum/tgui_shock/proc/on_message(type, payload, href_list)
|
||||||
|
if(type == "connected")
|
||||||
|
connected = TRUE
|
||||||
|
else if(type == "disconnected")
|
||||||
|
connected = FALSE
|
||||||
|
else if(type == "error")
|
||||||
|
connected = FALSE
|
||||||
|
log_debug("WebSocket Error [json_encode(payload)]")
|
||||||
|
else if(type == "incomingMessage")
|
||||||
|
if(payload["lastCall"] == "get_devices")
|
||||||
|
available_devices = json_decode(payload["data"])
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
// TGUI //
|
||||||
|
//////////////////////////////////////////
|
||||||
|
/datum/tgui_shock/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_always_state
|
||||||
|
|
||||||
|
/datum/tgui_shock/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui, custom_state)
|
||||||
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
|
if(!ui)
|
||||||
|
ui = new(user, src, "ShockConfigurator", "Shock Configurator")
|
||||||
|
ui.open()
|
||||||
|
|
||||||
|
/datum/tgui_shock/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
data["port"] = port
|
||||||
|
data["connected"] = connected
|
||||||
|
data["intensity"] = intensity
|
||||||
|
data["duration"] = duration
|
||||||
|
data["selectedDevice"] = selected_device
|
||||||
|
data["availableDevices"] = available_devices
|
||||||
|
data["enabledFlags"] = enabled_flags
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_shock/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("connect")
|
||||||
|
if(connected)
|
||||||
|
estop()
|
||||||
|
else
|
||||||
|
// TODO: preferences
|
||||||
|
connect()
|
||||||
|
. = TRUE
|
||||||
|
if("request_devices")
|
||||||
|
request_devices()
|
||||||
|
. = TRUE
|
||||||
|
if("estop")
|
||||||
|
estop()
|
||||||
|
. = TRUE
|
||||||
|
if("setSelectedDevice")
|
||||||
|
selected_device = text2num(params["device"])
|
||||||
|
. = TRUE
|
||||||
|
if("test")
|
||||||
|
shock(SHOCKFLAG_TEST)
|
||||||
|
. = TRUE
|
||||||
|
if("set_flag")
|
||||||
|
enabled_flags ^= text2num(params["flag"])
|
||||||
|
. = TRUE
|
||||||
|
if("port")
|
||||||
|
port = text2num(params["port"])
|
||||||
|
. = TRUE
|
||||||
|
if("intensity")
|
||||||
|
intensity = text2num(params["intensity"])
|
||||||
|
. = TRUE
|
||||||
|
if("duration")
|
||||||
|
duration = text2num(params["duration"])
|
||||||
|
. = TRUE
|
||||||
@@ -76,6 +76,7 @@
|
|||||||
if(COLD_RESISTANCE in mutations)
|
if(COLD_RESISTANCE in mutations)
|
||||||
damage = 0
|
damage = 0
|
||||||
adjustFireLoss(damage * blocked)
|
adjustFireLoss(damage * blocked)
|
||||||
|
attempt_multishock(SHOCKFLAG_BURNDAMAGE)
|
||||||
if(SEARING)
|
if(SEARING)
|
||||||
apply_damage(round(damage / 3), BURN, def_zone, initial_blocked, soaked, sharp, edge, used_weapon)
|
apply_damage(round(damage / 3), BURN, def_zone, initial_blocked, soaked, sharp, edge, used_weapon)
|
||||||
apply_damage(round(damage / 3 * 2), BRUTE, def_zone, initial_blocked, soaked, sharp, edge, used_weapon)
|
apply_damage(round(damage / 3 * 2), BRUTE, def_zone, initial_blocked, soaked, sharp, edge, used_weapon)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ GLOBAL_LIST_INIT(digest_modes, list())
|
|||||||
L.adjustOxyLoss(B.digest_oxy)
|
L.adjustOxyLoss(B.digest_oxy)
|
||||||
L.adjustToxLoss(B.digest_tox)
|
L.adjustToxLoss(B.digest_tox)
|
||||||
L.adjustCloneLoss(B.digest_clone)
|
L.adjustCloneLoss(B.digest_clone)
|
||||||
|
L.attempt_multishock(SHOCKFLAG_DIGESTION)
|
||||||
// Send a message when a prey-thing enters hard crit.
|
// Send a message when a prey-thing enters hard crit.
|
||||||
if(iscarbon(L) && old_health > 0 && L.health <= 0)
|
if(iscarbon(L) && old_health > 0 && L.health <= 0)
|
||||||
to_chat(B.owner, span_notice("You feel [L] go still within your [lowertext(B.name)]."))
|
to_chat(B.owner, span_notice("You feel [L] go still within your [lowertext(B.name)]."))
|
||||||
|
|||||||
79
html/shock.js
Normal file
79
html/shock.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
let webSocket;
|
||||||
|
let authKey;
|
||||||
|
let lastCall;
|
||||||
|
|
||||||
|
const reactRoot = document.getElementById("react-root");
|
||||||
|
if (reactRoot) {
|
||||||
|
reactRoot.innerHTML = "<h1>You shouldn't see this window, update your skin.</h1>";
|
||||||
|
}
|
||||||
|
|
||||||
|
Byond.subscribeTo("estop", function () {
|
||||||
|
if (webSocket) {
|
||||||
|
webSocket.close();
|
||||||
|
} else {
|
||||||
|
Byond.sendMessage("disconnected");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Byond.subscribeTo("connect", function (data) {
|
||||||
|
if (webSocket) {
|
||||||
|
webSocket.close();
|
||||||
|
}
|
||||||
|
webSocket = new WebSocket(`ws://localhost:${data.port}`);
|
||||||
|
webSocket.sendJson = (data) => {
|
||||||
|
webSocket.send(JSON.stringify(data));
|
||||||
|
};
|
||||||
|
authKey = JSON.parse(window.hubStorage.getItem("virgo-shocker-authkey"));
|
||||||
|
webSocket.onopen = (ev) => {
|
||||||
|
Byond.sendMessage("connected");
|
||||||
|
};
|
||||||
|
webSocket.onerror = (ev) => {
|
||||||
|
Byond.sendMessage("error", ev);
|
||||||
|
};
|
||||||
|
webSocket.onclose = (ev) => {
|
||||||
|
Byond.sendMessage("disconnected");
|
||||||
|
}
|
||||||
|
webSocket.onmessage = (ev) => {
|
||||||
|
Byond.sendMessage("incomingMessage", { data: ev.data, lastCall });
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
Byond.subscribeTo("enumerateShockers", function () {
|
||||||
|
if (!webSocket) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastCall = "get_devices";
|
||||||
|
webSocket.sendJson({
|
||||||
|
cmd: "get_devices",
|
||||||
|
auth_key: authKey,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// data: {
|
||||||
|
// "intensity": 10, // 1 - 100 - int
|
||||||
|
// "duration": 1, // 0.1 - 15 - float
|
||||||
|
// "shocker_ids": [], // [] - List of shocker ids
|
||||||
|
// "warning": false, // true, false - will send a vibrate with the same intensity and duration
|
||||||
|
// },
|
||||||
|
Byond.subscribeTo("shock", function (data) {
|
||||||
|
if (!webSocket) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastCall = "operate";
|
||||||
|
webSocket.sendJson({
|
||||||
|
"cmd": "operate",
|
||||||
|
"value": {
|
||||||
|
"intensity": data.intensity, // 1 - 100 - int
|
||||||
|
"duration": data.duration, // 0.1 - 15 - float
|
||||||
|
"shocker_option": "all", // all, random
|
||||||
|
"action": "shock", // shock, vibrate, beep, end
|
||||||
|
"shocker_ids": data.shocker_ids, // [] - List of shocker ids
|
||||||
|
"device_ids": [], // [] - list of pishock client ids, if one of these is provided it will activate all shockers associated with it
|
||||||
|
"warning": data.warning, // true, false - will send a vibrate with the same intensity and duration
|
||||||
|
"held": false, // true, false - for continuous commands
|
||||||
|
},
|
||||||
|
"auth_key": authKey,
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1192,6 +1192,14 @@ window "mainwindow"
|
|||||||
anchor2 = -1,-1
|
anchor2 = -1,-1
|
||||||
is-visible = false
|
is-visible = false
|
||||||
saved-params = ""
|
saved-params = ""
|
||||||
|
elem "tgui_shock"
|
||||||
|
type = BROWSER
|
||||||
|
pos = 0,0
|
||||||
|
size = 200x200
|
||||||
|
anchor1 = -1,-1
|
||||||
|
anchor2 = -1,-1
|
||||||
|
is-visible = false
|
||||||
|
saved-params = ""
|
||||||
elem "hotkey_toggle"
|
elem "hotkey_toggle"
|
||||||
type = BUTTON
|
type = BUTTON
|
||||||
pos = 560,400
|
pos = 560,400
|
||||||
|
|||||||
208
tgui/packages/tgui/interfaces/ShockConfigurator.tsx
Normal file
208
tgui/packages/tgui/interfaces/ShockConfigurator.tsx
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
import { storage } from 'common/storage';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useBackend } from 'tgui/backend';
|
||||||
|
import { Window } from 'tgui/layouts';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Input,
|
||||||
|
LabeledList,
|
||||||
|
NumberInput,
|
||||||
|
Section,
|
||||||
|
Stack,
|
||||||
|
} from 'tgui-core/components';
|
||||||
|
import { type BooleanLike } from 'tgui-core/react';
|
||||||
|
|
||||||
|
// These are straight from https://docs.pishock.com/multishock/multishock-websocket-api.html
|
||||||
|
type MultishockAPIShocker = {
|
||||||
|
name: string;
|
||||||
|
identifier: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MultishockAPIDevice = {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
shockers: Array<MultishockAPIShocker>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MultishockAPIAvailableDevices = Array<MultishockAPIDevice>;
|
||||||
|
|
||||||
|
// KEEP THIS UP TO DATE WITH code/__defines/shock.dm
|
||||||
|
enum ShockFlags {
|
||||||
|
BurnDamage = 1,
|
||||||
|
Digestion = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
port: number;
|
||||||
|
authKey: string;
|
||||||
|
connected: BooleanLike;
|
||||||
|
intensity: number;
|
||||||
|
duration: number;
|
||||||
|
selectedDevice: number;
|
||||||
|
availableDevices: MultishockAPIAvailableDevices;
|
||||||
|
enabledFlags: ShockFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ShockConfigurator = (props) => {
|
||||||
|
const { act, data } = useBackend<Data>();
|
||||||
|
const {
|
||||||
|
port,
|
||||||
|
connected,
|
||||||
|
intensity,
|
||||||
|
duration,
|
||||||
|
selectedDevice,
|
||||||
|
availableDevices,
|
||||||
|
enabledFlags,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
const [authKey, setAuthKey] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const async_get = async () => {
|
||||||
|
setAuthKey(await storage.get('shocker-authkey'));
|
||||||
|
};
|
||||||
|
async_get();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Window width={400} height={600}>
|
||||||
|
<Window.Content>
|
||||||
|
<Section title="Status">
|
||||||
|
<Stack>
|
||||||
|
<Stack.Item grow>
|
||||||
|
{connected ? (
|
||||||
|
<Box inline color="good">
|
||||||
|
Connected
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Box inline color="bad">
|
||||||
|
Disconnected
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Stack.Item>
|
||||||
|
<Stack.Item>
|
||||||
|
<Button onClick={() => act('connect')}>
|
||||||
|
{connected ? 'Disconnect' : 'Connect'}
|
||||||
|
</Button>
|
||||||
|
<Button ml={1} onClick={() => act('estop')}>
|
||||||
|
E-STOP
|
||||||
|
</Button>
|
||||||
|
</Stack.Item>
|
||||||
|
</Stack>
|
||||||
|
<LabeledList>
|
||||||
|
<LabeledList.Item label="MultiShock Port">
|
||||||
|
<NumberInput
|
||||||
|
value={port}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={25565}
|
||||||
|
step={1}
|
||||||
|
onChange={(val) => act('port', { port: val })}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="MultiShock Auth Key">
|
||||||
|
<Input
|
||||||
|
value={authKey}
|
||||||
|
onChange={(val) => {
|
||||||
|
storage.set('shocker-authkey', val);
|
||||||
|
setAuthKey(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Shock Intensity">
|
||||||
|
<NumberInput
|
||||||
|
value={intensity}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={100}
|
||||||
|
step={1}
|
||||||
|
onChange={(val) => act('intensity', { intensity: val })}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Shock Duration (Seconds)">
|
||||||
|
<NumberInput
|
||||||
|
value={duration}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={15}
|
||||||
|
step={0.1}
|
||||||
|
onChange={(val) => act('duration', { duration: val })}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
</LabeledList>
|
||||||
|
<Button onClick={() => act('test')}>Test Shocker</Button>
|
||||||
|
<Box color="bad">
|
||||||
|
ETIQUITTE NOTE: You must let your partners know you're using
|
||||||
|
this!
|
||||||
|
</Box>
|
||||||
|
</Section>
|
||||||
|
<Section title="Shock Sources">
|
||||||
|
<Box>
|
||||||
|
This section indicates when you would like to be shocked. Note: Burn
|
||||||
|
+ Digestion is not recommended, as it will shock you twice per
|
||||||
|
digest tick.
|
||||||
|
</Box>
|
||||||
|
<Button.Checkbox
|
||||||
|
checked={enabledFlags & ShockFlags.BurnDamage}
|
||||||
|
selected={enabledFlags & ShockFlags.BurnDamage}
|
||||||
|
onClick={() => act('set_flag', { flag: ShockFlags.BurnDamage })}
|
||||||
|
>
|
||||||
|
Burn
|
||||||
|
</Button.Checkbox>
|
||||||
|
<Button.Checkbox
|
||||||
|
checked={enabledFlags & ShockFlags.Digestion}
|
||||||
|
selected={enabledFlags & ShockFlags.Digestion}
|
||||||
|
onClick={() => act('set_flag', { flag: ShockFlags.Digestion })}
|
||||||
|
>
|
||||||
|
Digestion
|
||||||
|
</Button.Checkbox>
|
||||||
|
</Section>
|
||||||
|
<Section
|
||||||
|
title="Devices"
|
||||||
|
buttons={
|
||||||
|
<Button
|
||||||
|
icon="refresh"
|
||||||
|
tooltip="Refresh"
|
||||||
|
onClick={() => act('request_devices')}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{availableDevices && availableDevices.length ? (
|
||||||
|
availableDevices.map((device) => (
|
||||||
|
<Box key={device.id}>
|
||||||
|
<Box bold>
|
||||||
|
Device: {device.name} - {device.id}
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
{device.shockers.map((shocker) => (
|
||||||
|
<Box ml={4} key={shocker.identifier}>
|
||||||
|
Shocker: {shocker.name} - {shocker.identifier}
|
||||||
|
<Button.Checkbox
|
||||||
|
ml={1}
|
||||||
|
checked={shocker.identifier === selectedDevice}
|
||||||
|
selected={shocker.identifier === selectedDevice}
|
||||||
|
onClick={() => {
|
||||||
|
if (shocker.identifier !== selectedDevice) {
|
||||||
|
act('setSelectedDevice', {
|
||||||
|
device: shocker.identifier,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
act('setSelectedDevice', {
|
||||||
|
device: -1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Use This Device
|
||||||
|
</Button.Checkbox>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Box color="bad">No Devices Found</Box>
|
||||||
|
)}
|
||||||
|
</Section>
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -54,7 +54,7 @@ export const VorePanelEditToggle = (props: {
|
|||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
<Stack.Item>
|
<Stack.Item>
|
||||||
<Button
|
<Button
|
||||||
icon={persistEditMode ? 'lock' : 'lock-open'}
|
icon={persistEditMode ? 'lock-open' : 'lock'}
|
||||||
selected={persistEditMode}
|
selected={persistEditMode}
|
||||||
tooltip={
|
tooltip={
|
||||||
(persistEditMode ? 'Dis' : 'En') +
|
(persistEditMode ? 'Dis' : 'En') +
|
||||||
|
|||||||
@@ -144,6 +144,7 @@
|
|||||||
#include "code\__defines\SDQL_2.dm"
|
#include "code\__defines\SDQL_2.dm"
|
||||||
#include "code\__defines\shadekin.dm"
|
#include "code\__defines\shadekin.dm"
|
||||||
#include "code\__defines\shields.dm"
|
#include "code\__defines\shields.dm"
|
||||||
|
#include "code\__defines\shock.dm"
|
||||||
#include "code\__defines\shuttle.dm"
|
#include "code\__defines\shuttle.dm"
|
||||||
#include "code\__defines\simple_mob.dm"
|
#include "code\__defines\simple_mob.dm"
|
||||||
#include "code\__defines\size.dm"
|
#include "code\__defines\size.dm"
|
||||||
@@ -2265,6 +2266,7 @@
|
|||||||
#include "code\modules\client\preferences_toggle_procs.dm"
|
#include "code\modules\client\preferences_toggle_procs.dm"
|
||||||
#include "code\modules\client\preferences_vr.dm"
|
#include "code\modules\client\preferences_vr.dm"
|
||||||
#include "code\modules\client\record_updater.dm"
|
#include "code\modules\client\record_updater.dm"
|
||||||
|
#include "code\modules\client\shock.dm"
|
||||||
#include "code\modules\client\spam_prevention.dm"
|
#include "code\modules\client\spam_prevention.dm"
|
||||||
#include "code\modules\client\stored_item.dm"
|
#include "code\modules\client\stored_item.dm"
|
||||||
#include "code\modules\client\ui_style.dm"
|
#include "code\modules\client\ui_style.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user