Files
Bubberstation/code/modules/mob/dead/observer/orbit.dm
SkyratBot a0a9a43562 [MIRROR] Refactors Regal Rats into Basic Mobs (more titles edition) [MDB IGNORE] (#23188)
* Refactors Regal Rats into Basic Mobs (more titles edition) (#77681)

## About The Pull Request

I literally can't focus on anything nowadays, so I just did this to
break a never-ending chain of distress. Anyways, regal rats! These
fellas are mostly player controlled, but did have _some_ AI capabilities
(mainly tied to their actions), so that was incorporated too. Everything
should work as-expected (as well as look a shitload cleaner).

Instead of doing weird and awful conditional signals being sent out, I
made the `COMSIG_REGAL_RAT_INTERACT` (not the actual name) have a return
value so we can always rely on that working whenever we have that signal
registered on something we attack. I also cleaned up pretty much every
proc related to regal rats, gave them AIs to reflect their kingly nature
(and action capabilities (as well as move the action to
`mob_cooldown`)).

Since I thought they needed it, Regal Rats now get a special moniker!
This is stuff like "the Big Cheese" and what-not, like actual regents in
history. That's nice.
## Why It's Good For The Game

Two more off the list. Much better code to read. Way smarter rats with
spawning their army as part of a retaliatory assault (war). More sovl
with better regal rat names. The list goes on.
## Changelog
🆑
refactor: Regal Rats have been refactored into basic mobs. They should
be a bit smarter and retain their docility (until attacked, in which
case you should prepare to get rekt by summoned rats), and properly flee
when they can instead of just sit there as you beat them to death. The
framework for them interacting with stuff (i.e. opening doors while
slobbering on food) is a bit more unified too, now. They also have
cooler names too!
/🆑

FYI: Beyond a few code touchups, I haven't touched the actions at all. I
do not believe myself to be enthusiastic about fixing anything involving
the actions code as of this moment so that this PR is more overbloated
unless it's unbelievably stupid or easy to fix.

* Refactors Regal Rats into Basic Mobs (more titles edition)

---------

Co-authored-by: san7890 <the@san7890.com>
2023-08-18 19:28:25 -04:00

184 lines
5.7 KiB
Plaintext

GLOBAL_DATUM_INIT(orbit_menu, /datum/orbit_menu, new)
/datum/orbit_menu
///mobs worth orbiting. Because spaghetti, all mobs have the point of interest, but only some are allowed to actually show up.
///this obviously should be changed in the future, so we only add mobs as POI if they actually are interesting, and we don't use
///a typecache.
var/static/list/mob_allowed_typecache
/datum/orbit_menu/ui_state(mob/user)
return GLOB.observer_state
/datum/orbit_menu/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "Orbit")
ui.open()
/datum/orbit_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
switch(action)
if("orbit")
var/ref = params["ref"]
var/auto_observe = params["auto_observe"]
var/atom/poi = SSpoints_of_interest.get_poi_atom_by_ref(ref)
if((ismob(poi) && !SSpoints_of_interest.is_valid_poi(poi, CALLBACK(src, PROC_REF(validate_mob_poi)))) \
|| !SSpoints_of_interest.is_valid_poi(poi)
)
to_chat(usr, span_notice("That point of interest is no longer valid."))
return TRUE
var/mob/dead/observer/user = usr
user.ManualFollow(poi)
user.reset_perspective(null)
if (auto_observe)
user.do_observe(poi)
return TRUE
if ("refresh")
update_static_data(usr, ui)
return TRUE
/datum/orbit_menu/ui_static_data(mob/user)
var/list/new_mob_pois = SSpoints_of_interest.get_mob_pois(CALLBACK(src, PROC_REF(validate_mob_poi)), append_dead_role = FALSE)
var/list/new_other_pois = SSpoints_of_interest.get_other_pois()
var/list/alive = list()
var/list/antagonists = list()
var/list/deadchat_controlled = list()
var/list/dead = list()
var/list/ghosts = list()
var/list/misc = list()
var/list/npcs = list()
for(var/name in new_mob_pois)
var/list/serialized = list()
var/mob/mob_poi = new_mob_pois[name]
var/poi_ref = REF(mob_poi)
var/number_of_orbiters = length(mob_poi.get_all_orbiters())
serialized["ref"] = poi_ref
serialized["full_name"] = name
if(number_of_orbiters)
serialized["orbiters"] = number_of_orbiters
if(mob_poi.GetComponent(/datum/component/deadchat_control))
deadchat_controlled += list(serialized)
if(isobserver(mob_poi))
ghosts += list(serialized)
continue
if(mob_poi.stat == DEAD)
dead += list(serialized)
continue
if(isnull(mob_poi.mind))
npcs += list(serialized)
continue
var/datum/mind/mind = mob_poi.mind
var/was_antagonist = FALSE
serialized["name"] = mob_poi.real_name
if(isliving(mob_poi)) // handles edge cases like blob
var/mob/living/player = mob_poi
serialized["health"] = FLOOR((player.health / player.maxHealth * 100), 1)
if(issilicon(player))
serialized["job"] = player.job
else
var/obj/item/card/id/id_card = player.get_idcard(hand_first = FALSE)
serialized["job"] = id_card?.get_trim_assignment()
for(var/datum/antagonist/antag_datum as anything in mind.antag_datums)
if (antag_datum.show_to_ghosts)
was_antagonist = TRUE
serialized["antag"] = antag_datum.name
serialized["antag_group"] = antag_datum.antagpanel_category
antagonists += list(serialized)
break
if(!was_antagonist)
alive += list(serialized)
for(var/name in new_other_pois)
var/atom/atom_poi = new_other_pois[name]
// Deadchat Controlled objects are orbitable
if(atom_poi.GetComponent(/datum/component/deadchat_control))
var/number_of_orbiters = length(atom_poi.get_all_orbiters())
deadchat_controlled += list(list(
"ref" = REF(atom_poi),
"full_name" = name,
"orbiters" = number_of_orbiters,
))
continue
misc += list(list(
"ref" = REF(atom_poi),
"full_name" = name,
))
// Display the supermatter crystal integrity
if(istype(atom_poi, /obj/machinery/power/supermatter_crystal))
var/obj/machinery/power/supermatter_crystal/crystal = atom_poi
misc[length(misc)]["extra"] = "Integrity: [round(crystal.get_integrity_percent())]%"
continue
// Display the nuke timer
if(istype(atom_poi, /obj/machinery/nuclearbomb))
var/obj/machinery/nuclearbomb/bomb = atom_poi
if(bomb.timing)
misc[length(misc)]["extra"] = "Timer: [bomb.countdown?.displayed_text]s"
continue
// Display the holder if its a nuke disk
if(istype(atom_poi, /obj/item/disk/nuclear))
var/obj/item/disk/nuclear/disk = atom_poi
var/mob/holder = disk.pulledby || get(disk, /mob)
misc[length(misc)]["extra"] = "Location: [holder?.real_name || "Unsecured"]"
continue
return list(
"alive" = alive,
"antagonists" = antagonists,
"deadchat_controlled" = deadchat_controlled,
"dead" = dead,
"ghosts" = ghosts,
"misc" = misc,
"npcs" = npcs,
)
/// Shows the UI to the specified user.
/datum/orbit_menu/proc/show(mob/user)
ui_interact(user)
/**
* Helper POI validation function passed as a callback to various SSpoints_of_interest procs.
*
* Provides extended validation above and beyond standard, limiting mob POIs without minds or ckeys
* unless they're mobs, camera mobs or megafauna. Also allows exceptions for mobs that are deadchat controlled.
*
* If they satisfy that requirement, falls back to default validation for the POI.
*/
/datum/orbit_menu/proc/validate_mob_poi(datum/point_of_interest/mob_poi/potential_poi)
var/mob/potential_mob_poi = potential_poi.target
if(!potential_mob_poi.mind && !potential_mob_poi.ckey)
if(!mob_allowed_typecache)
mob_allowed_typecache = typecacheof(list(
/mob/camera,
/mob/living/basic/regal_rat,
/mob/living/simple_animal/bot,
/mob/living/simple_animal/hostile/megafauna,
))
if(!is_type_in_typecache(potential_mob_poi, mob_allowed_typecache) && !potential_mob_poi.GetComponent(/datum/component/deadchat_control))
return FALSE
return potential_poi.validate()