mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-12 03:02:54 +00:00
EventKit - Mob Spawner
This commit is contained in:
3
code/modules/eventkit/event_machinery.dm
Normal file
3
code/modules/eventkit/event_machinery.dm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/obj/machinery/eventkit/custom
|
||||||
|
name = "Custom Machine"
|
||||||
|
desc = "A custom machine created by a GM."
|
||||||
132
code/modules/eventkit/gm_interfaces/mob_spawner.dm
Normal file
132
code/modules/eventkit/gm_interfaces/mob_spawner.dm
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/datum/eventkit/mob_spawner
|
||||||
|
// The path of the mob to be spawned
|
||||||
|
var/path
|
||||||
|
|
||||||
|
// Defines if the location of the spawned mob should be bound of the users position
|
||||||
|
var/loc_lock = FALSE
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/New()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/tgui_interact(mob/user, datum/tgui/ui)
|
||||||
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
|
if(!ui)
|
||||||
|
ui = new(user, src, "MobSpawner", "EventKit - Mob Spawner")
|
||||||
|
ui.set_autoupdate(FALSE)
|
||||||
|
ui.open()
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/Destroy()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_admin_state
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/tgui_static_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
|
||||||
|
data["mob_paths"] = typesof(/mob);
|
||||||
|
|
||||||
|
data["initial_x"] = usr.x;
|
||||||
|
data["initial_y"] = usr.y;
|
||||||
|
data["initial_z"] = usr.z;
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/tgui_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
|
||||||
|
data["loc_lock"] = loc_lock;
|
||||||
|
if(loc_lock)
|
||||||
|
data["loc_x"] = usr.x;
|
||||||
|
data["loc_y"] = usr.y;
|
||||||
|
data["loc_z"] = usr.z;
|
||||||
|
|
||||||
|
data["path"] = path;
|
||||||
|
|
||||||
|
var/mob/M = new path();
|
||||||
|
if(M)
|
||||||
|
data["default_path_name"] = M.name;
|
||||||
|
data["default_desc"] = M.desc;
|
||||||
|
data["default_flavor_text"] = M.flavor_text;
|
||||||
|
qdel(M);
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/tgui_act(action, list/params)
|
||||||
|
. = ..()
|
||||||
|
if(.)
|
||||||
|
return
|
||||||
|
if(!check_rights_for(usr.client, R_SPAWN))
|
||||||
|
return
|
||||||
|
switch(action)
|
||||||
|
if("select_path")
|
||||||
|
path = params["path"]
|
||||||
|
return TRUE
|
||||||
|
if("loc_lock")
|
||||||
|
loc_lock = !loc_lock
|
||||||
|
return TRUE
|
||||||
|
if("start_spawn")
|
||||||
|
var/confirm = tgui_alert(usr, "Are you sure that you want to start spawning your custom mobs?", "Confirmation", list("Yes", "Cancel"))
|
||||||
|
|
||||||
|
if(confirm != "Yes")
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
var/amount = params["amount"]
|
||||||
|
var/name = params["name"]
|
||||||
|
var/x = params["x"]
|
||||||
|
var/y = params["y"]
|
||||||
|
var/z = params["z"]
|
||||||
|
|
||||||
|
var/turf/T = locate(x, y, z)
|
||||||
|
if(!T)
|
||||||
|
to_chat(usr, "<span class='warning'>Those coordinates are outside the boundaries of the map.</span>")
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
for(var/i = 0, i < amount, i++)
|
||||||
|
if(ispath(path,/turf))
|
||||||
|
var/turf/TU = get_turf(locate(x, y, z))
|
||||||
|
TU.ChangeTurf(path)
|
||||||
|
else
|
||||||
|
var/mob/M = new path(usr.loc)
|
||||||
|
|
||||||
|
M.name = sanitize(name)
|
||||||
|
M.desc = sanitize(params["desc"])
|
||||||
|
M.flavor_text = sanitize(params["flavor_text"])
|
||||||
|
|
||||||
|
/*
|
||||||
|
WIP: Radius around selected coords
|
||||||
|
|
||||||
|
var/list/turf/destTurfs
|
||||||
|
for(var/turf/RT in orange(T, params["r"]))
|
||||||
|
destTurfs += RT
|
||||||
|
|
||||||
|
var/turf/targetTurf = rand(0,length(destTurfs))
|
||||||
|
*/
|
||||||
|
|
||||||
|
var/size_mul = params["size_multiplier"]
|
||||||
|
if(isnum(size_mul))
|
||||||
|
M.size_multiplier = size_mul
|
||||||
|
M.update_icon()
|
||||||
|
else
|
||||||
|
to_chat(usr, "<span class='warning'>Size Multiplier not applied: ([size_mul]) is not a valid input.</span>")
|
||||||
|
|
||||||
|
M.forceMove(T)
|
||||||
|
|
||||||
|
log_and_message_admins("spawned [path] ([name]) at ([x],[y],[z]) [amount] times.")
|
||||||
|
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/eventkit/mob_spawner/tgui_close(mob/user)
|
||||||
|
. = ..()
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
|
/client/verb/eventkit_open_mob_spawner()
|
||||||
|
set category = "EventKit"
|
||||||
|
set name = "Open Mob Spawner"
|
||||||
|
set desc = "Opens an advanced version of the mob spawner."
|
||||||
|
|
||||||
|
if(!check_rights(R_SPAWN))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/datum/eventkit/mob_spawner/spawner = new()
|
||||||
|
spawner.tgui_interact(usr)
|
||||||
@@ -74,9 +74,14 @@
|
|||||||
/**
|
/**
|
||||||
* Resizes the mob immediately to the desired mod, animating it growing/shrinking.
|
* Resizes the mob immediately to the desired mod, animating it growing/shrinking.
|
||||||
* It can be used by anything that calls it.
|
* It can be used by anything that calls it.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * new_size - CHANGE_ME.
|
||||||
|
* * animate - CHANGE_ME. Default: TRUE
|
||||||
|
* * uncapped - CHANGE_ME. Default: FALSE
|
||||||
|
* * ignore_prefs - CHANGE_ME. Default: FALSE
|
||||||
|
* * aura_animation - CHANGE_ME. Default: TRUE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/mob/living/proc/resize(var/new_size, var/animate = TRUE, var/uncapped = FALSE, var/ignore_prefs = FALSE, var/aura_animation = TRUE)
|
/mob/living/proc/resize(var/new_size, var/animate = TRUE, var/uncapped = FALSE, var/ignore_prefs = FALSE, var/aura_animation = TRUE)
|
||||||
if(!uncapped)
|
if(!uncapped)
|
||||||
new_size = clamp(new_size, RESIZE_MINIMUM, RESIZE_MAXIMUM)
|
new_size = clamp(new_size, RESIZE_MINIMUM, RESIZE_MAXIMUM)
|
||||||
|
|||||||
211
tgui/packages/tgui/interfaces/MobSpawner.tsx
Normal file
211
tgui/packages/tgui/interfaces/MobSpawner.tsx
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
import { BooleanLike } from '../../common/react';
|
||||||
|
import { useBackend, useLocalState } from '../backend';
|
||||||
|
import { Button, Dropdown, Flex, Input, Knob, LabeledList, NumberInput, Section, Tabs, TextArea } from '../components';
|
||||||
|
import { Window } from '../layouts';
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
path: string;
|
||||||
|
|
||||||
|
default_path_name: string;
|
||||||
|
default_desc: string;
|
||||||
|
default_flavor_text: string;
|
||||||
|
|
||||||
|
default_speak_emotes: string[];
|
||||||
|
|
||||||
|
mob_paths: string[];
|
||||||
|
|
||||||
|
loc_lock: BooleanLike;
|
||||||
|
loc_x: number;
|
||||||
|
loc_y: number;
|
||||||
|
loc_z: number;
|
||||||
|
|
||||||
|
initial_x: number;
|
||||||
|
initial_y: number;
|
||||||
|
initial_z: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MobSpawner = (props, context) => {
|
||||||
|
const { act, data } = useBackend<Data>(context);
|
||||||
|
|
||||||
|
const [tabIndex, setTabIndex] = useLocalState(context, 'panelTabIndex', 0);
|
||||||
|
|
||||||
|
const tabs: any = [];
|
||||||
|
|
||||||
|
tabs[0] = <GeneralMobSettings />;
|
||||||
|
tabs[1] = <VoreMobSettings />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Window width={890} height={660} theme="abstract" resizable>
|
||||||
|
<Window.Content scrollable>
|
||||||
|
<Tabs>
|
||||||
|
<Tabs.Tab selected={tabIndex === 0} onClick={() => setTabIndex(0)}>
|
||||||
|
General Settings
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab selected={tabIndex === 1} onClick={() => setTabIndex(1)}>
|
||||||
|
Vore Settings [WIP]
|
||||||
|
</Tabs.Tab>
|
||||||
|
</Tabs>
|
||||||
|
{tabs[tabIndex] || 'Error'}
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GeneralMobSettings = (props, context) => {
|
||||||
|
const { act, data } = useBackend<Data>(context);
|
||||||
|
|
||||||
|
const [amount, setAmount] = useLocalState(context, 'amount', 1);
|
||||||
|
const [name, setName] = useLocalState(
|
||||||
|
context,
|
||||||
|
'name',
|
||||||
|
data.default_path_name
|
||||||
|
);
|
||||||
|
const [desc, setDesc] = useLocalState(context, 'desc', data.default_desc);
|
||||||
|
const [flavorText, setFlavorText] = useLocalState(
|
||||||
|
context,
|
||||||
|
'flavorText',
|
||||||
|
data.default_flavor_text
|
||||||
|
);
|
||||||
|
|
||||||
|
const [sizeMultiplier, setSizeMultiplier] = useLocalState(
|
||||||
|
context,
|
||||||
|
'sizeMultiplier',
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
|
const [x, setX] = useLocalState(context, 'x', data.initial_x);
|
||||||
|
const [y, setY] = useLocalState(context, 'y', data.initial_y);
|
||||||
|
const [z, setZ] = useLocalState(context, 'z', data.initial_z);
|
||||||
|
|
||||||
|
const [radius, setRadius] = useLocalState(context, 'radius', 0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Section title="General">
|
||||||
|
<LabeledList>
|
||||||
|
<LabeledList.Item label="Mob Name">
|
||||||
|
<Input
|
||||||
|
fluid
|
||||||
|
value={name || data.default_path_name}
|
||||||
|
onChange={(e, val) => setName(val)}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Mob Path">
|
||||||
|
<Dropdown
|
||||||
|
fluid
|
||||||
|
options={data.mob_paths}
|
||||||
|
displayText={data.path || 'No path selected yet.'}
|
||||||
|
onSelected={(val) => act('select_path', { path: val })}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Spawn Amount">
|
||||||
|
<NumberInput
|
||||||
|
value={amount}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={256}
|
||||||
|
onChange={(e, val) => setAmount(val)}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label={'Size (' + sizeMultiplier + '%)'}>
|
||||||
|
<Knob
|
||||||
|
value={sizeMultiplier}
|
||||||
|
minValue={50}
|
||||||
|
maxValue={200}
|
||||||
|
unit="%"
|
||||||
|
onChange={(e, val) => setSizeMultiplier(val)}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
</LabeledList>
|
||||||
|
</Section>
|
||||||
|
<Section title="Positional Settings">
|
||||||
|
<LabeledList>
|
||||||
|
<LabeledList.Item label="Spawn (X/Y/Z) Coords">
|
||||||
|
<NumberInput
|
||||||
|
value={data.loc_lock ? data.loc_x : x}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={256}
|
||||||
|
onChange={(e, val) => setX(val)}
|
||||||
|
/>
|
||||||
|
<NumberInput
|
||||||
|
value={data.loc_lock ? data.loc_y : y}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={256}
|
||||||
|
onChange={(e, val) => setY(val)}
|
||||||
|
/>
|
||||||
|
<NumberInput
|
||||||
|
value={data.loc_lock ? data.loc_z : z}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={256}
|
||||||
|
onChange={(e, val) => setZ(val)}
|
||||||
|
/>
|
||||||
|
<Button.Checkbox
|
||||||
|
content="Lock coords to self"
|
||||||
|
checked={data.loc_lock}
|
||||||
|
onClick={() => act('loc_lock')}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
<LabeledList.Item label="Spawn Radius (WIP)">
|
||||||
|
<NumberInput
|
||||||
|
value={radius}
|
||||||
|
disabled
|
||||||
|
minValue={0}
|
||||||
|
maxValue={256}
|
||||||
|
onChange={(e, val) => setRadius(val)}
|
||||||
|
/>
|
||||||
|
</LabeledList.Item>
|
||||||
|
</LabeledList>
|
||||||
|
</Section>
|
||||||
|
<Section title="Descriptions">
|
||||||
|
<Flex>
|
||||||
|
<Flex.Item width="50%">
|
||||||
|
Description:
|
||||||
|
<br />
|
||||||
|
<TextArea
|
||||||
|
height={'18rem'}
|
||||||
|
onChange={(e, val) => setDesc(val)}
|
||||||
|
value={desc || data.default_desc}
|
||||||
|
/>
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item width="50%">
|
||||||
|
Flavor Text:
|
||||||
|
<br />
|
||||||
|
<TextArea
|
||||||
|
height={'18rem'}
|
||||||
|
value={flavorText || data.default_flavor_text}
|
||||||
|
onChange={(e, val) => setFlavorText(val)}
|
||||||
|
/>
|
||||||
|
</Flex.Item>
|
||||||
|
</Flex>
|
||||||
|
</Section>
|
||||||
|
<Button
|
||||||
|
color="teal"
|
||||||
|
onCLick={() =>
|
||||||
|
act('start_spawn', {
|
||||||
|
amount: amount,
|
||||||
|
name: name,
|
||||||
|
desc: desc,
|
||||||
|
flavor_text: flavorText,
|
||||||
|
size_multiplier: sizeMultiplier * 0.01,
|
||||||
|
x: data.loc_lock ? data.loc_x : x,
|
||||||
|
y: data.loc_lock ? data.loc_y : y,
|
||||||
|
z: data.loc_lock ? data.loc_z : z,
|
||||||
|
radius: radius,
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
Spawn
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const VoreMobSettings = (props, context) => {
|
||||||
|
const { act, data } = useBackend<Data>(context);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="WIP">
|
||||||
|
This Tab is still under construction!
|
||||||
|
<br />
|
||||||
|
Functionality will be added in later updates.
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -2365,6 +2365,8 @@
|
|||||||
#include "code\modules\error_handler\error_handler.dm"
|
#include "code\modules\error_handler\error_handler.dm"
|
||||||
#include "code\modules\error_handler\error_viewer.dm"
|
#include "code\modules\error_handler\error_viewer.dm"
|
||||||
#include "code\modules\error_handler\~defines.dm"
|
#include "code\modules\error_handler\~defines.dm"
|
||||||
|
#include "code\modules\eventkit\event_machinery.dm"
|
||||||
|
#include "code\modules\eventkit\gm_interfaces\mob_spawner.dm"
|
||||||
#include "code\modules\events\apc_damage.dm"
|
#include "code\modules\events\apc_damage.dm"
|
||||||
#include "code\modules\events\atmos_leak.dm"
|
#include "code\modules\events\atmos_leak.dm"
|
||||||
#include "code\modules\events\aurora_caelus.dm"
|
#include "code\modules\events\aurora_caelus.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user