Skip to content

Commit

Permalink
hat stacking
Browse files Browse the repository at this point in the history
  • Loading branch information
dwasint committed Mar 17, 2023
1 parent 35a8689 commit 05a26fb
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 2 deletions.
16 changes: 16 additions & 0 deletions code/modules/clothing/head/_head.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
body_parts_covered = HEAD
slot_flags = ITEM_SLOT_HEAD

/obj/item/clothing/head/Initialize(mapload)
. = ..()
remove_verb(src, /obj/item/clothing/head/verb/detach_stacked_hat)

///Special throw_impact for hats to frisbee hats at people to place them on their heads/attempt to de-hat them.
/obj/item/clothing/head/throw_impact(atom/hit_atom, datum/thrownthing/thrownthing)
. = ..()
Expand Down Expand Up @@ -70,6 +74,18 @@
else
. += mutable_appearance('icons/effects/blood.dmi', "helmetblood")

if(contents)
var/current_hat = 1
for(var/obj/item/clothing/head/selected_hat in contents)
var/head_icon = 'icons/mob/clothing/head/beanie.dmi'
if(selected_hat.worn_icon)
head_icon = selected_hat.icon
var/mutable_appearance/hat_adding = selected_hat.build_worn_icon(HEAD_LAYER, head_icon, FALSE, FALSE)
hat_adding.pixel_y = ((current_hat * 4) - 1)
hat_adding.pixel_x = (rand(-1, 1))
current_hat++
. += hat_adding

/obj/item/clothing/head/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED)
..()
if(ismob(loc))
Expand Down
17 changes: 17 additions & 0 deletions code/modules/mob/emote.dm
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@
if(.)
user.SpinAnimation(7,1)

if(isliving(user) && intentional)
var/mob/living/L = user
if(iscarbon(L))
var/mob/living/carbon/hat_loser = user
if(hat_loser.head)
var/obj/item/clothing/head/worn_headwear = hat_loser.head
if(worn_headwear.contents.len)
worn_headwear.throw_hats(rand(2,3), get_turf(hat_loser), hat_loser)

/datum/emote/flip/check_cooldown(mob/user, intentional)
. = ..()
if(.)
Expand Down Expand Up @@ -106,6 +115,14 @@
. = ..()
if(.)
user.spin(20, 1)
if(isliving(user) && intentional)
var/mob/living/L = user
if(iscarbon(L))
var/mob/living/carbon/hat_loser = user
if(hat_loser.head)
var/obj/item/clothing/head/worn_headwear = hat_loser.head
if(worn_headwear.contents.len)
worn_headwear.throw_hats(rand(1,2), get_turf(hat_loser), hat_loser)

/datum/emote/spin/check_cooldown(mob/living/carbon/user, intentional)
. = ..()
Expand Down
118 changes: 118 additions & 0 deletions monkestation/code/modules/clothing/head/misc.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#define HAT_CAP 20 //Maximum number of hats stacked upon the base hat.
#define ADD_HAT 0
#define REMOVE_HAT 1

/obj/item/clothing/head/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/clothing/head) && !istype(I, /obj/item/clothing/head/mob_holder) && !istype(src, /obj/item/clothing/head/mob_holder)) //No putting Ian on a hat or vice-reversa
if(contents) //Checking for previous hats and preventing towers that are too large
if(I.contents)
if(I.contents.len + contents.len + 1 > HAT_CAP)
to_chat(user,"<span class='warning'>You think that this hat tower is perfect the way it is and decide against adding another.</span>")
return
for(var/obj/item/clothing/head/hat_movement in I.contents)
hat_movement.name = initial(name)
hat_movement.desc = initial(desc)
hat_movement.forceMove(src)
var/hat_count = contents.len
if(hat_count + 1 > HAT_CAP)
to_chat(user,"<span class='warning'>You think that this hat tower is perfect the way it is and decide against adding another.</span>")
return
var/obj/item/clothing/head/new_hat = I
if(user.transferItemToLoc(new_hat,src)) //Moving the new hat to the base hat's contents
to_chat(user, "<span class='notice'>You place the [new_hat] upon the [src].</span>")
update_hats(ADD_HAT, user)
else
. = ..()


/obj/item/clothing/head/verb/detach_stacked_hat()
set name = "Remove Stacked Hat"
set category = "Object"
set src in usr

if(!isliving(usr))
return
if(!can_use(usr))
return
if(src.contents)
update_hats(REMOVE_HAT,usr)

/obj/item/clothing/head/proc/restore_initial() //Why can't initial() be called directly by something?
name = initial(name)
desc = initial(desc)

/obj/item/clothing/head/proc/throw_hats(var/hat_count, var/turf/wearer_location, var/mob/user)
for(var/obj/item/clothing/head/throwing_hat in contents)
var/destination = get_edge_target_turf(wearer_location, pick(GLOB.alldirs))
if(!hat_count) //Only throw X number of hats
break
throwing_hat.forceMove(wearer_location)
throwing_hat.throw_at(destination, rand(1,4), 10)
hat_count--
update_hats(0, user)
if(user)
user.visible_message("<span class='warning'>[user]'s hats go flying off!</span>")

/obj/item/clothing/head/proc/update_hats(var/hat_removal, var/mob/living/user)

if(hat_removal)
var/obj/item/clothing/head/hat_to_remove = contents[contents.len] //Get the last item in the hat and hand it to the user.
hat_to_remove.restore_initial()
remove_verb(hat_to_remove, /obj/item/clothing/head/verb/detach_stacked_hat)
user.put_in_hands(hat_to_remove)

