Files
Bubberstation/code/datums/elements/beauty.dm
T
GhomandGitHub 7663b39cc8 Refactoring aquariums into components (feat: portable fish tanks) (#87866)
## About The Pull Request
I've been meaning to do this for some time. I need this for
portable/handheld aquariums/fishtanks to be possible. I'll sprite and
code them before I call this PR ready, however suggestions and code
reviews are welcome in the meantime.

Being a pretty heavy refactor, some things might break (we have more
than a few unit tests so perhaps not) while others, coincidentally,
might be fixed without me knowing. Anyway I'm sure this PR fixes
aquarium beauty, which wasn't really working to begin with because the
code was so fucking bad. Nothing really worth of a CL entry tho.


TODO:
- [x] handheld aquariums, craftable with a kit and little plastic or
buyable from the fun vendor ig.
- [x] an aquarium upgrade for handheld aquariums to bypass possible
restrictions.
- [x] update the beauty element to consider items, which shouldn't
contribute to the area beauty when held or otherwise not on a turf.

## Why It's Good For The Game
This should make handheld aquariums possible.

## Changelog

🆑
refactor: refactored aquariums heavily. Please report any fishy bug.
add: Added portable/handheld fish tanks to the game. They can be crafted
with an aquarium kit and 5 sheets of plastic. While portable, they
cannot store fish that are too big or if there're too many already. This
restriction can be removed by using the new "bluespace fish tank kit"
techweb item.
map: Replaced the lawyer's stationary pet aquarium with a fish tank, so
you can carry McGill around.
balance: Reduced the iron cost of stationary aquariums a little.
/🆑
2024-11-21 09:45:49 +13:00

96 lines
3.6 KiB
Plaintext

/**
* Beauty element. It makes the indoor area the parent is in prettier or uglier depending on the beauty var value.
* Clean and well decorated areas lead to positive moodlets for passerbies;
* Shabbier, dirtier ones lead to negative moodlets EXCLUSIVE to characters with the snob quirk.
*/
/datum/element/beauty
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH_ON_HOST_DESTROY
argument_hash_start_idx = 2
var/beauty = 0
/**
* Assoc list of atoms as keys and number of time the same element instance has been attached to them as assoc value.
* So things don't get odd with same-valued yet dissimilar beauty modifiers being added to the same atom.
*/
var/beauty_counter = list()
/datum/element/beauty/Attach(datum/target, beauty)
. = ..()
if(!isatom(target) || isarea(target))
return ELEMENT_INCOMPATIBLE
src.beauty = beauty
var/area/current_area = get_area(target)
var/beauty_active = TRUE
if(ismovable(target))
var/atom/movable/mov_target = target
var/is_item = isitem(mov_target)
beauty_active = !is_item || isturf(mov_target.loc)
if(!beauty_counter[target])
if(is_item)
RegisterSignal(mov_target, COMSIG_MOVABLE_MOVED, PROC_REF(on_item_moved))
if(beauty_active)
mov_target.become_area_sensitive(BEAUTY_ELEMENT_TRAIT)
RegisterSignal(mov_target, COMSIG_ENTER_AREA, PROC_REF(enter_area))
RegisterSignal(mov_target, COMSIG_EXIT_AREA, PROC_REF(exit_area))
beauty_counter[target]++
if(current_area && !current_area.outdoors && beauty_active)
current_area.totalbeauty += beauty
current_area.update_beauty()
/datum/element/beauty/proc/enter_area(datum/source, area/new_area)
SIGNAL_HANDLER
if(new_area.outdoors || HAS_TRAIT(source, TRAIT_BEAUTY_APPLIED))
return
new_area.totalbeauty += beauty * beauty_counter[source]
new_area.update_beauty()
ADD_TRAIT(source, TRAIT_BEAUTY_APPLIED, INNATE_TRAIT)
/datum/element/beauty/proc/exit_area(datum/source, area/old_area)
SIGNAL_HANDLER
if(old_area.outdoors || !HAS_TRAIT(source, TRAIT_BEAUTY_APPLIED))
return
old_area.totalbeauty -= beauty * beauty_counter[source]
old_area.update_beauty()
REMOVE_TRAIT(source, TRAIT_BEAUTY_APPLIED, INNATE_TRAIT)
///Items only contribute to beauty while not inside other objects or mobs (e.g on the floor, on a table etc.).
/datum/element/beauty/proc/on_item_moved(obj/item/source, atom/old_loc, direction, forced)
SIGNAL_HANDLER
var/is_old_turf = isturf(old_loc)
if(!is_old_turf && isturf(source.loc))
source.become_area_sensitive(BEAUTY_ELEMENT_TRAIT)
RegisterSignal(source, COMSIG_ENTER_AREA, PROC_REF(enter_area), TRUE)
RegisterSignal(source, COMSIG_EXIT_AREA, PROC_REF(exit_area), TRUE)
enter_area(source, get_area(source.loc))
else if(is_old_turf && !isturf(source.loc))
source.lose_area_sensitivity(BEAUTY_ELEMENT_TRAIT)
UnregisterSignal(source, list(COMSIG_ENTER_AREA, COMSIG_EXIT_AREA))
exit_area(source, get_area(old_loc))
/datum/element/beauty/Detach(atom/source)
if(!beauty_counter[source])
return ..()
var/area/current_area = (!isitem(source) || isturf(source.loc)) ? get_area(source) : null
if(!QDELETED(source))//lower the 'counter' down by one, update the area, and call parent if it's reached zero.
beauty_counter[source]--
if(current_area && !current_area.outdoors)
current_area.totalbeauty -= beauty
current_area.update_beauty()
if(beauty_counter[source])
return
else if(current_area)
exit_area(source, current_area)
UnregisterSignal(source, list(COMSIG_ENTER_AREA, COMSIG_EXIT_AREA, COMSIG_MOVABLE_MOVED))
beauty_counter -= source
var/atom/movable/movable_source = source
if(istype(movable_source))
movable_source.lose_area_sensitivity(BEAUTY_ELEMENT_TRAIT)