Skip to content

Commit

Permalink
Adds achievement-unlockables hats for orbies (feat. big rollies from …
Browse files Browse the repository at this point in the history
…hacked cigarette vending machines) (#86098)

## About The Pull Request
So, do you remember orbies, those cutesy virtual PDA pets from that PR
that Ben made roughly six months ago before moving on his next project,
leaving them to be probably forgotten in a near future/present/past?
Yeah, personally I never played around, however I recalled that they do
have customizable virtual hats, which can be selected from a dropdown in
the UI, and I thought that it would be a perfect target for some
achievement-related content, as they're totally cosmetic that provides
no gameplay advantage nor affects balance in no way whatsoever. I cannot
sit well with cheevos being purely an end to itself, that's the reason
this PR exists.

The new additions to orbies hats, and their respective required
achievements are:
- The fishing hat (Legendary Fisher)
- A huge-ass rollie (Unhealthy Snacks) (yeah, it isn't exactly a hat but
the code in no way assume that the item has to be a hat, beside vars
named like that for the sake of convenience)
- A tape wizard hat (Archmage)
- An energy cakehat (Very Important Piscis)
- A bounty hunter cowboy hat (Hot Damn!)
- A fancy crown (Outdebted)

The huge-ass rollie (called fat dart) in the game, is a new cigarette,
rarely found in hacked cigarette vending machines. It's obviously a
reference to that Ralsei meme from 3 years ago or so but I personally
don't care, I just wanted to give an excessively big cigarette to orbies
to symbolize the proposterous accomplishment of eating 500 cigarettes in
a single round without dying from nicotine OD less than halfway through,
but since orbie hats use actual items are references for their
appearance, I found myself obliged to add one to the code. Overall, the
fat dart comes from an old PR on Citadel, though I had to resprite it
myself.

Here's a lazy collage of the hats. For some reason unbeknownst to me,
the hats are horizontally squished. I need to ask Ben why he did them
this way when Orbies' heads are as wide as a rugby ball.

![immagine](https://github.com/user-attachments/assets/f1b0e28f-1fb5-4678-bc32-fe38ca04a1b6)

## Why It's Good For The Game
Simple, extra cosmetic stuff for a simple feature that's as relevant as
playing around with plushes.

## Changelog

:cl:
add: Added more customizable options to PDA virtual pets, which can be
unlocked by completing achievements.
add: Added a fat dart that can be rarely found in hacked cigarette
vending machines.
/:cl:
  • Loading branch information
Ghommie authored and Iajret committed Sep 23, 2024
1 parent 491ec36 commit 9184e80
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 19 deletions.
22 changes: 22 additions & 0 deletions code/game/objects/items/cigarettes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
name = "cigarette"
desc = "A roll of tobacco and nicotine. It is not food."
icon = 'icons/obj/cigarettes.dmi'
worn_icon = 'icons/mob/clothing/mask.dmi'
icon_state = "cigoff"
inhand_icon_state = "cigon" //gets overriden during intialize(), just have it for unit test sanity.
throw_speed = 0.5
Expand Down Expand Up @@ -693,6 +694,27 @@ CIGARETTE PACKETS ARE IN FANCY.DM
pixel_y = rand(-5, 5)


/obj/item/cigarette/dart
name = "fat dart"
desc = "Chuff back this fat dart"
icon_state = "bigon"
icon_on = "bigon"
icon_off = "bigoff"
w_class = WEIGHT_CLASS_BULKY
smoketime = 18 MINUTES
chem_volume = 65
list_reagents = list(/datum/reagent/drug/nicotine = 45)
choke_time_max = 40 SECONDS
lung_harm = 2

/obj/item/cigarette/dart/Initialize(mapload)
. = ..()
//the compiled icon state is how it appears when it's on.
//That's how we want it to show on orbies (little virtual PDA pets).
//However we should reset their appearance on runtime.
update_appearance(UPDATE_ICON_STATE)


////////////
// CIGARS //
////////////
Expand Down
9 changes: 8 additions & 1 deletion code/modules/clothing/head/cakehat.dm
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
/obj/item/clothing/head/utility/hardhat/cakehat/energycake
name = "energy cake"
desc = "You put the energy sword on your cake. Brilliant."
icon_state = "hardhat0_energycake"
icon_state = "hardhat1_energycake"
inhand_icon_state = "hardhat0_energycake"
hat_type = "energycake"
hitsound = 'sound/weapons/tap.ogg'
Expand All @@ -68,6 +68,13 @@
light_range = 3 //ditto
heat = 0

/obj/item/clothing/head/utility/hardhat/cakehat/energycake/Initialize(mapload)
. = ..()
//the compiled icon state is how it appears when it's on.
//That's how we want it to show on orbies (little virtual PDA pets).
//However we should reset their appearance on runtime.
update_appearance(UPDATE_ICON_STATE)

/obj/item/clothing/head/utility/hardhat/cakehat/energycake/turn_on(mob/living/user)
playsound(src, 'sound/weapons/saberon.ogg', 5, TRUE)
to_chat(user, span_warning("You turn on \the [src]."))
Expand Down
1 change: 1 addition & 0 deletions code/modules/mob/living/basic/pets/orbie/orbie.dm
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
AddComponent(/datum/component/obeys_commands, pet_commands)
AddElement(/datum/element/basic_eating, food_types = food_types)
ADD_TRAIT(src, TRAIT_SILICON_EMOTES_ALLOWED, INNATE_TRAIT)

RegisterSignal(src, COMSIG_ATOM_CAN_BE_PULLED, PROC_REF(on_pulled))
RegisterSignal(src, COMSIG_VIRTUAL_PET_LEVEL_UP, PROC_REF(on_level_up))
RegisterSignal(src, COMSIG_MOB_CLICKON, PROC_REF(on_click))
Expand Down
81 changes: 63 additions & 18 deletions code/modules/modular_computers/file_system/programs/virtual_pet.dm
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,47 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)
var/static/list/hat_selections = list(
/obj/item/clothing/head/hats/tophat = 1,
/obj/item/clothing/head/fedora = 1,
/obj/item/clothing/head/soft/fishing_hat = 1,
/obj/item/cigarette/dart = 1,
/obj/item/clothing/head/hats/bowler = 2,
/obj/item/clothing/head/hats/warden/police = 2,
/obj/item/clothing/head/wizard/tape = 2,
/obj/item/clothing/head/utility/hardhat/cakehat/energycake = 2,
/obj/item/clothing/head/cowboy/bounty = 2,
/obj/item/clothing/head/hats/warden/red = 3,
/obj/item/clothing/head/hats/caphat = 3,
/obj/item/clothing/head/costume/crown/fancy = 3,
)
///hat options that are locked behind achievements
var/static/list/cheevo_hats = list(
/obj/item/clothing/head/soft/fishing_hat = /datum/award/achievement/skill/legendary_fisher,
/obj/item/cigarette/dart = /datum/award/achievement/misc/cigarettes,
/obj/item/clothing/head/wizard/tape = /datum/award/achievement/misc/grand_ritual_finale,
/obj/item/clothing/head/utility/hardhat/cakehat/energycake = /datum/award/achievement/misc/cayenne_disk,
/obj/item/clothing/head/cowboy/bounty = /datum/award/achievement/misc/hot_damn,
/obj/item/clothing/head/costume/crown/fancy = /datum/award/achievement/misc/debt_extinguished,
)
///A list of hats that override the hat offsets and transform variable
var/static/list/special_hat_placement = list(
/obj/item/cigarette/dart = list(
"west" = list(2,-1),
"east" = list(-2,-1),
"north" = list(0,0),
"south" = list(0, -3),
"transform" = list(1, 1),
),
)
///hologram hat we have selected for our pet
var/list/selected_hat = list()
///area we have picked as dropoff location for petfeed
var/area/selected_area
///manage hat offsets for when we turn directions
var/static/list/hat_offsets = list(
"west" = list(0,1),
"east" = list(0,1),
"north" = list(1,1),
"south" = list(0,1),
"south" = list(1,1),
)
///area we have picked as dropoff location for petfeed
var/area/selected_area
///possible colors our pet can have
var/static/list/possible_colors= list(
"white" = null, //default color state
Expand Down Expand Up @@ -171,12 +196,11 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)

/datum/computer_file/program/virtual_pet/proc/set_hat_offsets(new_dir)
var/direction_text = dir2text(new_dir)
var/list/offsets_list = hat_offsets[direction_text]
if(isnull(offsets_list))
return
var/hat_type = selected_hat["type"]
var/list/offsets_list = special_hat_placement[hat_type]?[direction_text] || hat_offsets[direction_text]
var/mutable_appearance/hat_appearance = selected_hat["appearance"]
hat_appearance.pixel_x = offsets_list[1]
hat_appearance.pixel_y = offsets_list[2]
hat_appearance.pixel_w = offsets_list[1]
hat_appearance.pixel_z = offsets_list[2] + selected_hat["worn_offset"]
pet.update_appearance(UPDATE_OVERLAYS)

///give our pet his hologram hat
Expand All @@ -195,10 +219,15 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)
if(length(selected_hat))
var/mutable_appearance/our_selected_hat = selected_hat["appearance"]
var/mutable_appearance/hat_preview = mutable_appearance(our_selected_hat.icon, our_selected_hat.icon_state)
hat_preview.pixel_y = -9
hat_preview.pixel_y = -9 + selected_hat["worn_offset"]
var/list/spec_hat = special_hat_placement[selected_hat["type"]]?["south"]
if(spec_hat)
hat_preview.pixel_w += spec_hat[1]
hat_preview.pixel_z += spec_hat[2]
hat_preview.appearance_flags = RESET_COLOR
pet_preview.add_overlay(hat_preview)