cut_overlays()

if(contents)
//This section prepares the in-hand and on-ground icon states for the hats.
var/current_hat = 1
for(var/obj/item/clothing/head/selected_hat in contents)
selected_hat.cut_overlays()
selected_hat.forceMove(src)
selected_hat.name = initial(name)
selected_hat.desc = initial(desc)
var/mutable_appearance/hat_adding = mutable_appearance(selected_hat.icon, "[initial(selected_hat.icon_state)]")
hat_adding.pixel_y = ((current_hat * 6) - 1)
hat_adding.pixel_x = (rand(-1, 1))
current_hat++
add_overlay(hat_adding)

add_verb(src, /obj/item/clothing/head/verb/detach_stacked_hat) //Verb for removing hats.

switch(contents.len) //Section for naming/description
if(0)
name = initial(name)
desc = initial(desc)
remove_verb(src, /obj/item/clothing/head/verb/detach_stacked_hat)
if (1,2)
name = "Pile of Hats"
desc = "A meagre pile of hats"
if (3)
name = "Stack of Hats"
desc = "A decent stack of hats"
if(5,6)
name = "Towering Pillar of Hats"
desc = "A magnificent display of pride and wealth"
if(7,8)
name = "A Dangerous Amount of Hats"
desc = "A truly grand tower of hats"
if(9,10)
name = "A Lesser Hatularity"
desc = "A tower approaching unstable levels of hats"
if(11,12,13,14,15)
name = "A Hatularity"
desc = "A tower that has grown far too powerful"
if(16,17,18,19)
name = "A Greater Hatularity"
desc = "A monument to the madness of man"
if(20)
name = "The True Hat Tower"
desc = "<span class='narsiesmall'>AFTER NINE YEARS IN DEVELOPMENT, HOPEFULLY IT WILL HAVE BEEN WORTH THE WAIT</span>"

worn_overlays() //This is where the actual worn icon is generated
user.update_worn_head() //Regenerate the wearer's head appearance so that they have real-time hat updates.


#undef HAT_CAP
#undef ADD_HAT
#undef REMOVE_HAT
43 changes: 41 additions & 2 deletions monkestation/code/modules/datums/brain_damage/mild.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,48 @@
lose_text = "<span class='notice'>You no longer feel the urge to grab things.</span>"

/datum/brain_trauma/mild/kleptomania/on_gain()
owner.apply_status_effect(/datum/brain_trauma/mild/kleptomania)
owner.apply_status_effect(/datum/status_effect/kleptomania)
..()

/datum/brain_trauma/mild/kleptomania/on_lose()
owner.remove_status_effect(/datum/brain_trauma/mild/kleptomania)
owner.remove_status_effect(/datum/status_effect/kleptomania)
..()

/datum/status_effect/kleptomania
id = "kleptomania"
status_type = STATUS_EFFECT_UNIQUE
alert_type = null
var/kleptomania_chance = 2.5

/datum/status_effect/kleptomania/tick()
if(prob(kleptomania_chance) && owner.m_intent == MOVE_INTENT_RUN && !owner.get_active_held_item() && !(owner.incapacitated()) && owner.has_active_hand())
if(prob(25)) //we pick pockets
for(var/mob/living/carbon/human/victim in view(1, owner))
var/pockets = victim.get_pockets()
if(victim != owner && length(pockets))
var/obj/item/I = pick(pockets)
owner.visible_message("<span class='warning'>[owner] attempts to remove [I] from [victim]'s pocket!</span>","<span class='warning'>You attempt to remove [I] from [victim]'s pocket.</span>", FALSE, 1)
if(do_after(owner, victim, I.strip_delay) && victim.temporarilyRemoveItemFromInventory(I))
owner.visible_message("<span class='warning'>[owner] removes [I] from [victim]'s pocket!</span>","<span class='warning'>You remove [I] from [victim]'s pocket.</span>", FALSE, 1)
log_admin("[key_name(usr)] picked [victim.name]'s pockets with Kleptomania trait.")
if(!QDELETED(I) && !owner.putItemFromInventoryInHandIfPossible(I, owner.active_hand_index, TRUE, TRUE))
I.forceMove(owner.drop_location())
break
else
owner.visible_message("<span class='warning'>[owner] fails to pickpocket [victim].</span>","<span class='warning'>You fail to pick [victim]'s pocket.</span>", FALSE, 1)
else //we pick stuff off the ground
var/mob/living/carbon/C = owner
for(var/obj/item/I in oview(1, C))
if(!I.anchored && !(I in C.get_all_gear()) && I.Adjacent(C)) //anything that's not nailed down or worn
I.attack_hand(C)
break

/mob/living/carbon/human/proc/get_pockets()
var/list/pockets = list()
if(l_store)
pockets += l_store
if(r_store)
pockets += r_store
if(s_store)
pockets += s_store
return pockets
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -5128,6 +5128,7 @@
#include "monkestation\code\__HELPERS\mobs.dm"
#include "monkestation\code\modules\client\preferences\species_features\ipc.dm"
#include "monkestation\code\modules\client\preferences\species_features\simians.dm"
#include "monkestation\code\modules\clothing\head\misc.dm"
#include "monkestation\code\modules\clothing\spacesuits\hardsuits\_armor.dm"
#include "monkestation\code\modules\clothing\spacesuits\hardsuits\_hardsuit.dm"
#include "monkestation\code\modules\clothing\spacesuits\hardsuits\_helmet.dm"
Expand Down

0 comments on commit 05a26fb

Please sign in to comment.