Revamps the jump to area and teleport menu (#21384)

* commit funny

* random fixes

* Update jumpto.dm
This commit is contained in:
Redmoogle
2024-02-14 18:28:50 -05:00
committed by GitHub
parent 9935d9c50c
commit 2df699272c
5 changed files with 226 additions and 56 deletions

View File

@@ -10,7 +10,7 @@
/atom/movable/screen/ghost/jump_to_mob/Click()
var/mob/dead/observer/G = usr
G.jump_to_mob()
G.dead_tele()
/atom/movable/screen/ghost/orbit
name = "Orbit"

View 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)

View File

@@ -57,7 +57,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
// Used for displaying in ghost chat, without changing the actual name
// of the mob
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
///Action to quickly unobserve someone
@@ -182,7 +183,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
updateallghostimages()
QDEL_NULL(orbit_menu)
QDEL_NULL(orbit_ui)
QDEL_NULL(jump_ui)
QDEL_NULL(spawners_menu)
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()
set category = "Ghost"
set name = "Teleport"
set desc= "Teleport to a location"
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)
set desc= "Ghostly Magic"
if(!thearea)
return
if(!isobserver(usr))
to_chat(usr, span_warning("Not when you're not dead!"))
return
if(!jump_ui)
jump_ui = new(src)
var/list/L = list()
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()
jump_ui.ui_interact(src)
/mob/dead/observer/verb/follow()
set category = "Ghost"
set name = "Orbit" // "Haunt"
set desc = "Follow and orbit a mob."
if(!orbit_menu)
orbit_menu = new(src)
if(!orbit_ui)
orbit_ui = new(src)
orbit_menu.ui_interact(src)
orbit_ui.ui_interact(src)
// This is the ghost's follow verb with an argument
/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
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()
set category = "Ghost"
set name = "View Range"

View 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>
);
};

View File

@@ -2690,6 +2690,7 @@
#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\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\logout.dm"
#include "code\modules\mob\dead\observer\notificationprefs.dm"