profile_picture = getFlatIcon(pet_preview)
profile_picture = getFlatIcon(pet_preview, no_anim = TRUE)
COOLDOWN_START(src, alter_appearance_cooldown, 10 SECONDS)


Expand Down Expand Up @@ -344,12 +373,13 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)

/datum/computer_file/program/virtual_pet/ui_data(mob/user)
var/list/data = list()
var/obj/item/hat_type = selected_hat?["type"]
data["currently_summoned"] = (pet.loc != computer)
data["selected_area"] = (selected_area ? selected_area.name : "No location set")
data["pet_state"] = get_pet_state()
data["hunger"] = hunger
data["maximum_hunger"] = max_hunger
data["pet_hat"] = (length(selected_hat) ? selected_hat["name"] : "none")
data["pet_hat"] = (hat_type ? initial(hat_type.name) : "none")
data["can_reroll"] = COOLDOWN_FINISHED(src, area_reroll)
data["can_summon"] = COOLDOWN_FINISHED(src, summon_cooldown)
data["can_alter_appearance"] = COOLDOWN_FINISHED(src, alter_appearance_cooldown)
Expand Down Expand Up @@ -415,9 +445,14 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)
for(var/type_index as anything in hat_selections)
if(level >= hat_selections[type_index])
var/obj/item/hat = type_index
var/obj/item/hat_name = initial(hat.name)
if(length(SSachievements.achievements)) // The Achievements subsystem is active.
var/datum/award/required_cheevo = cheevo_hats[hat]
if(required_cheevo && !user.client.get_award_status(required_cheevo))
hat_name = "LOCKED"
data["hat_selections"] += list(list(
"hat_id" = type_index,
"hat_name" = initial(hat.name),
"hat_name" = hat_name,
))

