diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 6f2515b55d..d323270592 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -275,6 +275,41 @@ BLIND // can't see anything
update_icon(user)
user.update_action_buttons()
+/obj/item/clothing/head/attack_ai(var/mob/user)
+ if(!mob_wear_hat(user))
+ return ..()
+
+/obj/item/clothing/head/attack_generic(var/mob/user)
+ if(!mob_wear_hat(user))
+ return ..()
+
+/obj/item/clothing/head/proc/mob_wear_hat(var/mob/user)
+ if(!Adjacent(user))
+ return 0
+ var/success
+ if(istype(user, /mob/living/silicon/robot/drone))
+ var/mob/living/silicon/robot/drone/D = user
+ if(D.hat)
+ success = 2
+ else
+ D.wear_hat(src)
+ success = 1
+ else if(istype(user, /mob/living/carbon/alien/diona))
+ var/mob/living/carbon/alien/diona/D = user
+ if(D.hat)
+ success = 2
+ else
+ D.wear_hat(src)
+ success = 1
+
+ if(!success)
+ return 0
+ else if(success == 2)
+ user << "You are already wearing a hat."
+ else if(success == 1)
+ user << "You crawl under \the [src]."
+ return 1
+
/obj/item/clothing/head/update_icon(var/mob/user)
overlays.Cut()
diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm
index 26cbefc482..862602bd5c 100644
--- a/code/modules/mob/holder.dm
+++ b/code/modules/mob/holder.dm
@@ -5,10 +5,12 @@
icon = 'icons/obj/objects.dmi'
slot_flags = SLOT_HEAD
sprite_sheets = list("Vox" = 'icons/mob/species/vox/head.dmi')
+ origin_tech = null
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_holder.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_holder.dmi',
)
+ pixel_y = 8
/obj/item/weapon/holder/New()
..()
@@ -31,6 +33,38 @@
qdel(src)
+/obj/item/weapon/holder/proc/sync(var/mob/living/M)
+ dir = 2
+ overlays.Cut()
+ icon = M.icon
+ icon_state = M.icon_state
+ color = M.color
+ name = M.name
+ desc = M.desc
+ overlays |= M.overlays
+ var/mob/living/carbon/human/H = loc
+ if(istype(H))
+ if(H.l_hand == src)
+ H.update_inv_l_hand()
+ else if(H.r_hand == src)
+ H.update_inv_r_hand()
+ else
+ H.regenerate_icons()
+
+//Mob specific holders.
+/obj/item/weapon/holder/diona
+ origin_tech = list(TECH_MAGNET = 3, TECH_BIO = 5)
+ slot_flags = SLOT_HEAD | SLOT_OCLOTHING
+
+/obj/item/weapon/holder/drone
+ origin_tech = list(TECH_MAGNET = 3, TECH_ENGINERING = 5)
+
+/obj/item/weapon/holder/mouse
+ w_class = 1
+
+/obj/item/weapon/holder/borer
+ origin_tech = list(TECH_BIO = 6)
+
/obj/item/weapon/holder/attackby(obj/item/weapon/W as obj, mob/user as mob)
for(var/mob/M in src.contents)
M.attackby(W,user)
@@ -50,72 +84,5 @@
grabber << "You scoop up [src]."
src << "[grabber] scoops you up."
grabber.status_flags |= PASSEMOTES
+ H.sync(src)
return H
-
-//Mob specific holders.
-
-/obj/item/weapon/holder/diona
- name = "diona nymph"
- desc = "It's a tiny plant critter."
- icon_state = "nymph"
- origin_tech = list(TECH_MAGNET = 3, TECH_BIO = 5)
- slot_flags = SLOT_HEAD | SLOT_OCLOTHING
-
-/obj/item/weapon/holder/drone
- name = "maintenance drone"
- desc = "It's a small maintenance robot."
- icon_state = "drone"
- origin_tech = list(TECH_MAGNET = 3, TECH_ENGINERING = 5)
-
-/obj/item/weapon/holder/cat
- name = "cat"
- desc = "It's a cat. Meow."
- icon_state = "cat"
- origin_tech = null
-
-/obj/item/weapon/holder/mouse
- name = "mouse"
- desc = "It's a small rodent."
- icon_state = "mouse_gray"
- origin_tech = null
- w_class = 1
-
-/obj/item/weapon/holder/mouse/gray
- icon_state = "mouse_gray"
-
-/obj/item/weapon/holder/mouse/white
- icon_state = "mouse_white"
-
-/obj/item/weapon/holder/mouse/brown
- icon_state = "mouse_brown"
-
-/obj/item/weapon/holder/borer
- name = "cortical borer"
- desc = "It's a slimy brain slug. Gross."
- icon_state = "borer"
- origin_tech = list(TECH_BIO = 6)
-
-/obj/item/weapon/holder/monkey
- name = "monkey"
- desc = "It's a monkey. Ook."
- icon_state = "monkey"
-
-/obj/item/weapon/holder/monkey/farwa
- name = "farwa"
- desc = "It's a farwa."
- icon_state = "farwa"
-
-/obj/item/weapon/holder/monkey/stok
- name = "stok"
- desc = "It's a stok. stok."
- icon_state = "stok"
-
-/obj/item/weapon/holder/monkey/neaera
- name = "neaera"
- desc = "It's a neaera."
- icon_state = "neara"
-
-/obj/item/weapon/holder/pai
- name = "pAI"
- desc = "It's a little robot."
- icon_state = "pai"
diff --git a/code/modules/mob/living/carbon/alien/diona/diona.dm b/code/modules/mob/living/carbon/alien/diona/diona.dm
index 86dc101eda..95f01a6dff 100644
--- a/code/modules/mob/living/carbon/alien/diona/diona.dm
+++ b/code/modules/mob/living/carbon/alien/diona/diona.dm
@@ -9,6 +9,7 @@
universal_understand = 1
universal_speak = 0 // Dionaea do not need to speak to people other than other dionaea.
holder_type = /obj/item/weapon/holder/diona
+ var/obj/item/hat
/mob/living/carbon/alien/diona/New()
@@ -32,3 +33,10 @@
/mob/living/carbon/alien/diona/put_in_hands(var/obj/item/W) // No hands.
W.loc = get_turf(src)
return 1
+
+/mob/living/carbon/alien/diona/proc/wear_hat(var/obj/item/new_hat)
+ if(hat)
+ return
+ hat = new_hat
+ new_hat.loc = src
+ update_icons()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm
index 956171abf7..45d1f6fe46 100644
--- a/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm
+++ b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm
@@ -6,5 +6,22 @@
return
get_scooped(H)
return
+ else if(H.a_intent == "grab" && hat && !(H.l_hand && H.r_hand))
+ hat.loc = get_turf(src)
+ H.put_in_hands(hat)
+ H.visible_message("\The [H] removes \the [src]'s [hat].")
+ hat = null
+ update_icons()
else
return ..()
+
+/mob/living/carbon/alien/diona/attackby(var/obj/item/weapon/W, var/mob/user)
+ if(user.a_intent == "help" && istype(W, /obj/item/clothing/head))
+ if(hat)
+ user << "\The [src] is already wearing \the [hat]."
+ return
+ user.unEquip(W)
+ wear_hat(W)
+ user.visible_message("\The [user] puts \the [W] on \the [src].")
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/diona/update_icons.dm b/code/modules/mob/living/carbon/alien/diona/update_icons.dm
index b39972cdad..1d694cf624 100644
--- a/code/modules/mob/living/carbon/alien/diona/update_icons.dm
+++ b/code/modules/mob/living/carbon/alien/diona/update_icons.dm
@@ -6,3 +6,7 @@
icon_state = "[initial(icon_state)]_sleep"
else
icon_state = "[initial(icon_state)]"
+
+ overlays.Cut()
+ if(hat)
+ overlays |= get_hat_icon(hat, 0, -8)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species/station/monkey.dm b/code/modules/mob/living/carbon/human/species/station/monkey.dm
index db6c69b409..6ae24db2f6 100644
--- a/code/modules/mob/living/carbon/human/species/station/monkey.dm
+++ b/code/modules/mob/living/carbon/human/species/station/monkey.dm
@@ -37,7 +37,6 @@
bump_flag = MONKEY
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
push_flags = MONKEY|SLIME|SIMPLE_ANIMAL|ALIEN
- var/holder_type = /obj/item/weapon/holder/monkey
/datum/species/monkey/handle_npc(var/mob/living/carbon/human/H)
if(H.stat != CONSCIOUS)
@@ -47,10 +46,6 @@
if(prob(1))
H.emote(pick("scratch","jump","roll","tail"))
-/datum/species/monkey/handle_post_spawn(var/mob/living/carbon/human/H)
- ..()
- H.holder_type = holder_type
-
/datum/species/monkey/get_random_name()
return "[lowertext(name)] ([rand(100,999)])"
@@ -66,7 +61,6 @@
flesh_color = "#AFA59E"
base_color = "#333333"
tail = "farwatail"
- holder_type = /obj/item/weapon/holder/monkey/farwa
/datum/species/monkey/skrell
name = "Neara"
@@ -81,7 +75,6 @@
blood_color = "#1D2CBF"
reagent_tag = IS_SKRELL
tail = null
- holder_type = /obj/item/weapon/holder/monkey/neaera
/datum/species/monkey/unathi
name = "Stok"
@@ -96,4 +89,3 @@
flesh_color = "#34AF10"
base_color = "#066000"
reagent_tag = IS_UNATHI
- holder_type = /obj/item/weapon/holder/monkey/stok
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 65e8c2f278..5e7a6e2d90 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -127,7 +127,8 @@
//this handles hud updates. Calls update_vision() and handle_hud_icons()
/mob/living/handle_regular_hud_updates()
- if(!client) return 0
+ if(!client)
+ return 0
..()
handle_vision()
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index ad06c58d6e..4641c7d2de 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -6,7 +6,6 @@
emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person)
small = 1
pass_flags = 1
- holder_type = /obj/item/weapon/holder/pai
var/network = "SS13"
var/obj/machinery/camera/current = null
@@ -430,4 +429,4 @@
get_scooped(H)
return
else
- return ..()
+ return ..()
diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm
index 04e3728c6a..37c40d7161 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone.dm
@@ -1,3 +1,23 @@
+var/list/mob_hat_cache = list()
+/proc/get_hat_icon(var/obj/item/hat, var/offset_x = 0, var/offset_y = 0)
+ var/t_state = hat.icon_state
+ if(hat.item_state_slots && hat.item_state_slots[slot_head_str])
+ t_state = hat.item_state_slots[slot_head_str]
+ else if(hat.item_state)
+ t_state = hat.item_state
+ var/key = "[t_state]_[offset_x]_[offset_y]"
+ if(!mob_hat_cache[key]) // Not ideal as there's no guarantee all hat icon_states
+ var/t_icon = INV_HEAD_DEF_ICON // are unique across multiple dmis, but whatever.
+ if(hat.icon_override)
+ t_icon = hat.icon_override
+ else if(hat.item_icons && (slot_head_str in hat.item_icons))
+ t_icon = hat.item_icons[slot_head_str]
+ var/image/I = image(icon = t_icon, icon_state = t_state)
+ I.pixel_x = offset_x
+ I.pixel_y = offset_y
+ mob_hat_cache[key] = I
+ return mob_hat_cache[key]
+
/mob/living/silicon/robot/drone
name = "drone"
real_name = "drone"
@@ -29,9 +49,26 @@
var/module_type = /obj/item/weapon/robot_module/drone
var/can_pull_size = 2
var/can_pull_mobs
+ var/obj/item/hat
+ var/hat_x_offset = 0
+ var/hat_y_offset = -13
holder_type = /obj/item/weapon/holder/drone
+/mob/living/silicon/robot/drone/Destroy()
+ if(hat)
+ hat.loc = get_turf(src)
+ ..()
+
+/mob/living/silicon/robot/drone/construction
+ icon_state = "constructiondrone"
+ law_type = /datum/ai_laws/construction_drone
+ module_type = /obj/item/weapon/robot_module/drone/construction
+ can_pull_size = 5
+ can_pull_mobs = 1
+ hat_x_offset = 1
+ hat_y_offset = -12
+
/mob/living/silicon/robot/drone/New()
..()
@@ -82,6 +119,8 @@
overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
+ if(hat) // Let the drones wear hats.
+ overlays |= get_hat_icon(hat, hat_x_offset, hat_y_offset)
/mob/living/silicon/robot/drone/choose_icon()
return
@@ -89,10 +128,25 @@
/mob/living/silicon/robot/drone/pick_module()
return
-//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
-/mob/living/silicon/robot/drone/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/mob/living/silicon/robot/drone/proc/wear_hat(var/obj/item/new_hat)
+ if(hat)
+ return
+ hat = new_hat
+ new_hat.loc = src
+ updateicon()
- if(istype(W, /obj/item/borg/upgrade/))
+//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
+/mob/living/silicon/robot/drone/attackby(var/obj/item/weapon/W, var/mob/user)
+
+ if(user.a_intent == "help" && istype(W, /obj/item/clothing/head))
+ if(hat)
+ user << "\The [src] is already wearing \the [hat]."
+ return
+ user.unEquip(W)
+ wear_hat(W)
+ user.visible_message("\The [user] puts \the [W] on \the [src].")
+ return
+ else if(istype(W, /obj/item/borg/upgrade/))
user << "\The [src] is not compatible with \the [W]."
return
@@ -135,7 +189,7 @@
return
..()
-
+
/mob/living/silicon/robot/drone/emag_act(var/remaining_charges, var/mob/user)
if(!client || stat == 2)
user << "There's not much point subverting this heap of junk."
@@ -279,13 +333,6 @@
/mob/living/silicon/robot/drone/remove_robot_verbs()
src.verbs -= silicon_subsystems
-/mob/living/silicon/robot/drone/construction
- icon_state = "constructiondrone"
- law_type = /datum/ai_laws/construction_drone
- module_type = /obj/item/weapon/robot_module/drone/construction
- can_pull_size = 5
- can_pull_mobs = 1
-
/mob/living/silicon/robot/drone/construction/welcome_drone()
src << "You are a construction drone, an autonomous engineering and fabrication system.."
src << "You are assigned to a Sol Central construction project. The name is irrelevant. Your task is to complete construction and subsystem integration as soon as possible."
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm
index 0eaf1c8779..e5aa936a08 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm
@@ -10,13 +10,13 @@
mail_destination = ""
return
- src << "\blue You configure your internal beacon, tagging yourself for delivery to '[new_tag]'."
+ src << "You configure your internal beacon, tagging yourself for delivery to '[new_tag]'."
mail_destination = new_tag
//Auto flush if we use this verb inside a disposal chute.
var/obj/machinery/disposal/D = src.loc
if(istype(D))
- src << "\blue \The [D] acknowledges your signal."
+ src << "\The [D] acknowledges your signal."
D.flush_count = D.flush_every_ticks
return
@@ -27,5 +27,11 @@
if(H.a_intent == "help")
get_scooped(H)
return
+ else if(H.a_intent == "grab" && hat && !(H.l_hand && H.r_hand))
+ hat.loc = get_turf(src)
+ H.put_in_hands(hat)
+ H.visible_message("\The [H] removes \the [src]'s [hat].")
+ hat = null
+ updateicon()
else
return ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
index a292ead1b1..171fc29933 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
@@ -78,7 +78,8 @@
flick("h_lathe_leave",src)
time_last_drone = world.time
- var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src))
+ if(player.mob && player.mob.mind) player.mob.mind.reset()
+ var/mob/living/silicon/robot/drone/new_drone = PoolOrNew(drone_type, get_turf(src))
new_drone.transfer_personality(player)
new_drone.master_fabricator = src
@@ -90,7 +91,6 @@
set name = "Join As Drone"
set desc = "If there is a powered, enabled fabricator in the game world with a prepared chassis, join as a maintenance drone."
-
if(ticker.current_state < GAME_STATE_PLAYING)
src << "The game hasn't started yet!"
return
@@ -108,17 +108,11 @@
if(jobban_isbanned(src,"Cyborg"))
usr << "You are banned from playing synthetics and cannot spawn as a drone."
return
-
+
if(!MayRespawn(1))
return
var/deathtime = world.time - src.timeofdeath
- if(istype(src,/mob/dead/observer))
- var/mob/dead/observer/G = src
- if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
- usr << "Upon using the antagHUD you forfeighted the ability to join the round."
- return
-
var/deathtimeminutes = round(deathtime / 600)
var/pluralcheck = "minute"
if(deathtimeminutes == 0)
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 70f7282b8e..e0ffc718ff 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -63,13 +63,6 @@
if(!body_color)
body_color = pick( list("brown","gray","white") )
- switch(body_color)
- if("brown")
- holder_type = /obj/item/weapon/holder/mouse/brown
- if("gray")
- holder_type = /obj/item/weapon/holder/mouse/gray
- if("white")
- holder_type = /obj/item/weapon/holder/mouse/white
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
@@ -125,17 +118,14 @@
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
- holder_type = /obj/item/weapon/holder/mouse/white
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
- holder_type = /obj/item/weapon/holder/mouse/gray
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
- holder_type = /obj/item/weapon/holder/mouse/brown
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
diff --git a/html/changelogs/Zuhayr-dronehats.yml b/html/changelogs/Zuhayr-dronehats.yml
new file mode 100644
index 0000000000..06dc80786d
--- /dev/null
+++ b/html/changelogs/Zuhayr-dronehats.yml
@@ -0,0 +1,4 @@
+author: Zuhayr
+delete-after: True
+changes:
+ - rscadd: "Click a hat on a drone with help intent to equip it. Drag the drone onto yourself with grab intent to remove it."
diff --git a/icons/mob/alien.dmi b/icons/mob/alien.dmi
index 362dcc96ea..171abcf1c0 100644
Binary files a/icons/mob/alien.dmi and b/icons/mob/alien.dmi differ