mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 03:02:38 +00:00
175 lines
6.1 KiB
Plaintext
175 lines
6.1 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
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE //Prioritize the old comp over, which may have callbacks and stuff specific to the mob.
|
|
///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))
|
|
|
|
/datum/component/happiness/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_MOB_ATE))
|
|
happiness_callback = null
|
|
|
|
/datum/component/happiness/proc/on_eat(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
change_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 NONE
|
|
|
|
COOLDOWN_START(src, groom_cooldown, GROOM_COOLDOWN)
|
|
change_happiness_level(on_groom_change)
|
|
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
|
|
|
|
/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
|
|
change_happiness_level(on_petted_change)
|
|
COOLDOWN_START(src, pet_cooldown, PET_COOLDOWN)
|
|
|
|
|
|
/datum/component/happiness/proc/change_happiness_level(amount)
|
|
var/old_happiness = happiness_level
|
|
happiness_level = clamp(happiness_level + amount, 0, maximum_happiness)
|
|
var/happiness_percentage = happiness_level / maximum_happiness
|
|
var/old_percentage = old_happiness / maximum_happiness
|
|
|
|
var/old_threshold = 0
|
|
var/new_threshold = 0
|
|
for(var/check_percentage in callback_percentages)
|
|
if (check_percentage <= old_percentage)
|
|
old_threshold = check_percentage
|
|
if (check_percentage <= happiness_percentage)
|
|
new_threshold = check_percentage
|
|
|
|
if (old_threshold != new_threshold)
|
|
SEND_SIGNAL(parent, COMSIG_MOB_HAPPINESS_CHANGE, happiness_percentage)
|
|
happiness_callback?.Invoke(happiness_percentage)
|
|
|
|
var/mob/living/living_parent = parent
|
|
living_parent.ai_controller?.set_blackboard_key(blackboard_key, happiness_percentage)
|
|
|
|
if(!HAS_TRAIT(parent, TRAIT_MOB_HIDE_HAPPINESS) && amount > 0)
|
|
new /obj/effect/temp_visual/heart(living_parent.loc)
|
|
living_parent.spin(spintime = 2 SECONDS, speed = 1)
|
|
|
|
if (happiness_level > 0)
|
|
START_PROCESSING(SSprocessing, src)
|
|
|
|
/datum/component/happiness/proc/view_happiness(mob/living/source, mob/living/clicker)
|
|
if(HAS_TRAIT(source, TRAIT_MOB_HIDE_HAPPINESS) || !istype(clicker) || !COOLDOWN_FINISHED(src, happiness_inspect) || !source.IsReachableBy(clicker))
|
|
return
|
|
var/y_position = source.get_cached_height() + 1
|
|
var/obj/effect/overlay/happiness_overlay/hearts = new
|
|
hearts.pixel_w -= source.base_pixel_x + source.base_pixel_w
|
|
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()
|
|
if(happiness_level <= 0)
|
|
return PROCESS_KILL
|
|
var/mob/living/living_parent = parent
|
|
var/modifier = living_parent.ai_controller?.blackboard[BB_BASIC_DEPRESSED] ? 2 : 1
|
|
change_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
|