data["possible_colors"] = list()
Expand Down Expand Up @@ -461,12 +496,22 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)
if(isnull(chosen_type))
selected_hat.Cut()

else if((chosen_type in hat_selections))
selected_hat["name"] = initial(chosen_type.name)
var/mutable_appearance/selected_hat_appearance = mutable_appearance(icon = initial(chosen_type.worn_icon), icon_state = initial(chosen_type.icon_state), layer = ABOVE_ALL_MOB_LAYER)
selected_hat_appearance.transform = selected_hat_appearance.transform.Scale(0.8, 1)
selected_hat["appearance"] = selected_hat_appearance
set_hat_offsets(pet.dir)
else if(hat_selections[chosen_type])
var/datum/award/required_cheevo = cheevo_hats[chosen_type]
if(length(SSachievements.achievements) && required_cheevo && !ui.user.client.get_award_status(required_cheevo))
to_chat(ui.user, span_info("This customization requires the \"[span_bold(initial(required_cheevo.name))]\ achievement to be unlocked."))
else
selected_hat["type"] = chosen_type
var/state_to_use = initial(chosen_type.worn_icon_state) || initial(chosen_type.icon_state)
var/mutable_appearance/selected_hat_appearance = mutable_appearance(initial(chosen_type.worn_icon), state_to_use, appearance_flags = RESET_COLOR)
selected_hat["worn_offset"] = initial(chosen_type.worn_y_offset)
var/list/scale_list = special_hat_placement[chosen_type]?["scale"]
if(scale_list)
selected_hat_appearance.transform = selected_hat_appearance.transform.Scale(scale_list[1], scale_list[2])
else
selected_hat_appearance.transform = selected_hat_appearance.transform.Scale(0.8, 1)
selected_hat["appearance"] = selected_hat_appearance
set_hat_offsets(pet.dir)

var/chosen_color = params["chosen_color"]
if(isnull(chosen_color))
Expand Down
1 change: 1 addition & 0 deletions code/modules/vending/cigarette.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
)
contraband = list(
/obj/item/vape = 5,
/obj/item/cigarette/dart = 1,
)
premium = list(
/obj/item/storage/fancy/cigarettes/cigpack_robustgold = 3,
Expand Down
Binary file modified icons/mob/clothing/mask.dmi
Binary file not shown.
Binary file modified icons/obj/cigarettes.dmi
Binary file not shown.

0 comments on commit 9184e80

Please sign in to comment.