Files
Bubberstation/code/datums/components/happiness.dm
T
ProfakosandGitHub 0cfef4fae1 Dead raptors no longer get happy when petted or groomed (#84959)
## About The Pull Request

I have noticed that when I petted a raptor corpse I have found, it
started spinning and hearts appeared above it. Apparently, the same
happens if you wash them. This PR makes sure that dead raptors stop
spinning in their graves.

I decided to not to disable the happiness component's processing on
death, as the idea that the raptor's ghost looms over you, patiently
waiting to be revived is funny, and also encourages their revival to be
a priority.

This PR also removes a duplicate animal petting proc that has not
actually been hooked into anything.

## Why It's Good For The Game

Dead animals should consistently act as dead animals.

## Changelog

🆑
fix: Fixes dead raptors getting excited when petted or groomed
/🆑
2024-07-15 19:47:05 +01:00

162 lines
5.7 KiB
Plaintext

#define INSPECT_TIMER 10 SECONDS
#define PET_COOLDOWN 10 SECONDS
#define GROOM_COOLDOWN 30 SECONDS
/*
* A component that allows mobs to have happiness levels
*/
/datum/component/happiness
///our current happiness level
var/happiness_level
///our maximum happiness level
var/maximum_happiness
///happiness AI blackboard key
var/blackboard_key
///happiness when we get groomed
var/on_groom_change
///happiness when we get petted
var/on_petted_change
///happiness when we eat
var/on_eat_change
///percentages we should be calling back on
var/list/callback_percentages
///callback when our happiness changes
var/datum/callback/happiness_callback
///how long till we can inspect happiness again?
COOLDOWN_DECLARE(happiness_inspect)
///how long till we can pet it again?
COOLDOWN_DECLARE(pet_cooldown)
///how long till we can groom it again
COOLDOWN_DECLARE(groom_cooldown)
/datum/component/happiness/Initialize(maximum_happiness = 400, blackboard_key = BB_BASIC_HAPPINESS, on_groom_change = 200, on_eat_change = 300, on_petted_change = 30, callback_percentages = list(0, 25, 50, 75, 100), happiness_callback)
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
src.maximum_happiness = maximum_happiness
src.blackboard_key = blackboard_key
src.on_groom_change = on_groom_change
src.on_petted_change = on_petted_change
src.on_eat_change = on_eat_change
src.happiness_callback = happiness_callback
src.callback_percentages = callback_percentages
ADD_TRAIT(parent, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type)
/datum/component/happiness/RegisterWithParent()
if(on_petted_change)
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(on_petted))
if(on_groom_change)
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_clean))
if(on_eat_change)
RegisterSignal(parent, COMSIG_MOB_ATE, PROC_REF(on_eat))
RegisterSignal(parent, COMSIG_SHIFT_CLICKED_ON, PROC_REF(view_happiness))
ADD_TRAIT(parent, TRAIT_MOB_RELAY_HAPPINESS, REF(src))
/datum/component/happiness/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_MOB_ATE))
REMOVE_TRAIT(parent, TRAIT_MOB_RELAY_HAPPINESS, REF(src))
happiness_callback = null
/datum/component/happiness/proc/on_eat(datum/source)
SIGNAL_HANDLER
increase_happiness_level(on_eat_change)
/datum/component/happiness/proc/on_clean(mob/living/source)
SIGNAL_HANDLER
if(!COOLDOWN_FINISHED(src, groom_cooldown))
return
var/mob/living/living_parent = parent
if (living_parent.stat != CONSCIOUS)
return
COOLDOWN_START(src, groom_cooldown, GROOM_COOLDOWN)
increase_happiness_level(on_groom_change)
/datum/component/happiness/proc/on_petted(datum/source, mob/living/petter, list/modifiers)
SIGNAL_HANDLER
if(!LAZYACCESS(modifiers, LEFT_CLICK) || petter.combat_mode)
return
var/mob/living/living_parent = parent
if (living_parent.stat != CONSCIOUS)
return
pet_animal()
/datum/component/happiness/proc/pet_animal()
if(!COOLDOWN_FINISHED(src, pet_cooldown))
return
increase_happiness_level(on_petted_change)
COOLDOWN_START(src, pet_cooldown, PET_COOLDOWN)
/datum/component/happiness/proc/increase_happiness_level(amount)
happiness_level = min(happiness_level + amount, maximum_happiness)
var/mob/living/living_parent = parent
new /obj/effect/temp_visual/heart(living_parent.loc)
living_parent.spin(spintime = 2 SECONDS, speed = 1)
START_PROCESSING(SSprocessing, src)
/datum/component/happiness/proc/view_happiness(mob/living/source, mob/living/clicker)
if(!istype(clicker) || !COOLDOWN_FINISHED(src, happiness_inspect) || !clicker.CanReach(source))
return
var/list/offset_to_add = get_icon_dimensions(source.icon)
var/y_position = offset_to_add["height"] + 1
var/obj/effect/overlay/happiness_overlay/hearts = new
hearts.pixel_y = y_position
hearts.set_hearts(happiness_level/maximum_happiness)
source.vis_contents += hearts
COOLDOWN_START(src, happiness_inspect, INSPECT_TIMER)
/datum/component/happiness/process()
var/mob/living/living_parent = parent
var/happiness_percentage = happiness_level/maximum_happiness
living_parent.ai_controller?.set_blackboard_key(blackboard_key, happiness_percentage)
var/check_percentage_in_list = round(happiness_percentage * 100, 1)
if(check_percentage_in_list in callback_percentages)
SEND_SIGNAL(parent, COMSIG_MOB_HAPPINESS_CHANGE, happiness_percentage)
happiness_callback?.Invoke(happiness_percentage)
if(happiness_level <= 0)
return PROCESS_KILL
var/modifier = living_parent.ai_controller?.blackboard[BB_BASIC_DEPRESSED] ? 2 : 1
happiness_level = max(0, happiness_level - modifier)
/obj/effect/overlay/happiness_overlay
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = TRUE
vis_flags = VIS_INHERIT_DIR | VIS_INHERIT_PLANE
layer = ABOVE_HUD_PLANE
///how many hearts should we display
VAR_PRIVATE/hearts_percentage
///icon of our heart
var/heart_icon = 'icons/effects/effects.dmi'
/obj/effect/overlay/happiness_overlay/Initialize(mapload)
. = ..()
QDEL_IN(src, 5 SECONDS)
/obj/effect/overlay/happiness_overlay/proc/set_hearts(happiness_percentage)
hearts_percentage = happiness_percentage
update_appearance(UPDATE_OVERLAYS)
/obj/effect/overlay/happiness_overlay/update_overlays()
. = ..()
var/static/list/heart_positions = list(-13, -5, 3, 11)
var/display_amount = round(length(heart_positions) * hearts_percentage, 1)
for(var/index in 1 to length(heart_positions))
var/heart_icon_state = display_amount >= index ? "full_heart" : "empty_heart"
var/mutable_appearance/display_icon = mutable_appearance(icon = heart_icon, icon_state = heart_icon_state, layer = ABOVE_HUD_PLANE)
display_icon.pixel_x = heart_positions[index]
. += display_icon
#undef INSPECT_TIMER
#undef PET_COOLDOWN
#undef GROOM_COOLDOWN