Files
Bubberstation/code/__HELPERS/chat.dm
san7890 3415828c6b Refactors Revenants into Basic Mobs (#78782)
## About The Pull Request

I felt bad about taking all the "easy" ones, so let's change it up with
a decently difficult one. Revenants are now basic mobs! This alone
doesn't change much of anything because it pretty much overrode much of
simple_animal code. However we do a few new things.

* Multiple code improvements! No more weird proc names that aren't
`snake_case`, cleaner variable names, more dmdoccing, etc.
* Files are now reorganized, Rather than a 800-line dogshit monofile,
we're all nice now
* Multiple logic improvements, like early returns to make stuff more
readable and the like. many `isnull()` yes
* Instead of abusing key ownership logic, we use `mind.transfer_to()`
instead for much cleaner behavior when we need to change stuff
* Instead of iterating over the entire list of mobs to find dead mobs,
we use a new `revenant_relay()` system that automatically handles
broadcasting revenant messages to all observers and fellow revenants
(like `blob_talk()`)
* Instead of having a weird invisible "corpse", we move the revenant
inside the actual ectoplasm when they die. This drastically simplifies a
lot of wacky code that was completely useless since we still had the mob
to work with, but now it's a lot cleaner when it comes down to it.
* Some more hooks into stuff like `Life()` that might be useful for
other people in the same way this is.
* Less <span> crap, more macros, wahoo
* Uses an `examine_block()` for when we relay instructions to new
revenants. also cache those instructions to save time in the long run
* Revenants being stunned, inhibited, and revealed are now managed by
status effects rather than being chicanery on `Life()`
* Everything should now just in general be a lot nicer to work with.
This list is not exhaustive but a lot of the junk 7-year-old code has
been gutted and replaced with the modern standards.

There are stuff that I explicitly didn't touch and will not be touching
in this PR as it's already rather large.
* Revenant actions. I touched some proc names but I didn't alter the key
ways they work.
* Revenant movement. That's another can of worms.
* Revenant event code. I just made it use the transfer to system to make
a closed loop and that's about it.
* Revenant AI. They don't have any, it's an event/admin spawn. I'm not
adding AI here.
## Why It's Good For The Game

Revenants are more extensible now rather than being a real big
clusterfuck of bullshit, should be much easier to tweak stuff here and
there or logically follow how the code for this fella should go. The
number of weird revenant bugs should go down since we do stuff more
simply- but there could be some sleeper bugs that can bite us.
## Changelog
🆑
refactor: Revenants, the mob that's split between planes of Life and
Death, have been refactored into a basic mob. While this alone shouldn't
touch behavior, a lot of the backend code has been gutted and refactored
to try and furnish a better antagonist experience. This might mean that
some weird stuff can come up and around, report something if it's
utterly broken.
code: In order to better facilitate some code, you do not ghost outside
of a revenant on death, you simply get transferred into the ectoplasm.
You should still be able to speak with your ghost friends on how hard
you got wrecked or if you'll be able to resurrect though.
code: The timing on revenant stuff such as being revealed, stunned, and
inhibited (by holy weapons) should be tweaked a bit to allow better
management. This should mean that getting unstunned and such should be a
bit more precise now.
qol: Revenant instructions are now relayed in a neat little examine
block.
/🆑
2023-10-09 23:15:20 +01:00

100 lines
3.4 KiB
Plaintext

/*
Here's how to use the TGS chat system with configs
send2adminchat is a simple function that broadcasts to all admin channels that are designated in TGS
send2chat is a bit verbose but can be very specific
In TGS3 it will always be sent to all connected designated game chats.
In TGS4+ they use the new tagging system
The second parameter is a string, this string should be read from a config.
What this does is dictate which TGS channels can be sent to.
For example if you have the following channels in tgs4 set up
- Channel 1, Tag: asdf
- Channel 2, Tag: bombay,asdf
- Channel 3, Tag: Hello my name is asdf
- Channel 4, No Tag
- Channel 5, Tag: butts
and you make the call:
send2chat(new /datum/tgs_message_content("I sniff butts"), CONFIG_GET(string/where_to_send_sniff_butts))
and the config option is set like:
WHERE_TO_SEND_SNIFF_BUTTS asdf
It will be sent to channels 1 and 2
Alternatively if you set the config option to just:
WHERE_TO_SEND_SNIFF_BUTTS
it will be sent to all connected chats.
*/
/**
* Asynchronously sends a message to TGS chat channels.
*
* message - The [/datum/tgs_message_content] to send.
* channel_tag - Required. If "", the message with be sent to all connected (Game-type for TGS3) channels. Otherwise, it will be sent to TGS4 channels with that tag (Delimited by ','s).
* admin_only - Determines if this communication can only be sent to admin only channels.
*/
/proc/send2chat(datum/tgs_message_content/message, channel_tag, admin_only = FALSE)
set waitfor = FALSE
if(channel_tag == null || !world.TgsAvailable())
return
var/datum/tgs_version/version = world.TgsVersion()
if(channel_tag == "" || version.suite == 3)
world.TgsTargetedChatBroadcast(message, admin_only)
return
var/list/channels_to_use = list()
for(var/I in world.TgsChatChannelInfo())
var/datum/tgs_chat_channel/channel = I
var/list/applicable_tags = splittext(channel.custom_tag, ",")
if((!admin_only || channel.is_admin_channel) && (channel_tag in applicable_tags))
channels_to_use += channel
if(channels_to_use.len)
world.TgsChatBroadcast(message, channels_to_use)
/**
* Asynchronously sends a message to TGS admin chat channels.
*
* category - The category of the mssage.
* message - The message to send.
*/
/proc/send2adminchat(category, message, embed_links = FALSE)
set waitfor = FALSE
category = replacetext(replacetext(category, "\proper", ""), "\improper", "")
message = replacetext(replacetext(message, "\proper", ""), "\improper", "")
if(!embed_links)
message = GLOB.has_discord_embeddable_links.Replace(replacetext(message, "`", ""), " ```$1``` ")
world.TgsTargetedChatBroadcast(new /datum/tgs_message_content("[category] | [message]"), TRUE)
/// Handles text formatting for item use hints in examine text
#define EXAMINE_HINT(text) ("<b>" + text + "</b>")
/// Sends a message to all dead and observing players, if a source is provided a follow link will be attached.
/proc/send_to_observers(message, source)
var/list/all_observers = GLOB.dead_player_list + GLOB.current_observers_list
for(var/mob/observer as anything in all_observers)
if (isnull(source))
to_chat(observer, "[message]")
continue
var/link = FOLLOW_LINK(observer, source)
to_chat(observer, "[link] [message]")
/// Sends a message to everyone within the list, as well as all observers.
/proc/relay_to_list_and_observers(message, list/mob_list, source)
for(var/mob/creature as anything in mob_list)
to_chat(creature, message)
send_to_observers(message, source)