Files
Bubberstation/code/game/objects/items/frog_statue.dm
John Willard 41f34c2a86 Adds tgui color picker (#94313)
## About The Pull Request

Ports https://github.com/Monkestation/Monkestation2.0/pull/1231 which is
a port of https://github.com/BeeStation/BeeStation-Hornet/pull/9417
which is a port of https://github.com/omgovich/react-colorful/
Also a port of
https://github.com/effigy-se/effigy/blob/main/tgui/packages/tgui/interfaces/effigy/ColorPickerModal.tsx
for hex color presets

Admin stuff got excluded (pref-like picker, filterrific, get-variables)



https://github.com/user-attachments/assets/7069bef9-81cd-4636-bf68-cbad227ef09e


## Why It's Good For The Game

It's one of the only input areas that still doesn't use TGUI, leaving
darkmode players flashbanged every single time a color selection UI is
opened. This is also just visually great and I think a big upgrade from
byond's.

## Changelog

🆑 omgovich, itsmeow, Absolucy, JohnFulpWillard, jlsnow301, TealSeer,
lessthnthree
add: Color selection panels now use TGUI (If you have TGUI enabled in
settings).
/🆑
2025-12-21 16:18:34 -08:00

166 lines
5.4 KiB
Plaintext

#define STATUE_FILTER "statue_filter"
#define FILTER_COLOR "#34b347"
#define RECALL_DURATION 3 SECONDS
#define MINIMUM_COLOR_VALUE 20
/obj/item/frog_statue
name = "frog statue"
desc = "Are they really comfortable living in this thing?"
icon = 'icons/obj/weapons/guns/magic.dmi'
icon_state = "frog_statue"
item_flags = NOBLUDGEON
///our pet frog
var/mob/living/contained_frog
///the summon cooldown
COOLDOWN_DECLARE(summon_cooldown)
/obj/item/frog_statue/attack_self(mob/user)
. = ..()
if(.)
return TRUE
if(!COOLDOWN_FINISHED(src, summon_cooldown))
user.balloon_alert(user, "recharging!")
return TRUE
COOLDOWN_START(src, summon_cooldown, 30 SECONDS)
if(isnull(contained_frog))
user.balloon_alert(user, "no frog linked!")
return TRUE
if(contained_frog.loc == src)
release_frog(user)
return TRUE
recall_frog(user)
return TRUE
/obj/item/frog_statue/examine(mob/user)
. = ..()
if(!IS_WIZARD(user))
return
if(isnull(contained_frog))
. += span_notice("There are currently no frogs linked to this statue!")
else
. += span_notice("Using it will [(contained_frog in src) ? "release" : "recall"] the beast!")
///resummon the frog into its home
/obj/item/frog_statue/proc/recall_frog(mob/user)
playsound(src, 'sound/items/frog_statue_release.ogg', 20)
user.Beam(contained_frog, icon_state = "lichbeam", time = RECALL_DURATION)
animate(contained_frog, transform = matrix().Scale(0.3, 0.3), time = RECALL_DURATION)
addtimer(CALLBACK(contained_frog, TYPE_PROC_REF(/atom/movable, forceMove), src), RECALL_DURATION)
///release the frog to wreak havoc
/obj/item/frog_statue/proc/release_frog(mob/user)
var/list/possible_turfs = list()
for(var/turf/possible_turf in oview(2, user))
if(possible_turf.is_blocked_turf() || isopenspaceturf(possible_turf))
continue
possible_turfs += possible_turf
playsound(src, 'sound/items/frog_statue_release.ogg', 50, TRUE)
var/turf/final_turf = length(possible_turfs) ? pick(possible_turfs) : get_turf(src)
user.Beam(final_turf, icon_state = "lichbeam", time = RECALL_DURATION)
contained_frog.forceMove(final_turf)
animate(contained_frog, transform = matrix(), time = RECALL_DURATION)
REMOVE_TRAIT(contained_frog, TRAIT_AI_PAUSED, MAGIC_TRAIT)
///set this frog as our inhabitor
/obj/item/frog_statue/proc/set_new_frog(mob/living/frog)
frog.transform = frog.transform.Scale(0.3, 0.3)
contained_frog = frog
animate_filter()
RegisterSignal(frog, COMSIG_QDELETING, PROC_REF(render_obsolete))
/// we have lost our frog, let out a scream!
/obj/item/frog_statue/proc/render_obsolete(datum/source)
SIGNAL_HANDLER
contained_frog = null
playsound(src, 'sound/effects/magic/demon_dies.ogg', 50, TRUE)
UnregisterSignal(source, COMSIG_QDELETING)
/obj/item/frog_statue/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
. = ..()
if(arrived != contained_frog)
return
animate_filter()
ADD_TRAIT(contained_frog, TRAIT_AI_PAUSED, MAGIC_TRAIT)
if(contained_frog.health < contained_frog.maxHealth)
START_PROCESSING(SSobj, src)
/obj/item/frog_statue/process(seconds_per_tick)
if(isnull(contained_frog))
return
if(contained_frog.health == contained_frog.maxHealth)
STOP_PROCESSING(SSobj, src)
return
if(contained_frog.stat == DEAD)
contained_frog.revive()
contained_frog.adjust_brute_loss(-5)
/obj/item/frog_statue/proc/animate_filter(mob/living/frog)
add_filter(STATUE_FILTER, 2, list("type" = "outline", "color" = FILTER_COLOR, "size" = 1))
var/filter = get_filter(STATUE_FILTER)
animate(filter, alpha = 230, time = 2 SECONDS, loop = -1)
animate(alpha = 30, time = 0.5 SECONDS)
/obj/item/frog_statue/Exited(atom/movable/gone, direction)
. = ..()
if(gone != contained_frog)
return
clear_filters()
/obj/item/frog_contract
name = "frog contract"
desc = "Create a pact with an elder frog! This great beast will be your mount, protector, but most importantly your friend."
icon = 'icons/obj/scrolls.dmi'
icon_state = "scroll"
/obj/item/frog_contract/attack_self(mob/user)
. = ..()
if(.)
return TRUE
create_frog(user)
return TRUE
///customize our own frog and trap it into the statue
/obj/item/frog_contract/proc/create_frog(mob/user)
var/obj/item/frog_statue/statue = new(null)
var/mob/living/basic/leaper/new_frog = new(statue)
statue.set_new_frog(new_frog)
new_frog.befriend(user)
ADD_TRAIT(new_frog, TRAIT_AI_PAUSED, MAGIC_TRAIT)
select_frog_name(user, new_frog)
select_frog_color(user, new_frog)
user.put_in_hands(statue)
qdel(src)
/obj/item/frog_contract/proc/select_frog_name(mob/user, mob/new_frog)
var/frog_name = sanitize_name(tgui_input_text(user, "Choose your frog's name!", "Name pet toad", "leaper", MAX_NAME_LEN), allow_numbers = TRUE)
if(!frog_name)
to_chat(user, span_warning("Please enter a valid name."))
select_frog_name(user, new_frog)
return
new_frog.name = frog_name
/obj/item/frog_contract/proc/select_frog_color(mob/user, mob/living/basic/leaper/new_frog)
var/frog_color = tgui_color_picker(user, "Select your frog's color!" , "Pet toad color", COLOR_GREEN)
if(isnull(frog_color))
to_chat(user, span_warning("Please choose a valid color."))
select_frog_color(user, new_frog)
return
var/list/hsv_frog = rgb2hsv(frog_color)
if(hsv_frog[3] < MINIMUM_COLOR_VALUE)
to_chat(user, span_danger("This color is too dark!"))
select_frog_color(user, new_frog)
return
new_frog.set_color_overlay(frog_color)
#undef STATUE_FILTER
#undef FILTER_COLOR
#undef RECALL_DURATION
#undef MINIMUM_COLOR_VALUE