Bring your pet to work day! (#86879)
## About The Pull Request Adds a new neutral station trait where people are able to bring their personal pets to show off to the rest of the crew (or to donate to the chef). Before joining, players will be able to customize their pets https://github.com/user-attachments/assets/5a5cda18-e551-4f87-b649-67a6940ffc6a u can set their name, gender, pet carrier color, and teach them give them a unique dance sequence trick. if players dont wish to opt in, they also have the choice not to ## Why It's Good For The Game adds a new station trait which people can RP around, whether its by competitively comparing pets, or resolving conflicts around pets being killed/kidnapped. Ive also GAGsified pet carriers, so people can now have the option to recolor those too ## Changelog 🆑 add: adds a new station trait, "bring your pet to work" day /🆑
@@ -33,6 +33,9 @@
|
||||
///keeps track of how many gutlunches are born
|
||||
GLOBAL_VAR_INIT(gutlunch_count, 0)
|
||||
|
||||
///Pet customization settings saved for every client
|
||||
GLOBAL_LIST_EMPTY(customized_pets)
|
||||
|
||||
//raptor defines
|
||||
|
||||
#define RAPTOR_RED "Red"
|
||||
|
||||
@@ -229,6 +229,21 @@
|
||||
icon_file = 'icons/obj/toys/plushes.dmi'
|
||||
json_config = 'code/datums/greyscale/json_configs/plushie_carp.json'
|
||||
|
||||
/datum/greyscale_config/pet_carrier
|
||||
name = "Pet Carrier"
|
||||
icon_file = 'icons/obj/pet_carrier.dmi'
|
||||
json_config = 'code/datums/greyscale/json_configs/pet_carrier.json'
|
||||
|
||||
/datum/greyscale_config/pet_carrier_inhands_left
|
||||
name = "Pet Carrier Left"
|
||||
icon_file = 'icons/mob/inhands/items_lefthand.dmi'
|
||||
json_config = 'code/datums/greyscale/json_configs/pet_carrier_inhands.json'
|
||||
|
||||
/datum/greyscale_config/pet_carrier_inhands_right
|
||||
name = "Pet Carrier Right"
|
||||
icon_file = 'icons/mob/inhands/items_righthand.dmi'
|
||||
json_config = 'code/datums/greyscale/json_configs/pet_carrier_inhands.json'
|
||||
|
||||
/datum/greyscale_config/plush_lizard
|
||||
name = "Plushie Lizard"
|
||||
icon_file = 'icons/obj/toys/plushes.dmi'
|
||||
|
||||
@@ -14,3 +14,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"pet_carrier_open": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_open",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_gags",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
}
|
||||
],
|
||||
"pet_carrier_closed_unlocked": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_unlocked",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_closed",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_gags",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
}
|
||||
],
|
||||
"pet_carrier_closed_locked": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_locked",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_closed",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_gags",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
}
|
||||
],
|
||||
"pet_carrier_occupied_unlocked": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_unlocked",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_occupied",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_gags",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
}
|
||||
],
|
||||
"pet_carrier_occupied_locked": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_locked",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_occupied",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_gags",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"pet_carrier": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier",
|
||||
"blend_mode": "overlay"
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "pet_carrier_gags",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -544,3 +544,47 @@
|
||||
dynamic_category = RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS
|
||||
threat_reduction = 15
|
||||
dynamic_threat_id = "Background Checks"
|
||||
|
||||
|
||||
/datum/station_trait/pet_day
|
||||
name = "Bring Your Pet To Work Day"
|
||||
trait_type = STATION_TRAIT_NEUTRAL
|
||||
show_in_report = FALSE
|
||||
weight = 2
|
||||
sign_up_button = TRUE
|
||||
|
||||
/datum/station_trait/pet_day/New()
|
||||
. = ..()
|
||||
RegisterSignal(SSdcs, COMSIG_GLOB_JOB_AFTER_SPAWN, PROC_REF(on_job_after_spawn))
|
||||
|
||||
/datum/station_trait/pet_day/setup_lobby_button(atom/movable/screen/lobby/button/sign_up/lobby_button)
|
||||
lobby_button.desc = "Want to bring your innocent pet to a giant metal deathtrap? Click here to customize it!"
|
||||
RegisterSignal(lobby_button, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_lobby_button_update_overlays))
|
||||
return ..()
|
||||
|
||||
/datum/station_trait/pet_day/can_display_lobby_button(client/player)
|
||||
return sign_up_button
|
||||
|
||||
/datum/station_trait/pet_day/on_round_start()
|
||||
return
|
||||
|
||||
/datum/station_trait/pet_day/on_lobby_button_click(atom/movable/screen/lobby/button/sign_up/lobby_button, updates)
|
||||
var/mob/our_player = lobby_button.get_mob()
|
||||
var/client/player_client = our_player.client
|
||||
if(isnull(player_client))
|
||||
return
|
||||
var/datum/pet_customization/customization = GLOB.customized_pets[REF(player_client)]
|
||||
if(isnull(customization))
|
||||
customization = new(player_client)
|
||||
INVOKE_ASYNC(customization, TYPE_PROC_REF(/datum, ui_interact), our_player)
|
||||
|
||||
/datum/station_trait/pet_day/proc/on_job_after_spawn(datum/source, datum/job/job, mob/living/spawned, client/player_client)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/datum/pet_customization/customization = GLOB.customized_pets[REF(player_client)]
|
||||
if(isnull(customization))
|
||||
return
|
||||
INVOKE_ASYNC(customization, TYPE_PROC_REF(/datum/pet_customization, create_pet), spawned, player_client)
|
||||
|
||||
/datum/station_trait/pet_day/proc/on_lobby_button_update_overlays(atom/movable/screen/lobby/button/sign_up/lobby_button, list/overlays)
|
||||
overlays += "select_pet"
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
inhand_icon_state = "pet_carrier"
|
||||
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
|
||||
greyscale_config = /datum/greyscale_config/pet_carrier
|
||||
greyscale_config_inhand_left = /datum/greyscale_config/pet_carrier_inhands_left
|
||||
greyscale_config_inhand_right = /datum/greyscale_config/pet_carrier_inhands_right
|
||||
greyscale_colors = COLOR_BLUE
|
||||
force = 5
|
||||
attack_verb_continuous = list("bashes", "carries")
|
||||
attack_verb_simple = list("bash", "carry")
|
||||
@@ -19,7 +23,6 @@
|
||||
throw_range = 3
|
||||
custom_materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT * 7.5, /datum/material/glass = SMALL_MATERIAL_AMOUNT)
|
||||
interaction_flags_mouse_drop = NEED_DEXTERITY
|
||||
|
||||
var/open = TRUE
|
||||
var/locked = FALSE
|
||||
var/list/occupants = list()
|
||||
@@ -147,14 +150,9 @@
|
||||
if(open)
|
||||
icon_state = initial(icon_state)
|
||||
return ..()
|
||||
icon_state = "[base_icon_state]_[!occupants.len ? "closed" : "occupied"]"
|
||||
icon_state = "[base_icon_state]_[!occupants.len ? "closed" : "occupied"]_[locked ? "locked" : "unlocked"]"
|
||||
return ..()
|
||||
|
||||
/obj/item/pet_carrier/update_overlays()
|
||||
. = ..()
|
||||
if(!open)
|
||||
. += "[base_icon_state]_[locked ? "" : "un"]locked"
|
||||
|
||||
/obj/item/pet_carrier/mouse_drop_dragged(atom/over_atom, mob/user, src_location, over_location, params)
|
||||
if(isopenturf(over_atom) && open && occupants.len)
|
||||
user.visible_message(span_notice("[user] unloads [src]."), \
|
||||
@@ -202,5 +200,9 @@
|
||||
base_icon_state = "biopod"
|
||||
icon_state = "biopod_open"
|
||||
inhand_icon_state = "biopod"
|
||||
greyscale_config = null
|
||||
greyscale_config_inhand_left = null
|
||||
greyscale_config_inhand_right = null
|
||||
greyscale_colors = null
|
||||
|
||||
#undef pet_carrier_full
|
||||
|
||||
@@ -45,6 +45,14 @@
|
||||
/obj/item/food/deadmouse,
|
||||
/obj/item/food/fishmeat,
|
||||
)
|
||||
///list of pet commands we follow
|
||||
var/static/list/pet_commands = list(
|
||||
/datum/pet_command/idle,
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/follow,
|
||||
/datum/pet_command/perform_trick_sequence,
|
||||
)
|
||||
|
||||
///item we are currently holding
|
||||
var/obj/item/held_food
|
||||
///mutable appearance for held item
|
||||
@@ -74,6 +82,7 @@
|
||||
|
||||
/mob/living/basic/pet/cat/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/obeys_commands, pet_commands)
|
||||
AddElement(/datum/element/cultist_pet, pet_cult_icon_state = cult_icon_state)
|
||||
AddElement(/datum/element/wears_collar, collar_icon_state = collar_icon_state, collar_resting_icon_state = TRUE)
|
||||
AddElement(/datum/element/ai_retaliate)
|
||||
@@ -224,3 +233,9 @@
|
||||
name = "Jerry"
|
||||
desc = "Tom is VERY amused."
|
||||
gender = MALE
|
||||
|
||||
/mob/living/basic/pet/cat/tabby
|
||||
icon_state = "cat"
|
||||
icon_living = "cat"
|
||||
icon_dead = "cat_dead"
|
||||
held_state = "cat"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/ai_controller/basic_controller/cat
|
||||
blackboard = list(
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_HOSTILE_MEOWS = list("Mawwww", "Mrewwww", "mhhhhng..."),
|
||||
BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/pet/cat),
|
||||
BB_BABIES_CHILD_TYPES = list(/mob/living/basic/pet/cat/kitten),
|
||||
@@ -9,6 +10,7 @@
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
/datum/ai_planning_subtree/reside_in_home,
|
||||
/datum/ai_planning_subtree/flee_target/from_flee_key/cat_struggle,
|
||||
/datum/ai_planning_subtree/find_and_hunt_target/hunt_mice,
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
blackboard = list(
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
BB_HUNGRY_MEOW = list("mrrp...", "mraw..."),
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_MAX_DISTANCE_TO_FOOD = 2,
|
||||
)
|
||||
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
/datum/ai_planning_subtree/target_retaliate,
|
||||
/datum/ai_planning_subtree/flee_target,
|
||||
/datum/ai_planning_subtree/beg_human,
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/good_boy/dog,
|
||||
/datum/pet_command/follow/dog,
|
||||
/datum/pet_command/perform_trick_sequence,
|
||||
/datum/pet_command/point_targeting/attack/dog,
|
||||
/datum/pet_command/point_targeting/fetch,
|
||||
/datum/pet_command/play_dead,
|
||||
|
||||
@@ -28,9 +28,19 @@
|
||||
attack_sound = 'sound/items/weapons/bite.ogg'
|
||||
attack_vis_effect = ATTACK_EFFECT_BITE
|
||||
ai_controller = /datum/ai_controller/basic_controller/fox
|
||||
///list of our pet commands we follow
|
||||
var/static/list/pet_commands = list(
|
||||
/datum/pet_command/idle,
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/follow,
|
||||
/datum/pet_command/point_targeting/attack,
|
||||
/datum/pet_command/perform_trick_sequence,
|
||||
)
|
||||
|
||||
|
||||
/mob/living/basic/pet/fox/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/obeys_commands, pet_commands)
|
||||
AddElement(/datum/element/cultist_pet)
|
||||
AddElement(/datum/element/wears_collar)
|
||||
AddElement(/datum/element/pet_bonus, "pants and yaps happily!")
|
||||
@@ -42,12 +52,14 @@
|
||||
blackboard = list(
|
||||
BB_ALWAYS_IGNORE_FACTION = TRUE,
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/ours_or_smaller,
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
)
|
||||
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
/datum/ai_planning_subtree/target_retaliate/to_flee,
|
||||
/datum/ai_planning_subtree/flee_target/from_flee_key,
|
||||
/datum/ai_planning_subtree/simple_find_target/not_while_observed,
|
||||
|
||||
@@ -76,6 +76,13 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
|
||||
var/static/list/edibles = list(
|
||||
/obj/item/food/cracker,
|
||||
)
|
||||
///list of commands we follow
|
||||
var/static/list/pet_commands = list(
|
||||
/datum/pet_command/idle,
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/follow,
|
||||
/datum/pet_command/perform_trick_sequence,
|
||||
)
|
||||
|
||||
/// Tracks the times when we send a phrase through either being pet or attack to ensure it's not abused to flood
|
||||
COOLDOWN_DECLARE(forced_speech_cooldown)
|
||||
@@ -92,7 +99,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
|
||||
AddElement(/datum/element/simple_flying)
|
||||
AddComponent(/datum/component/listen_and_repeat, desired_phrases = get_static_list_of_phrases(), blackboard_key = BB_PARROT_REPEAT_STRING)
|
||||
AddComponent(/datum/component/tameable, food_types = edibles, tame_chance = 100, bonus_tame_chance = 0)
|
||||
|
||||
AddComponent(/datum/component/obeys_commands, pet_commands)
|
||||
RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attacking))
|
||||
RegisterSignal(src, COMSIG_MOB_CLICKON, PROC_REF(on_click))
|
||||
RegisterSignal(src, COMSIG_ATOM_ATTACKBY_SECONDARY, PROC_REF(on_attacked)) // this means we could have a peaceful interaction, like getting a cracker
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/ai_controller/basic_controller/parrot
|
||||
blackboard = list(
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items,
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_HOARD_LOCATION_RANGE = 9,
|
||||
)
|
||||
|
||||
@@ -9,11 +10,12 @@
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk/parrot
|
||||
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/parrot_as_in_repeat, // always get a witty oneliner in when you can
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
/datum/ai_planning_subtree/target_retaliate,
|
||||
/datum/ai_planning_subtree/perch_on_target,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
||||
/datum/ai_planning_subtree/hoard_items,
|
||||
/datum/ai_planning_subtree/parrot_as_in_repeat, // always get a witty oneliner in when you can
|
||||
)
|
||||
|
||||
/datum/idle_behavior/idle_random_walk/parrot
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
#define PET_OPTION_DOG "Dog"
|
||||
#define PET_OPTION_CAT "Cat"
|
||||
#define PET_OPTION_FOX "Fox"
|
||||
#define PET_OPTION_VERMIN "Vermin"
|
||||
#define PET_OPTION_BIRD "Bird"
|
||||
|
||||
GLOBAL_LIST_INIT(pet_options, list(
|
||||
PET_OPTION_DOG = list(
|
||||
/mob/living/basic/pet/dog/corgi,
|
||||
/mob/living/basic/pet/dog/pug,
|
||||
/mob/living/basic/pet/dog/bullterrier,
|
||||
/mob/living/basic/pet/dog/corgi/puppy,
|
||||
/mob/living/basic/pet/dog/corgi/exoticcorgi,
|
||||
),
|
||||
PET_OPTION_CAT = list(
|
||||
/mob/living/basic/pet/cat/tabby,
|
||||
/mob/living/basic/pet/cat,
|
||||
/mob/living/basic/pet/cat/kitten,
|
||||
),
|
||||
PET_OPTION_FOX = list(
|
||||
/mob/living/basic/pet/fox,
|
||||
),
|
||||
PET_OPTION_VERMIN = list(
|
||||
/mob/living/basic/mothroach,
|
||||
/mob/living/basic/spider/maintenance,
|
||||
/mob/living/basic/mouse,
|
||||
),
|
||||
PET_OPTION_BIRD = list(
|
||||
/mob/living/basic/parrot,
|
||||
),
|
||||
))
|
||||
|
||||
/datum/pet_customization
|
||||
///our selected path type
|
||||
var/mob/living/basic/selected_path = /mob/living/basic/pet/dog/corgi
|
||||
///current selected specie
|
||||
var/pet_specie = PET_OPTION_DOG
|
||||
///custom name to apply to our pet
|
||||
var/custom_name
|
||||
///type of pet carrier to give our pet
|
||||
var/pet_carrier_path
|
||||
///pet collar color to give our pet
|
||||
var/pet_collar_type
|
||||
///our pet's gender
|
||||
var/pet_gender = MALE
|
||||
///trick name of our pet!
|
||||
var/pet_trick_name = "Trick"
|
||||
///our pet's trick moves
|
||||
var/list/pet_trick_moves
|
||||
///our selected carrier
|
||||
var/pet_carrier
|
||||
///our cached pet carrier icons
|
||||
var/static/list/custom_pet_carriers
|
||||
///possible emotes our pet can run
|
||||
var/static/list/pet_possible_emotes = list(
|
||||
/datum/emote/flip,
|
||||
/datum/emote/jump,
|
||||
/datum/emote/spin,
|
||||
)
|
||||
///list of carrier colors we can pick from
|
||||
var/static/list/possible_colors = list(
|
||||
"Blue" = COLOR_BLUE,
|
||||
"Red" = COLOR_RED,
|
||||
"Yellow" = COLOR_YELLOW,
|
||||
"Green" = COLOR_GREEN,
|
||||
)
|
||||
|
||||
/datum/pet_customization/New(client/player_client)
|
||||
. = ..()
|
||||
if(isnull(custom_pet_carriers))
|
||||
custom_pet_carriers = setup_pet_carriers()
|
||||
pet_carrier = possible_colors[1]
|
||||
GLOB.customized_pets[REF(player_client)] = src
|
||||
|
||||
/datum/pet_customization/proc/setup_pet_carriers()
|
||||
var/list/list_to_return = list()
|
||||
|
||||
var/obj/item/pet_carrier/demo_carrier = new()
|
||||
demo_carrier.open = FALSE
|
||||
demo_carrier.update_appearance()
|
||||
|
||||
for(var/color in possible_colors)
|
||||
demo_carrier.set_greyscale(possible_colors[color])
|
||||
list_to_return[color] = icon2base64(getFlatIcon(demo_carrier))
|
||||
qdel(demo_carrier)
|
||||
return list_to_return
|
||||
|
||||
/datum/pet_customization/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "PetBuilder")
|
||||
ui.open()
|
||||
|
||||
/datum/pet_customization/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["pet_name"] = custom_name
|
||||
data["pet_path"] = selected_path
|
||||
data["pet_gender"] = pet_gender
|
||||
data["pet_trick_name"] = pet_trick_name
|
||||
data["pet_specie"] = pet_specie
|
||||
data["pet_types"] = list()
|
||||
data["pet_options"] = list()
|
||||
for(var/pet_option in GLOB.pet_options)
|
||||
data["pet_types"] += pet_option
|
||||
data["pet_options"] += retrieve_pet_options(pet_option, GLOB.pet_options[pet_option])
|
||||
data["pet_carrier"] = pet_carrier
|
||||
|
||||
data["carrier_options"] = list()
|
||||
for(var/carrier_option in custom_pet_carriers)
|
||||
data["carrier_options"] += list(list(
|
||||
"carrier_color" = carrier_option,
|
||||
"carrier_icon" = custom_pet_carriers[carrier_option],
|
||||
))
|
||||
|
||||
data["pet_possible_emotes"] = list()
|
||||
for(var/datum/emote/emote as anything in pet_possible_emotes)
|
||||
data["pet_possible_emotes"] += emote.key
|
||||
|
||||
return data
|
||||
|
||||
/datum/pet_customization/ui_state(mob/user)
|
||||
return GLOB.always_state
|
||||
|
||||
/datum/pet_customization/proc/retrieve_pet_options(pet_specie, list/input_list)
|
||||
var/list/pet_options = list()
|
||||
for(var/mob/living/pet_type as anything in input_list)
|
||||
pet_options += list(list(
|
||||
"pet_specie" = pet_specie,
|
||||
"pet_name" = pet_type::name,
|
||||
"pet_icon" = pet_type:icon,
|
||||
"pet_path" = pet_type,
|
||||
"pet_icon_state" = pet_type::icon_state,
|
||||
))
|
||||
return pet_options
|
||||
|
||||
/datum/pet_customization/ui_act(action, params, datum/tgui/ui)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("finalize_pet")
|
||||
|
||||
var/pet_type = text2path(params["selected_path"])
|
||||
for(var/pet_category in GLOB.pet_options)
|
||||
var/list/pet_list = GLOB.pet_options[pet_category]
|
||||
if(pet_list.Find(pet_type))
|
||||
selected_path = pet_type
|
||||
break
|
||||
|
||||
var/trick_name = params["selected_trick_name"]
|
||||
if(trick_name && sanitize_name(trick_name))
|
||||
pet_trick_name = trick_name
|
||||
|
||||
var/pet_name = params["selected_pet_name"]
|
||||
if(pet_name && sanitize_name(pet_name))
|
||||
custom_name = pet_name
|
||||
|
||||
switch(params["selected_gender"])
|
||||
if("male")
|
||||
pet_gender = MALE
|
||||
if("female")
|
||||
pet_gender = FEMALE
|
||||
if("neuter")
|
||||
pet_gender = NEUTER
|
||||
|
||||
var/list/trick_moves = params["selected_trick_moves"]
|
||||
if(length(trick_moves))
|
||||
pet_trick_moves = trick_moves
|
||||
|
||||
var/selected_color = params["selected_carrier"]
|
||||
if(!isnull(selected_color))
|
||||
pet_carrier = selected_color
|
||||
|
||||
var/selected_specie = params["selected_specie"]
|
||||
if(!isnull(selected_specie))
|
||||
pet_specie = selected_specie
|
||||
ui.close()
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/pet_customization/proc/create_pet(mob/living/spawned, client/player_client)
|
||||
var/obj/item/pet_carrier/carrier = new(get_turf(spawned))
|
||||
carrier.open = FALSE
|
||||
carrier.update_appearance()
|
||||
var/final_color = possible_colors[pet_carrier] || COLOR_BLUE
|
||||
carrier.set_greyscale(final_color)
|
||||
var/mob/living/our_pet = new selected_path(get_turf(spawned)) //spawning these in nullspace leads to runtimes
|
||||
our_pet.gender = pet_gender
|
||||
|
||||
if(custom_name)
|
||||
our_pet.fully_replace_character_name(our_pet.name, custom_name)
|
||||
|
||||
if(pet_trick_name)
|
||||
our_pet.ai_controller.set_blackboard_key(BB_TRICK_NAME, pet_trick_name)
|
||||
if(pet_trick_moves)
|
||||
our_pet.ai_controller.override_blackboard_key(BB_TRICK_SEQUENCE, pet_trick_moves)
|
||||
our_pet.befriend(spawned)
|
||||
carrier.add_occupant(our_pet)
|
||||
spawned.put_in_hands(carrier, forced = TRUE)
|
||||
GLOB.customized_pets -= REF(player_client)
|
||||
qdel(src)
|
||||
|
||||
#undef PET_OPTION_DOG
|
||||
#undef PET_OPTION_CAT
|
||||
#undef PET_OPTION_FOX
|
||||
#undef PET_OPTION_VERMIN
|
||||
#undef PET_OPTION_BIRD
|
||||
@@ -44,11 +44,13 @@
|
||||
/datum/ai_controller/basic_controller/giant_spider/pest
|
||||
blackboard = list(
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/ours_or_smaller, // Hunt mobs our size
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/larger, // Run away from mobs bigger than we are
|
||||
)
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
/datum/ai_planning_subtree/target_retaliate/to_flee,
|
||||
/datum/ai_planning_subtree/flee_target/from_flee_key,
|
||||
/datum/ai_planning_subtree/simple_find_target,
|
||||
|
||||
@@ -171,10 +171,18 @@
|
||||
response_harm_simple = "splat"
|
||||
ai_controller = /datum/ai_controller/basic_controller/giant_spider/pest
|
||||
apply_spider_antag = FALSE
|
||||
///list of pet commands we follow
|
||||
var/static/list/pet_commands = list(
|
||||
/datum/pet_command/idle,
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/follow,
|
||||
/datum/pet_command/perform_trick_sequence,
|
||||
)
|
||||
|
||||
/mob/living/basic/spider/maintenance/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
|
||||
AddElement(/datum/element/web_walker, /datum/movespeed_modifier/average_web)
|
||||
AddElement(/datum/element/ai_retaliate)
|
||||
AddComponent(/datum/component/obeys_commands, pet_commands)
|
||||
AddElement(/datum/element/tiny_mob_hunter)
|
||||
|
||||
@@ -33,11 +33,19 @@
|
||||
faction = list(FACTION_NEUTRAL)
|
||||
|
||||
ai_controller = /datum/ai_controller/basic_controller/mothroach
|
||||
///list of pet commands we follow
|
||||
var/static/list/pet_commands = list(
|
||||
/datum/pet_command/idle,
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/follow,
|
||||
/datum/pet_command/perform_trick_sequence,
|
||||
)
|
||||
|
||||
/mob/living/basic/mothroach/Initialize(mapload)
|
||||
. = ..()
|
||||
var/static/list/food_types = list(/obj/item/clothing)
|
||||
AddElement(/datum/element/basic_eating, food_types = food_types)
|
||||
AddComponent(/datum/component/obeys_commands, pet_commands)
|
||||
ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(food_types))
|
||||
AddElement(/datum/element/ai_retaliate)
|
||||
AddElement(/datum/element/pet_bonus, "squeaks happily!")
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
/datum/ai_controller/basic_controller/mothroach
|
||||
blackboard = list(
|
||||
BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items,
|
||||
)
|
||||
|
||||
@@ -10,6 +11,7 @@
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
/datum/ai_planning_subtree/find_food/mothroach,
|
||||
/datum/ai_planning_subtree/target_retaliate/to_flee,
|
||||
/datum/ai_planning_subtree/flee_target/from_flee_key,
|
||||
|
||||
@@ -36,6 +36,13 @@
|
||||
var/contributes_to_ratcap = TRUE
|
||||
/// Probability that, if we successfully bite a shocked cable, that we will die to it.
|
||||
var/cable_zap_prob = 85
|
||||
///list of pet commands we follow
|
||||
var/static/list/pet_commands = list(
|
||||
/datum/pet_command/idle,
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/follow,
|
||||
/datum/pet_command/perform_trick_sequence,
|
||||
)
|
||||
|
||||
/mob/living/basic/mouse/Initialize(mapload, tame = FALSE, new_body_color)
|
||||
. = ..()
|
||||
@@ -55,6 +62,7 @@
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
||||
)
|
||||
AddComponent(/datum/component/obeys_commands, pet_commands)
|
||||
AddElement(/datum/element/connect_loc, loc_connections)
|
||||
make_tameable()
|
||||
AddComponent(/datum/component/swarming, 16, 16) //max_x, max_y
|
||||
@@ -383,9 +391,8 @@
|
||||
/// The mouse AI controller
|
||||
/datum/ai_controller/basic_controller/mouse
|
||||
blackboard = list( // Always cowardly
|
||||
BB_CURRENT_HUNTING_TARGET = null, // cheese
|
||||
BB_LOW_PRIORITY_HUNTING_TARGET = null, // cable
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, // Use this to find people to run away from
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_BASIC_MOB_FLEE_DISTANCE = 3,
|
||||
)
|
||||
|
||||
@@ -393,6 +400,7 @@
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
// Top priority is to look for and execute hunts for cheese even if someone is looking at us
|
||||
/datum/ai_planning_subtree/find_and_hunt_target/look_for_cheese,
|
||||
// Next priority is see if anyone is looking at us
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -5079,6 +5079,7 @@
|
||||
#include "code\modules\mob\living\basic\pets\fox.dm"
|
||||
#include "code\modules\mob\living\basic\pets\penguin.dm"
|
||||
#include "code\modules\mob\living\basic\pets\pet.dm"
|
||||
#include "code\modules\mob\living\basic\pets\pet_designer.dm"
|
||||
#include "code\modules\mob\living\basic\pets\sloth.dm"
|
||||
#include "code\modules\mob\living\basic\pets\cat\bread_cat_ai.dm"
|
||||
#include "code\modules\mob\living\basic\pets\cat\cat.dm"
|
||||
|
||||
@@ -4,11 +4,18 @@ import { SearchItem } from './types';
|
||||
|
||||
type Props = {
|
||||
item: SearchItem;
|
||||
size: Size;
|
||||
};
|
||||
|
||||
type Size = {
|
||||
height: number;
|
||||
width: number;
|
||||
};
|
||||
|
||||
export function IconDisplay(props: Props) {
|
||||
const {
|
||||
item: { icon, icon_state },
|
||||
size: { height, width },
|
||||
} = props;
|
||||
|
||||
const fallback = <Icon name="spinner" size={2.2} spin color="gray" />;
|
||||
@@ -27,8 +34,8 @@ export function IconDisplay(props: Props) {
|
||||
fallback={fallback}
|
||||
icon={icon}
|
||||
icon_state={icon_state}
|
||||
height={3}
|
||||
width={3}
|
||||
height={height}
|
||||
width={width}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export function LootBox(props: Props) {
|
||||
});
|
||||
}}
|
||||
>
|
||||
<IconDisplay item={item} />
|
||||
<IconDisplay item={item} size={{ height: 3, width: 3 }} />
|
||||
{amount > 1 && <div className="SearchItem--amount">{amount}</div>}
|
||||
</div>
|
||||
{!is_blind && <span className="SearchItem--text">{name}</span>}
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useBackend } from '../backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Dropdown,
|
||||
Flex,
|
||||
Icon,
|
||||
Image,
|
||||
Input,
|
||||
LabeledList,
|
||||
Section,
|
||||
Stack,
|
||||
} from '../components';
|
||||
import { Window } from '../layouts';
|
||||
import { IconDisplay } from './LootPanel/IconDisplay';
|
||||
type Data = {
|
||||
pet_name: string | null;
|
||||
pet_specie: string;
|
||||
pet_path: string;
|
||||
pet_gender: string;
|
||||
pet_types: string[];
|
||||
pet_trick_name: string;
|
||||
pet_options: PetOptions[];
|
||||
pet_carrier: string;
|
||||
carrier_options: CarrierOptions[];
|
||||
pet_possible_emotes: String[];
|
||||
};
|
||||
|
||||
enum PetGender {
|
||||
male = 'male',
|
||||
female = 'female',
|
||||
neuter = 'neuter',
|
||||
}
|
||||
|
||||
type CarrierOptions = {
|
||||
carrier_color: string;
|
||||
carrier_icon: string;
|
||||
};
|
||||
|
||||
type PetOptions = {
|
||||
pet_specie: string;
|
||||
pet_name: string;
|
||||
pet_icon: string;
|
||||
pet_path: string;
|
||||
pet_icon_state: string;
|
||||
};
|
||||
|
||||
const RetrievePet = (pet_path: string, pet_options: PetOptions[]) => {
|
||||
return pet_options.find((option) => option.pet_path === pet_path);
|
||||
};
|
||||
|
||||
const RetrieveCarrier = (color: string, carrier_options: CarrierOptions[]) => {
|
||||
return carrier_options.find((option) => option.carrier_color === color);
|
||||
};
|
||||
|
||||
const FilterPetList = (pet_specie: string, pet_options: PetOptions[]) => {
|
||||
return pet_options.filter((pet) => pet.pet_specie === pet_specie);
|
||||
};
|
||||
|
||||
export const PetBuilder = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
const {
|
||||
pet_name,
|
||||
pet_path,
|
||||
pet_gender,
|
||||
pet_options,
|
||||
pet_types,
|
||||
pet_specie,
|
||||
pet_trick_name,
|
||||
carrier_options,
|
||||
pet_carrier,
|
||||
pet_possible_emotes,
|
||||
} = data;
|
||||
|
||||
const [selectedCarrier, setSelectedCarrier] = useState(
|
||||
() => RetrieveCarrier(pet_carrier, carrier_options) || null,
|
||||
);
|
||||
const [sequences, setSequences] = useState(['none', 'none', 'none']);
|
||||
const [TrickName, setTrickName] = useState(pet_trick_name);
|
||||
|
||||
const UpdateSequence = (Index: number, Trick: string) => {
|
||||
const NewSequence = [...sequences];
|
||||
NewSequence[Index] = Trick;
|
||||
setSequences(NewSequence);
|
||||
};
|
||||
|
||||
const [selectedPath, setSelectedPath] = useState(pet_path);
|
||||
const [selectedPet, setSelectedPet] = useState(
|
||||
() => RetrievePet(selectedPath, pet_options) || null,
|
||||
);
|
||||
const [selectedSpecie, setSelectedSpecie] = useState(pet_specie);
|
||||
const [filteredPetList, setFilteredPetList] = useState(
|
||||
() => FilterPetList(selectedSpecie, pet_options) || [],
|
||||
);
|
||||
const [selectedName, setSelectedName] = useState(pet_name);
|
||||
const [selectedGender, setSelectedGender] = useState(pet_gender);
|
||||
|
||||
const ScrollPetSpecies = (direction: string) => {
|
||||
let dir = direction === 'next' ? 1 : -1;
|
||||
let currindex = pet_types.indexOf(selectedSpecie);
|
||||
const newSpecie =
|
||||
pet_types[(currindex + dir + pet_types.length) % pet_types.length];
|
||||
|
||||
const newFilteredPetList = FilterPetList(newSpecie, pet_options);
|
||||
setSelectedSpecie(newSpecie);
|
||||
setFilteredPetList(newFilteredPetList);
|
||||
setSelectedPet(newFilteredPetList[0]);
|
||||
};
|
||||
|
||||
const ScrollPetOptions = (direction: string) => {
|
||||
if (!selectedPet) {
|
||||
return;
|
||||
}
|
||||
let dir = direction === 'next' ? 1 : -1;
|
||||
let currindex = filteredPetList.indexOf(selectedPet);
|
||||
setSelectedPet(
|
||||
filteredPetList[
|
||||
(currindex + dir + filteredPetList.length) % filteredPetList.length
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Window title="Create Your Pet!" width={665} height={325}>
|
||||
<Window.Content>
|
||||
<Flex width="50%">
|
||||
<Flex.Item>
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<PetSelector
|
||||
selectedSpecie={selectedSpecie}
|
||||
selectedPet={selectedPet}
|
||||
pet_types={pet_types}
|
||||
ScrollPetSpecies={ScrollPetSpecies}
|
||||
ScrollPetOptions={ScrollPetOptions}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item mt={1.5}>
|
||||
<Section
|
||||
textAlign="center"
|
||||
style={{
|
||||
borderRadius: '1em',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
act('finalize_pet', {
|
||||
selected_path: selectedPet?.pet_path,
|
||||
selected_trick_name: TrickName,
|
||||
selected_trick_moves: sequences,
|
||||
selected_pet_name: selectedName,
|
||||
selected_gender: selectedGender,
|
||||
selected_specie: selectedSpecie,
|
||||
selected_carrier: selectedCarrier?.carrier_color,
|
||||
})
|
||||
}
|
||||
style={{
|
||||
fontSize: '27px',
|
||||
borderRadius: '1em',
|
||||
}}
|
||||
>
|
||||
<Flex>
|
||||
<Flex.Item>
|
||||
<Icon name="paw" />
|
||||
</Flex.Item>
|
||||
<Flex.Item ml={1}>Finalize Pet!</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Icon ml={1} name="paw" />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Button>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Flex.Item>
|
||||
<Flex.Item ml={1}>
|
||||
<Section width="350px">
|
||||
<PetDetails
|
||||
selectedName={selectedName}
|
||||
setSelectedName={setSelectedName}
|
||||
selectedGender={selectedGender}
|
||||
setSelectedGender={setSelectedGender}
|
||||
/>
|
||||
<Flex>
|
||||
<Flex.Item width="70px">
|
||||
<CarrierSelector
|
||||
selectedCarrier={selectedCarrier}
|
||||
carrier_options={carrier_options}
|
||||
setSelectedCarrier={setSelectedCarrier}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item ml={5} grow>
|
||||
<TrickSequence
|
||||
ml={5}
|
||||
TrickName={TrickName}
|
||||
pet_possible_emotes={pet_possible_emotes}
|
||||
setTrickName={setTrickName}
|
||||
sequences={sequences}
|
||||
UpdateSequence={UpdateSequence}
|
||||
carrier_options={carrier_options}
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const PetSelector = ({
|
||||
selectedSpecie,
|
||||
selectedPet,
|
||||
pet_types,
|
||||
ScrollPetSpecies,
|
||||
ScrollPetOptions,
|
||||
}: any) => (
|
||||
<Section>
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<Flex style={{ borderBottom: '2px solid #6f1d94' }}>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
color="transparent"
|
||||
icon="arrow-left"
|
||||
style={{ fontSize: '16px' }}
|
||||
onClick={() => ScrollPetSpecies('previous')}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item grow textAlign="center" style={{ fontSize: '16px' }}>
|
||||
{selectedSpecie}
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
color="transparent"
|
||||
icon="arrow-right"
|
||||
style={{ fontSize: '16px' }}
|
||||
onClick={() => ScrollPetSpecies('next')}
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Stack.Item>
|
||||
{selectedPet && (
|
||||
<Stack.Item mt={5}>
|
||||
<Flex>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
mt={5}
|
||||
color="transparent"
|
||||
icon="arrow-left"
|
||||
style={{ fontSize: '20px' }}
|
||||
onClick={() => ScrollPetOptions('previous')}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item grow textAlign="center">
|
||||
<IconDisplay
|
||||
item={{
|
||||
icon: selectedPet.pet_icon,
|
||||
icon_state: selectedPet.pet_icon_state,
|
||||
name: selectedPet.pet_name,
|
||||
path: selectedPet.pet_path,
|
||||
ref: selectedPet.pet_ref,
|
||||
}}
|
||||
size={{
|
||||
height: 11,
|
||||
width: 11,
|
||||
}}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
mt={5}
|
||||
color="transparent"
|
||||
style={{ fontSize: '20px' }}
|
||||
icon="arrow-right"
|
||||
onClick={() => ScrollPetOptions('next')}
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Stack.Item>
|
||||
)}
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
|
||||
const PetDetails = ({
|
||||
selectedName,
|
||||
setSelectedName,
|
||||
selectedGender,
|
||||
setSelectedGender,
|
||||
}: any) => (
|
||||
<Stack vertical width="85%">
|
||||
<Flex style={{ borderBottom: '1px solid gray' }}>
|
||||
<Flex.Item>
|
||||
<Stack vertical>
|
||||
<Stack.Item style={{ fontSize: '16px' }}>Pet Name</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Input
|
||||
mb={2}
|
||||
ml={2}
|
||||
mt={0.5}
|
||||
width="220px"
|
||||
maxLength={30}
|
||||
value={selectedName}
|
||||
onInput={(_, value) => setSelectedName(value)}
|
||||
style={{ borderRadius: '1em' }}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Icon
|
||||
style={{ transform: 'rotate(30deg)', fontSize: '30px' }}
|
||||
ml={8}
|
||||
mt={1}
|
||||
name="paw"
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
<Stack.Item>
|
||||
<Stack vertical>
|
||||
<Stack.Item style={{ fontSize: '16px' }}>Pet Gender</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Stack mt={0.5} style={{ borderBottom: '1px solid gray' }}>
|
||||
<Stack.Item grow ml={2} mb={2}>
|
||||
<Button
|
||||
selected={selectedGender === PetGender.male}
|
||||
icon="mars"
|
||||
onClick={() => setSelectedGender(PetGender.male)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Button
|
||||
selected={selectedGender === PetGender.female}
|
||||
icon="venus"
|
||||
onClick={() => setSelectedGender(PetGender.female)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Button
|
||||
selected={selectedGender === PetGender.neuter}
|
||||
icon="neuter"
|
||||
onClick={() => setSelectedGender(PetGender.neuter)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
const TrickSequence = ({
|
||||
TrickName,
|
||||
setTrickName,
|
||||
sequences,
|
||||
pet_possible_emotes,
|
||||
UpdateSequence,
|
||||
carrier_options,
|
||||
}: any) => (
|
||||
<Section
|
||||
mt={1}
|
||||
width="80%"
|
||||
style={{ borderBottom: '0px solid #6f1d94' }}
|
||||
title={TrickName}
|
||||
buttons={
|
||||
<Button.Input
|
||||
color="transparent"
|
||||
onCommit={(_, value) => setTrickName(value)}
|
||||
>
|
||||
Rename
|
||||
</Button.Input>
|
||||
}
|
||||
>
|
||||
<Box ml={2}>
|
||||
<LabeledList>
|
||||
{sequences.map((sequence: string, index: number) => (
|
||||
<LabeledList.Item key={index} label={`Move ${index + 1}`}>
|
||||
<Dropdown
|
||||
width="80%"
|
||||
selected={sequences[index]}
|
||||
options={pet_possible_emotes}
|
||||
onSelected={(selected: string) => UpdateSequence(index, selected)}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
|
||||
const CarrierSelector = ({
|
||||
selectedCarrier,
|
||||
carrier_options,
|
||||
setSelectedCarrier,
|
||||
}: any) => (
|
||||
<Flex grow>
|
||||
<Flex.Item width="30%">
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<Image
|
||||
m={1}
|
||||
src={`data:image/jpeg;base64,${selectedCarrier?.carrier_icon}`}
|
||||
height="64px"
|
||||
width="64px"
|
||||
style={{ verticalAlign: 'middle' }}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Dropdown
|
||||
width="70px"
|
||||
selected={selectedCarrier?.carrier_color}
|
||||
options={carrier_options.map(
|
||||
(carrier: any) => carrier.carrier_color,
|
||||
)}
|
||||
onSelected={(selected: string) => {
|
||||
const new_carrier = RetrieveCarrier(selected, carrier_options);
|
||||
if (new_carrier) {
|
||||
setSelectedCarrier(new_carrier);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
);
|
||||