mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Revamps the jump to area and teleport menu (#21384)
* commit funny * random fixes * Update jumpto.dm
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
/atom/movable/screen/ghost/jump_to_mob/Click()
|
/atom/movable/screen/ghost/jump_to_mob/Click()
|
||||||
var/mob/dead/observer/G = usr
|
var/mob/dead/observer/G = usr
|
||||||
G.jump_to_mob()
|
G.dead_tele()
|
||||||
|
|
||||||
/atom/movable/screen/ghost/orbit
|
/atom/movable/screen/ghost/orbit
|
||||||
name = "Orbit"
|
name = "Orbit"
|
||||||
|
|||||||
75
code/modules/mob/dead/observer/jumpto.dm
Normal file
75
code/modules/mob/dead/observer/jumpto.dm
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/datum/jump_menu
|
||||||
|
var/mob/dead/observer/owner
|
||||||
|
var/auto_observe = FALSE
|
||||||
|
|
||||||
|
/datum/jump_menu/New(mob/dead/observer/new_owner)
|
||||||
|
if(!istype(new_owner))
|
||||||
|
qdel(src)
|
||||||
|
owner = new_owner
|
||||||
|
|
||||||
|
/datum/jump_menu/ui_state(mob/user)
|
||||||
|
return GLOB.observer_state
|
||||||
|
|
||||||
|
/datum/jump_menu/ui_interact(mob/user, datum/tgui/ui)
|
||||||
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
|
if (!ui)
|
||||||
|
ui = new(user, src, "Jump")
|
||||||
|
ui.open()
|
||||||
|
|
||||||
|
/datum/jump_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||||
|
. = ..()
|
||||||
|
if(.)
|
||||||
|
return
|
||||||
|
switch(action)
|
||||||
|
if ("jump")
|
||||||
|
if(!isobserver(usr))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/ref = params["ref"]
|
||||||
|
var/list/pois = GLOB.mob_list
|
||||||
|
var/atom/movable/poi = (locate(ref) in pois) || (locate(ref) in GLOB.areas)
|
||||||
|
|
||||||
|
if (!poi)
|
||||||
|
. = TRUE
|
||||||
|
return
|
||||||
|
|
||||||
|
if(isarea(poi))
|
||||||
|
var/area/A = poi
|
||||||
|
owner.forceMove(pick(get_area_turfs(A)))
|
||||||
|
else
|
||||||
|
owner.forceMove(get_turf(poi))
|
||||||
|
owner.reset_perspective(null)
|
||||||
|
if ("refresh")
|
||||||
|
update_static_data(owner, ui)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
/datum/jump_menu/ui_static_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
|
||||||
|
var/list/mobs = list()
|
||||||
|
var/list/areas
|
||||||
|
|
||||||
|
var/list/mob_list = GLOB.mob_list
|
||||||
|
for (var/mob/M in mob_list)
|
||||||
|
var/list/serialized = list()
|
||||||
|
serialized["name"] = M.name
|
||||||
|
serialized["ref"] = REF(M) // Apparently name isn't a direct ref.
|
||||||
|
mobs += list(serialized)
|
||||||
|
|
||||||
|
var/list/Alist = GLOB.areas
|
||||||
|
for (var/area/A in Alist)
|
||||||
|
if(A.hidden)
|
||||||
|
continue
|
||||||
|
var/list/serialized = list()
|
||||||
|
serialized["name"] = A.name
|
||||||
|
serialized["ref"] = REF(A)
|
||||||
|
areas += list(serialized)
|
||||||
|
|
||||||
|
data["mobs"] = mobs
|
||||||
|
data["areas"] = areas
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/jump_menu/ui_assets()
|
||||||
|
. = ..() || list()
|
||||||
|
. += get_asset_datum(/datum/asset/simple/orbit)
|
||||||
|
|
||||||
@@ -57,7 +57,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
|||||||
// Used for displaying in ghost chat, without changing the actual name
|
// Used for displaying in ghost chat, without changing the actual name
|
||||||
// of the mob
|
// of the mob
|
||||||
var/deadchat_name
|
var/deadchat_name
|
||||||
var/datum/orbit_menu/orbit_menu
|
var/datum/orbit_menu/orbit_ui
|
||||||
|
var/datum/jump_menu/jump_ui
|
||||||
var/datum/spawners_menu/spawners_menu
|
var/datum/spawners_menu/spawners_menu
|
||||||
|
|
||||||
///Action to quickly unobserve someone
|
///Action to quickly unobserve someone
|
||||||
@@ -182,7 +183,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
|||||||
|
|
||||||
updateallghostimages()
|
updateallghostimages()
|
||||||
|
|
||||||
QDEL_NULL(orbit_menu)
|
QDEL_NULL(orbit_ui)
|
||||||
|
QDEL_NULL(jump_ui)
|
||||||
QDEL_NULL(spawners_menu)
|
QDEL_NULL(spawners_menu)
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
@@ -435,42 +437,22 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
|||||||
/mob/dead/observer/proc/dead_tele()
|
/mob/dead/observer/proc/dead_tele()
|
||||||
set category = "Ghost"
|
set category = "Ghost"
|
||||||
set name = "Teleport"
|
set name = "Teleport"
|
||||||
set desc= "Teleport to a location"
|
set desc= "Ghostly Magic"
|
||||||
if(!isobserver(usr))
|
|
||||||
to_chat(usr, span_warning("Not when you're not dead!"))
|
|
||||||
return
|
|
||||||
var/list/filtered = list()
|
|
||||||
for(var/area/A as anything in get_sorted_areas())
|
|
||||||
if(!A.hidden)
|
|
||||||
filtered += A
|
|
||||||
var/area/thearea = tgui_input_list(usr, "Area to jump to", "BOOYEA", filtered)
|
|
||||||
|
|
||||||
if(!thearea)
|
if(!jump_ui)
|
||||||
return
|
jump_ui = new(src)
|
||||||
if(!isobserver(usr))
|
|
||||||
to_chat(usr, span_warning("Not when you're not dead!"))
|
|
||||||
return
|
|
||||||
|
|
||||||
var/list/L = list()
|
jump_ui.ui_interact(src)
|
||||||
for(var/turf/T in get_area_turfs(thearea.type))
|
|
||||||
L+=T
|
|
||||||
|
|
||||||
if(!L || !length(L))
|
|
||||||
to_chat(usr, span_warning("No area available."))
|
|
||||||
return
|
|
||||||
|
|
||||||
usr.forceMove(pick(L))
|
|
||||||
update_parallax_contents()
|
|
||||||
|
|
||||||
/mob/dead/observer/verb/follow()
|
/mob/dead/observer/verb/follow()
|
||||||
set category = "Ghost"
|
set category = "Ghost"
|
||||||
set name = "Orbit" // "Haunt"
|
set name = "Orbit" // "Haunt"
|
||||||
set desc = "Follow and orbit a mob."
|
set desc = "Follow and orbit a mob."
|
||||||
|
|
||||||
if(!orbit_menu)
|
if(!orbit_ui)
|
||||||
orbit_menu = new(src)
|
orbit_ui = new(src)
|
||||||
|
|
||||||
orbit_menu.ui_interact(src)
|
orbit_ui.ui_interact(src)
|
||||||
|
|
||||||
// This is the ghost's follow verb with an argument
|
// This is the ghost's follow verb with an argument
|
||||||
/mob/dead/observer/proc/ManualFollow(atom/movable/target)
|
/mob/dead/observer/proc/ManualFollow(atom/movable/target)
|
||||||
@@ -508,32 +490,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
|||||||
pixel_y = 0
|
pixel_y = 0
|
||||||
animate(src, pixel_y = 2, time = 1 SECONDS, loop = -1)
|
animate(src, pixel_y = 2, time = 1 SECONDS, loop = -1)
|
||||||
|
|
||||||
/mob/dead/observer/verb/jump_to_mob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
|
|
||||||
set category = "Ghost"
|
|
||||||
set name = "Jump to Mob"
|
|
||||||
set desc = "Teleport to a mob"
|
|
||||||
|
|
||||||
if(isobserver(usr)) //Make sure they're an observer!
|
|
||||||
|
|
||||||
|
|
||||||
var/list/possible_destinations = getpois(mobs_only = TRUE) //List of possible destinations (mobs)
|
|
||||||
var/target = null //Chosen target.
|
|
||||||
|
|
||||||
target = tgui_input_list(usr, "Please, select a player!", "Jump to Mob", possible_destinations)
|
|
||||||
|
|
||||||
if (!target)//Make sure we actually have a target
|
|
||||||
return
|
|
||||||
else
|
|
||||||
var/mob/M = possible_destinations[target] //Destination mob
|
|
||||||
var/mob/A = src //Source mob
|
|
||||||
var/turf/T = get_turf(M) //Turf of the destination mob
|
|
||||||
|
|
||||||
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
|
|
||||||
A.forceMove(T)
|
|
||||||
A.update_parallax_contents()
|
|
||||||
else
|
|
||||||
to_chat(A, "This mob is not located in the game world.")
|
|
||||||
|
|
||||||
/mob/dead/observer/verb/change_view_range()
|
/mob/dead/observer/verb/change_view_range()
|
||||||
set category = "Ghost"
|
set category = "Ghost"
|
||||||
set name = "View Range"
|
set name = "View Range"
|
||||||
|
|||||||
138
tgui/packages/tgui/interfaces/Jump.js
Normal file
138
tgui/packages/tgui/interfaces/Jump.js
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import { createSearch } from 'common/string';
|
||||||
|
import { useBackend, useLocalState } from '../backend';
|
||||||
|
import { Collapsible, Button, Divider, Flex, Icon, Input, Section } from '../components';
|
||||||
|
import { Window } from '../layouts';
|
||||||
|
|
||||||
|
const PATTERN_NUMBER = / \(([0-9]+)\)$/;
|
||||||
|
|
||||||
|
const searchFor = searchText => createSearch(searchText, thing => thing.name);
|
||||||
|
|
||||||
|
const compareString = (a, b) => a < b ? -1 : a > b;
|
||||||
|
|
||||||
|
const compareNumberedText = (a, b) => {
|
||||||
|
const aName = a.name;
|
||||||
|
const bName = b.name;
|
||||||
|
|
||||||
|
// Check if aName and bName are the same except for a number at the end
|
||||||
|
// e.g. Medibot (2) and Medibot (3)
|
||||||
|
const aNumberMatch = aName.match(PATTERN_NUMBER);
|
||||||
|
const bNumberMatch = bName.match(PATTERN_NUMBER);
|
||||||
|
|
||||||
|
if (aNumberMatch
|
||||||
|
&& bNumberMatch
|
||||||
|
&& aName.replace(PATTERN_NUMBER, "") === bName.replace(PATTERN_NUMBER, "")
|
||||||
|
) {
|
||||||
|
const aNumber = parseInt(aNumberMatch[1], 10);
|
||||||
|
const bNumber = parseInt(bNumberMatch[1], 10);
|
||||||
|
|
||||||
|
return aNumber - bNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
return compareString(aName, bName);
|
||||||
|
};
|
||||||
|
|
||||||
|
const JumpButton = (props, context) => {
|
||||||
|
const { act } = useBackend(context);
|
||||||
|
const { thing } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
onClick={() => act("jump", {
|
||||||
|
ref: thing.ref,
|
||||||
|
})}>
|
||||||
|
{thing.name}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BasicSection = (props, context) => {
|
||||||
|
const { act } = useBackend(context);
|
||||||
|
const { searchText, source, title } = props;
|
||||||
|
const things = source.filter(searchFor(searchText));
|
||||||
|
things.sort(compareNumberedText);
|
||||||
|
return source.length > 0 && (
|
||||||
|
<Collapsible open title={`${title} - (${source.length})`}>
|
||||||
|
{things.map(thing => (
|
||||||
|
<JumpButton
|
||||||
|
key={thing.name}
|
||||||
|
thing={thing}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Collapsible>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Jump = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
const {
|
||||||
|
mobs,
|
||||||
|
areas,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
const [searchText, setSearchText] = useLocalState(context, "searchText", "");
|
||||||
|
|
||||||
|
const jumpMostRelevant = searchText => {
|
||||||
|
for (const source of [
|
||||||
|
mobs, areas,
|
||||||
|
]) {
|
||||||
|
const member = source
|
||||||
|
.filter(searchFor(searchText))
|
||||||
|
.sort(compareNumberedText)[0];
|
||||||
|
if (member !== undefined) {
|
||||||
|
act("jump", { ref: member.ref });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Window
|
||||||
|
title="Jump Menu"
|
||||||
|
width={350}
|
||||||
|
height={700}>
|
||||||
|
<Window.Content scrollable>
|
||||||
|
<Section>
|
||||||
|
<Flex>
|
||||||
|
<Flex.Item>
|
||||||
|
<Icon
|
||||||
|
name="search"
|
||||||
|
mr={1} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item grow={1}>
|
||||||
|
<Input
|
||||||
|
placeholder="Search..."
|
||||||
|
autoFocus
|
||||||
|
fluid
|
||||||
|
value={searchText}
|
||||||
|
onInput={(_, value) => setSearchText(value)}
|
||||||
|
onEnter={(_, value) => jumpMostRelevant(value)} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Divider vertical />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
inline
|
||||||
|
color="transparent"
|
||||||
|
tooltip="Refresh"
|
||||||
|
tooltipPosition="bottom-start"
|
||||||
|
icon="sync-alt"
|
||||||
|
onClick={() => act("refresh")} />
|
||||||
|
</Flex.Item>
|
||||||
|
</Flex>
|
||||||
|
</Section>
|
||||||
|
<BasicSection
|
||||||
|
title="Mobs"
|
||||||
|
source={mobs}
|
||||||
|
searchText={searchText}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BasicSection
|
||||||
|
title="Areas"
|
||||||
|
source={areas}
|
||||||
|
searchText={searchText}
|
||||||
|
/>
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -2690,6 +2690,7 @@
|
|||||||
#include "code\modules\mob\dead\new_player\poll.dm"
|
#include "code\modules\mob\dead\new_player\poll.dm"
|
||||||
#include "code\modules\mob\dead\new_player\preferences_setup.dm"
|
#include "code\modules\mob\dead\new_player\preferences_setup.dm"
|
||||||
#include "code\modules\mob\dead\new_player\sprite_accessories.dm"
|
#include "code\modules\mob\dead\new_player\sprite_accessories.dm"
|
||||||
|
#include "code\modules\mob\dead\observer\jumpto.dm"
|
||||||
#include "code\modules\mob\dead\observer\login.dm"
|
#include "code\modules\mob\dead\observer\login.dm"
|
||||||
#include "code\modules\mob\dead\observer\logout.dm"
|
#include "code\modules\mob\dead\observer\logout.dm"
|
||||||
#include "code\modules\mob\dead\observer\notificationprefs.dm"
|
#include "code\modules\mob\dead\observer\notificationprefs.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user