diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index ba151bb74de..6afa76a02b0 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -164,4 +164,5 @@
#define CAN_WINGDINGS 19
#define NOZOMBIE 20
#define NO_GERMS 21
-#define NO_DECAY 22
\ No newline at end of file
+#define NO_DECAY 22
+#define PIERCEIMMUNE 23
\ No newline at end of file
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index e93b3b121e6..d06069b43a4 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -211,3 +211,6 @@
to_chat(usr, "Switched HUD mode. Press F12 to toggle.")
else
to_chat(usr, "This mob type does not use a HUD.")
+
+/datum/hud/proc/update_locked_slots()
+ return
\ No newline at end of file
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 811a7e89cdb..0a6680b3ba4 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -383,6 +383,28 @@
inv_slots[inv.slot_id] = inv
inv.update_icon()
+ update_locked_slots()
+
+/datum/hud/human/update_locked_slots()
+ if(!mymob)
+ return
+ var/mob/living/carbon/human/H = mymob
+ if(!istype(H) || !H.dna.species)
+ return
+ var/datum/species/S = H.dna.species
+ for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+ if(inv.slot_id)
+ if(inv.slot_id in S.no_equip)
+ inv.alpha = 128
+ else
+ inv.alpha = initial(inv.alpha)
+ for(var/obj/screen/craft/crafting in static_inventory)
+ if(!S.can_craft)
+ crafting.invisibility = INVISIBILITY_ABSTRACT
+ H.handcrafting.close(H)
+ else
+ crafting.invisibility = initial(crafting.invisibility)
+
/datum/hud/human/hidden_inventory_update()
if(!mymob)
return
diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm
deleted file mode 100644
index 6541c5bfdab..00000000000
--- a/code/_onclick/hud/monkey.dm
+++ /dev/null
@@ -1,134 +0,0 @@
-/mob/living/carbon/human/monkey/create_mob_hud()
- if(client && !hud_used)
- hud_used = new /datum/hud/monkey(src, ui_style2icon(client.prefs.UI_style), client.prefs.UI_style_color, client.prefs.UI_style_alpha)
-
-/datum/hud/monkey/New(mob/living/carbon/human/owner, var/ui_style = 'icons/mob/screen_white.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255)
- ..()
-
- var/obj/screen/using
- var/obj/screen/inventory/inv_box
-
- using = new /obj/screen/act_intent()
- using.icon_state = mymob.a_intent
- using.color = ui_color
- using.alpha = ui_alpha
- static_inventory += using
- action_intent = using
-
- using = new /obj/screen/mov_intent()
- using.icon = ui_style
- using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
- using.screen_loc = ui_movi
- using.color = ui_color
- using.alpha = ui_alpha
- static_inventory += using
- move_intent = using
-
- using = new /obj/screen/language_menu
- using.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- static_inventory += using
-
- using = new /obj/screen/drop()
- using.icon = ui_style
- using.screen_loc = ui_drop_throw
- using.color = ui_color
- using.alpha = ui_alpha
- static_inventory += using
-
- inv_box = new /obj/screen/inventory/hand()
- inv_box.name = "r_hand"
- inv_box.icon = ui_style
- inv_box.icon_state = "hand_r"
- inv_box.color = ui_color
- inv_box.alpha = ui_alpha
- inv_box.screen_loc = ui_rhand
- inv_box.slot_id = slot_r_hand
- static_inventory += inv_box
-
- inv_box = new /obj/screen/inventory/hand()
- inv_box.name = "l_hand"
- inv_box.icon = ui_style
- inv_box.icon_state = "hand_l"
- inv_box.color = ui_color
- inv_box.alpha = ui_alpha
- inv_box.screen_loc = ui_lhand
- inv_box.slot_id = slot_l_hand
- static_inventory += inv_box
-
- using = new /obj/screen/swap_hand()
- using.name = "hand"
- using.icon = ui_style
- using.icon_state = "swap_1_m"
- using.screen_loc = ui_swaphand1
- using.color = ui_color
- using.alpha = ui_alpha
- static_inventory += using
-
- using = new /obj/screen/swap_hand()
- using.name = "hand"
- using.icon = ui_style
- using.icon_state = "swap_2"
- using.screen_loc = ui_swaphand2
- using.color = ui_color
- using.alpha = ui_alpha
- static_inventory += using
-
- inv_box = new /obj/screen/inventory()
- inv_box.name = "mask"
- inv_box.icon = ui_style
- inv_box.icon_state = "mask"
- inv_box.screen_loc = ui_mask
- inv_box.slot_id = slot_wear_mask
- inv_box.color = ui_color
- inv_box.alpha = ui_alpha
- toggleable_inventory += inv_box
-
- inv_box = new /obj/screen/inventory()
- inv_box.name = "back"
- inv_box.icon = ui_style
- inv_box.icon_state = "back"
- inv_box.screen_loc = ui_back
- inv_box.slot_id = slot_back
- inv_box.color = ui_color
- inv_box.alpha = ui_alpha
- static_inventory += inv_box
-
- mymob.throw_icon = new /obj/screen/throw_catch()
- mymob.throw_icon.icon = ui_style
- mymob.throw_icon.screen_loc = ui_drop_throw
- mymob.throw_icon.color = ui_color
- mymob.throw_icon.alpha = ui_alpha
- hotkeybuttons += mymob.throw_icon
-
- mymob.healths = new /obj/screen/healths()
- infodisplay += mymob.healths
-
- mymob.healthdoll = new()
- infodisplay += mymob.healthdoll
-
- mymob.pullin = new /obj/screen/pull()
- mymob.pullin.icon = ui_style
- mymob.pullin.update_icon(mymob)
- mymob.pullin.screen_loc = ui_pull_resist
- static_inventory += mymob.pullin
-
- lingchemdisplay = new /obj/screen/ling/chems()
- infodisplay += lingchemdisplay
-
- lingstingdisplay = new /obj/screen/ling/sting()
- infodisplay += lingstingdisplay
-
- mymob.zone_sel = new /obj/screen/zone_sel()
- mymob.zone_sel.icon = ui_style
- mymob.zone_sel.update_icon(mymob)
- static_inventory += mymob.zone_sel
-
- inventory_shown = 0
-
- for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
- if(inv.slot_id)
- inv.hud = src
- inv_slots[inv.slot_id] = inv
- inv.update_icon()
diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm
new file mode 100644
index 00000000000..63c6110aa5d
--- /dev/null
+++ b/code/datums/components/caltrop.dm
@@ -0,0 +1,59 @@
+/datum/component/caltrop
+ var/min_damage
+ var/max_damage
+ var/probability
+ var/flags
+
+ var/cooldown = 0
+
+/datum/component/caltrop/Initialize(_min_damage = 0, _max_damage = 0, _probability = 100, _flags = NONE)
+ min_damage = _min_damage
+ max_damage = max(_min_damage, _max_damage)
+ probability = _probability
+ flags = _flags
+
+ RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED), .proc/Crossed)
+
+/datum/component/caltrop/proc/Crossed(datum/source, atom/movable/AM)
+ var/atom/A = parent
+ if(!has_gravity(A))
+ return
+
+ if(!prob(probability))
+ return
+
+ if(ishuman(AM))
+ var/mob/living/carbon/human/H = AM
+ if(PIERCEIMMUNE in H.dna.species.species_traits)
+ return
+
+ if((flags & CALTROP_IGNORE_WALKERS) && H.m_intent == MOVE_INTENT_WALK)
+ return
+
+ var/picked_def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
+ var/obj/item/organ/external/O = H.get_organ(picked_def_zone)
+ if(!istype(O))
+ return
+ if(O.is_robotic())
+ return
+
+ var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET))
+
+ if(!(flags & CALTROP_BYPASS_SHOES) && (H.shoes || feetCover))
+ return
+
+ if((H.flying) || H.buckled)
+ return
+
+ var/damage = rand(min_damage, max_damage)
+
+ H.apply_damage(damage, BRUTE, picked_def_zone)
+
+ if(cooldown < world.time - 10) //cooldown to avoid message spam.
+ if(!H.incapacitated(ignore_restraints = TRUE))
+ H.visible_message("[H] steps on [A].", "You step on [A]!")
+ else
+ H.visible_message("[H] slides on [A]!", "You slide on [A]!")
+
+ cooldown = world.time
+ H.Weaken(3)
\ No newline at end of file
diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm
index d0c32b19620..97b5eff3be2 100644
--- a/code/game/dna/genes/monkey.dm
+++ b/code/game/dna/genes/monkey.dm
@@ -38,12 +38,6 @@
H.gib()
return
- QDEL_NULL(H.hud_used)
-
- if(H.client)
- H.hud_used = new /datum/hud/monkey(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha)
- H.hud_used.show_hud(H.hud_used.hud_version)
-
to_chat(H, "You are now a [H.dna.species.name].")
return H
@@ -83,12 +77,6 @@
H.real_name = H.dna.real_name
H.name = H.real_name
- QDEL_NULL(H.hud_used)
-
- if(H.client)
- H.hud_used = new /datum/hud/human(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha)
- H.hud_used.show_hud(H.hud_used.hud_version)
-
to_chat(H, "You are now a [H.dna.species.name].")
- return H
+ return H
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index 736ba1cc767..c480d8f450c 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -72,6 +72,10 @@
icon_state = "d4"
sides = 4
+/obj/item/dice/d4/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/caltrop, 1, 4) //1d4 damage
+
/obj/item/dice/d6
name = "d6"
diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm
index e2fc07712bf..3e04ad3a440 100644
--- a/code/game/objects/items/weapons/shards.dm
+++ b/code/game/objects/items/weapons/shards.dm
@@ -25,6 +25,7 @@
/obj/item/shard/Initialize(mapload)
. = ..()
+ AddComponent(/datum/component/caltrop, force)
icon_state = pick("large", "medium", "small")
switch(icon_state)
if("small")
@@ -48,7 +49,7 @@
return
if(ishuman(user))
var/mob/living/carbon/human/H = user
- if(!H.gloves)
+ if(!H.gloves && !(PIERCEIMMUNE in H.dna.species.species_traits))
var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
if(affecting.is_robotic())
return
@@ -82,29 +83,6 @@
if(L.incorporeal_move || L.flying)
return
playsound(loc, 'sound/effects/glass_step.ogg', 50, TRUE)
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- var/obj/item/organ/external/affecting = H.get_organ(pick("l_foot", "r_foot"))
- if(!affecting)
- return
- if(affecting.is_robotic())
- return
- var/feetCover = (H.wear_suit && H.wear_suit.body_parts_covered & FEET) || (H.w_uniform && H.w_uniform.body_parts_covered & FEET)
- if(H.shoes || feetCover || H.buckled)
- return
- if(affecting.receive_damage(force, 0))
- H.UpdateDamageIcon()
-
- if(cooldown < world.time - 10) //cooldown to avoid message spam.
- if(!H.incapacitated(ignore_restraints = TRUE))
- H.visible_message("[H] steps on [src]!", \
- "You step on [src]!")
- else
- H.visible_message("[H] slides on [src]!", \
- "You slide on [src]!")
-
- cooldown = world.time
- H.Weaken(3)
return ..()
/obj/item/shard/plasma
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index c2428dd8d97..ded21767fe6 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -6,6 +6,7 @@
animate_movement = 2
var/throwforce = 1
var/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
+ var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
var/sharp = 0 // whether this object cuts
var/in_use = 0 // If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
var/can_deconstruct = TRUE
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index 258212f0ab6..3610ec8b451 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -37,12 +37,18 @@
if(holder)
holder.update_icon()
-/obj/item/assembly/mousetrap/proc/triggered(mob/target, var/type = "feet")
+/obj/item/assembly/mousetrap/proc/triggered(mob/target, type = "feet")
if(!armed)
return
var/obj/item/organ/external/affecting = null
if(ishuman(target))
var/mob/living/carbon/human/H = target
+ if(PIERCEIMMUNE in H.dna.species.species_traits)
+ playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
+ armed = FALSE
+ update_icon()
+ pulse(FALSE)
+ return FALSE
switch(type)
if("feet")
if(!H.shoes)
diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm
index 77a4076347d..c31e1abf4b5 100644
--- a/code/modules/clothing/gloves/boxing.dm
+++ b/code/modules/clothing/gloves/boxing.dm
@@ -4,6 +4,7 @@
icon_state = "boxing"
item_state = "boxing"
put_on_delay = 60
+ species_exception = list(/datum/species/golem) // now you too can be a golem boxing champion
/obj/item/clothing/gloves/boxing/green
icon_state = "boxinggreen"
diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm
index f3759a67786..9b7f78f709d 100644
--- a/code/modules/clothing/suits/labcoat.dm
+++ b/code/modules/clothing/suits/labcoat.dm
@@ -9,7 +9,7 @@
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
allowed = list(/obj/item/analyzer,/obj/item/stack/medical,/obj/item/dnainjector,/obj/item/reagent_containers/dropper,/obj/item/reagent_containers/syringe,/obj/item/reagent_containers/hypospray,/obj/item/healthanalyzer,/obj/item/flashlight/pen,/obj/item/reagent_containers/glass/bottle,/obj/item/reagent_containers/glass/beaker,/obj/item/reagent_containers/food/pill,/obj/item/storage/pill_bottle,/obj/item/paper,/obj/item/rad_laser)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 50, rad = 0)
-
+ species_exception = list(/datum/species/golem)
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi',
"Grey" = 'icons/mob/species/grey/suit.dmi'
diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm
index e05e31c297f..aaed5f5672c 100644
--- a/code/modules/crafting/craft.dm
+++ b/code/modules/crafting/craft.dm
@@ -266,6 +266,10 @@
ui = new(user, src, ui_key, "personal_crafting.tmpl", "Crafting Menu", 700, 800, state = state)
ui.open()
+/datum/personal_crafting/proc/close(mob/user)
+ var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
+ ui.close()
+
/datum/personal_crafting/ui_data(mob/user)
var/list/data = list()
var/list/subs = list()
diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm
index 444939ca861..cfb02987201 100644
--- a/code/modules/hydroponics/grown/nettle.dm
+++ b/code/modules/hydroponics/grown/nettle.dm
@@ -50,10 +50,12 @@
/obj/item/grown/nettle/pickup(mob/living/user)
..()
if(!ishuman(user))
- return TRUE
+ return FALSE
var/mob/living/carbon/human/H = user
if(H.gloves)
- return TRUE
+ return FALSE
+ if(PIERCEIMMUNE in H.dna.species.species_traits)
+ return FALSE
var/organ = ((H.hand ? "l_":"r_") + "arm")
var/obj/item/organ/external/affecting = H.get_organ(organ)
if(affecting)
diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm
index 46df9ddfd9b..af0006edafc 100644
--- a/code/modules/mining/lavaland/ash_flora.dm
+++ b/code/modules/mining/lavaland/ash_flora.dm
@@ -149,18 +149,10 @@
regrowth_time_low = 4800
regrowth_time_high = 7200
-/obj/structure/flora/ash/cacti/Crossed(mob/AM, oldloc)
- if(ishuman(AM) && has_gravity(loc) && prob(70))
- var/mob/living/carbon/human/H = AM
- if(!H.shoes && !H.lying) //ouch, my feet.
- var/picked_def_zone = pick("l_leg", "r_leg")
- var/obj/item/organ/external/affected = H.get_organ(picked_def_zone)
- if(!istype(affected))
- return
- H.apply_damage(rand(3, 6), BRUTE, picked_def_zone)
- H.Weaken(2)
- H.visible_message("[H] steps on a cactus!", \
- "You step on a cactus!")
+/obj/structure/flora/ash/cacti/Initialize(mapload)
+ . = ..()
+ // min dmg 3, max dmg 6, prob(70)
+ AddComponent(/datum/component/caltrop, 3, 6, 70)
/obj/item/reagent_containers/food/snacks/grown/ash_flora
name = "mushroom shavings"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 36e1589989f..0a860b6019f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -406,7 +406,7 @@
else
dat += "
| Uniform: | [(w_uniform && !(w_uniform.flags&ABSTRACT)) ? w_uniform : "Empty"] |
"
- if(w_uniform == null || (slot_w_uniform in obscured))
+ if((w_uniform == null && !(dna && dna.species.nojumpsuit)) || (slot_w_uniform in obscured))
dat += "| ↳Pockets: |
"
dat += "| ↳ID: |
"
dat += "| ↳Belt: |
"
@@ -1015,6 +1015,10 @@
else
target_zone = user.zone_sel.selecting
+
+ if(PIERCEIMMUNE in dna.species.species_traits)
+ . = 0
+
var/obj/item/organ/external/affecting = get_organ(target_zone)
var/fail_msg
if(!affecting)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 73147afb93a..87bc491f4ab 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -318,7 +318,7 @@ emp_act
else if(I)
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD)
if(can_embed(I))
- if(prob(I.embed_chance))
+ if(prob(I.embed_chance) && !(PIERCEIMMUNE in dna.species.species_traits))
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/organ/external/L = pick(bodyparts)
L.embedded_objects |= I
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 380d2bcf236..f0d4a3e9a79 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -411,148 +411,8 @@
..(what, who, where, silent = is_silent)
-/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0)
- switch(dna.species.handle_can_equip(I, slot, disable_warning, src))
- if(1) return TRUE
- if(2) return FALSE //if it returns 2, it wants no normal handling
- if(!has_organ_for_slot(slot))
- return FALSE
-
- if(istype(I, /obj/item/clothing/under) || istype(I, /obj/item/clothing/suit))
- if(FAT in mutations)
- //testing("[M] TOO FAT TO WEAR [src]!")
- if(!(I.flags_size & ONESIZEFITSALL))
- if(!disable_warning)
- to_chat(src, "You're too fat to wear the [I].")
- return FALSE
-
- switch(slot)
- if(slot_l_hand)
- return !l_hand && !incapacitated()
- if(slot_r_hand)
- return !r_hand && !incapacitated()
- if(slot_wear_mask)
- return !wear_mask && (I.slot_flags & SLOT_MASK)
- if(slot_back)
- return !back && (I.slot_flags & SLOT_BACK)
- if(slot_wear_suit)
- return !wear_suit && (I.slot_flags & SLOT_OCLOTHING)
- if(slot_gloves)
- return !gloves && (I.slot_flags & SLOT_GLOVES)
- if(slot_shoes)
- return !shoes && (I.slot_flags & SLOT_FEET)
- if(slot_belt)
- if(belt)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- to_chat(src, "You need a jumpsuit before you can attach this [name].")
- return 0
- if(!(I.slot_flags & SLOT_BELT))
- return
- return 1
- if(slot_glasses)
- return !glasses && (I.slot_flags & SLOT_EYES)
- if(slot_head)
- return !head && (I.slot_flags & SLOT_HEAD)
- if(slot_l_ear)
- return !l_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && r_ear)
- if(slot_r_ear)
- return !r_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && l_ear)
- if(slot_w_uniform)
- return !w_uniform && (I.slot_flags & SLOT_ICLOTHING)
- if(slot_wear_id)
- if(wear_id)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- to_chat(src, "You need a jumpsuit before you can attach this [name].")
- return 0
- if(!(I.slot_flags & SLOT_ID))
- return 0
- return 1
- if(slot_wear_pda)
- if(wear_pda)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- to_chat(src, "You need a jumpsuit before you can attach this [name].")
- return 0
- if(!(I.slot_flags & SLOT_PDA))
- return 0
- return 1
- if(slot_l_store)
- if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them.
- return 0
- if(l_store)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- to_chat(src, "You need a jumpsuit before you can attach this [name].")
- return 0
- if(I.slot_flags & SLOT_DENYPOCKET)
- return
- if(I.w_class <= WEIGHT_CLASS_SMALL || (I.slot_flags & SLOT_POCKET))
- return 1
- if(slot_r_store)
- if(I.flags & NODROP)
- return 0
- if(r_store)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- to_chat(src, "You need a jumpsuit before you can attach this [name].")
- return 0
- if(I.slot_flags & SLOT_DENYPOCKET)
- return 0
- if(I.w_class <= WEIGHT_CLASS_SMALL || (I.slot_flags & SLOT_POCKET))
- return 1
- return 0
- if(slot_s_store)
- if(I.flags & NODROP) //Suit storage NODROP items drop if you take a suit off, this is to prevent people exploiting this.
- return 0
- if(s_store)
- return 0
- if(!wear_suit)
- if(!disable_warning)
- to_chat(src, "You need a suit before you can attach this [name].")
- return 0
- if(!wear_suit.allowed)
- if(!disable_warning)
- to_chat(src, "You somehow have a suit with no defined allowed items for suit storage, stop that.")
- return 0
- if(I.w_class > WEIGHT_CLASS_BULKY)
- if(!disable_warning)
- to_chat(src, "The [name] is too big to attach.")
- return 0
- if(istype(I, /obj/item/pda) || istype(I, /obj/item/pen) || is_type_in_list(I, wear_suit.allowed))
- return 1
- return 0
- if(slot_handcuffed)
- return !handcuffed && istype(I, /obj/item/restraints/handcuffs)
- if(slot_legcuffed)
- return !legcuffed && istype(I, /obj/item/restraints/legcuffs)
- if(slot_in_backpack)
- if(back && istype(back, /obj/item/storage/backpack))
- var/obj/item/storage/backpack/B = back
- if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class)
- return 1
- return 0
- if(slot_tie)
- if(!w_uniform)
- if(!disable_warning)
- to_chat(src, "You need a jumpsuit before you can attach this [name].")
- return 0
- var/obj/item/clothing/under/uniform = w_uniform
- if(uniform.accessories.len && !uniform.can_attach_accessory(src))
- if(!disable_warning)
- to_chat(src, "You already have an accessory of this type attached to your [uniform].")
- return 0
- if(!(I.slot_flags & SLOT_TIE))
- return 0
- return 1
-
- return 0 //Unsupported slot
+/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE)
+ return dna.species.can_equip(I, slot, disable_warning, src)
/mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE)
var/datum/outfit/O = null
diff --git a/code/modules/mob/living/carbon/human/npcs.dm b/code/modules/mob/living/carbon/human/npcs.dm
index c21c1990cbe..41c108dadb9 100644
--- a/code/modules/mob/living/carbon/human/npcs.dm
+++ b/code/modules/mob/living/carbon/human/npcs.dm
@@ -4,6 +4,7 @@
icon_state = "punpun"
item_color = "punpun"
species_restricted = list("Monkey")
+ species_exception = list(/datum/species/monkey)
/mob/living/carbon/human/monkey/punpun/Initialize(mapload)
..()
diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm
index b658124bb8f..10b23dcfc82 100644
--- a/code/modules/mob/living/carbon/human/species/_species.dm
+++ b/code/modules/mob/living/carbon/human/species/_species.dm
@@ -53,7 +53,6 @@
var/stamina_mod = 1
var/stun_mod = 1 // If a species is more/less impacated by stuns/weakens/paralysis
var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
- var/armor = 0 // overall defense for the race... or less defense, if it's negative.
var/blood_damage_type = OXY //What type of damage does this species take if it's low on blood?
var/obj/item/mutanthands
var/total_health = 100
@@ -74,6 +73,10 @@
var/clothing_flags = 0 // Underwear and socks.
var/exotic_blood
var/skinned_type
+ var/list/no_equip = list() // slots the race can't equip stuff to
+ var/nojumpsuit = 0 // this is sorta... weird. it basically lets you equip stuff that usually needs jumpsuits without one, like belts and pockets and ids
+ var/can_craft = TRUE // Can this mob using crafting or not?
+
var/bodyflags = 0
var/dietflags = 0 // Make sure you set this, otherwise it won't be able to digest a lot of foods
@@ -271,7 +274,12 @@
return .
/datum/species/proc/on_species_gain(mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment.
- return
+ for(var/slot_id in no_equip)
+ var/obj/item/thing = H.get_item_by_slot(slot_id)
+ if(thing && (!thing.species_exception || !is_type_in_list(src, thing.species_exception)))
+ H.unEquip(thing)
+ if(H.hud_used)
+ H.hud_used.update_locked_slots()
/datum/species/proc/on_species_loss(mob/living/carbon/human/H)
if(H.butcher_results) //clear it out so we don't butcher a actual human.
@@ -585,8 +593,158 @@
attack_verb = list("slash", "claw")
damage = 6
-/datum/species/proc/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user)
- return FALSE
+/datum/species/proc/can_equip(obj/item/I, slot, disable_warning = FALSE, mob/living/carbon/human/H)
+ if(slot in no_equip)
+ if(!I.species_exception || !is_type_in_list(src, I.species_exception))
+ return FALSE
+
+ if(!H.has_organ_for_slot(slot))
+ return FALSE
+
+ if(istype(I, /obj/item/clothing/under) || istype(I, /obj/item/clothing/suit))
+ if(FAT in H.mutations)
+ if(!(I.flags_size & ONESIZEFITSALL))
+ if(!disable_warning)
+ to_chat(H, "You're too fat to wear the [I].")
+ return FALSE
+
+ switch(slot)
+ if(slot_l_hand)
+ return !H.l_hand && !H.incapacitated()
+ if(slot_r_hand)
+ return !H.r_hand && !H.incapacitated()
+ if(slot_wear_mask)
+ return !H.wear_mask && (I.slot_flags & SLOT_MASK)
+ if(slot_back)
+ return !H.back && (I.slot_flags & SLOT_BACK)
+ if(slot_wear_suit)
+ return !H.wear_suit && (I.slot_flags & SLOT_OCLOTHING)
+ if(slot_gloves)
+ return !H.gloves && (I.slot_flags & SLOT_GLOVES)
+ if(slot_shoes)
+ return !H.shoes && (I.slot_flags & SLOT_FEET)
+ if(slot_belt)
+ if(H.belt)
+ return FALSE
+ var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_CHEST)
+
+ if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
+ if(!disable_warning)
+ to_chat(H, "You need a jumpsuit before you can attach this [name].")
+ return FALSE
+ if(!(I.slot_flags & SLOT_BELT))
+ return
+ return TRUE
+ if(slot_glasses)
+ return !H.glasses && (I.slot_flags & SLOT_EYES)
+ if(slot_head)
+ return !H.head && (I.slot_flags & SLOT_HEAD)
+ if(slot_l_ear)
+ return !H.l_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && H.r_ear)
+ if(slot_r_ear)
+ return !H.r_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && H.l_ear)
+ if(slot_w_uniform)
+ return !H.w_uniform && (I.slot_flags & SLOT_ICLOTHING)
+ if(slot_wear_id)
+ if(H.wear_id)
+ return FALSE
+ var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_CHEST)
+
+ if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
+ if(!disable_warning)
+ to_chat(H, "You need a jumpsuit before you can attach this [name].")
+ return FALSE
+ if(!(I.slot_flags & SLOT_ID))
+ return FALSE
+ return TRUE
+ if(slot_wear_pda)
+ if(H.wear_pda)
+ return FALSE
+ var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_CHEST)
+
+ if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
+ if(!disable_warning)
+ to_chat(H, "You need a jumpsuit before you can attach this [name].")
+ return FALSE
+ if(!(I.slot_flags & SLOT_PDA))
+ return FALSE
+ return TRUE
+ if(slot_l_store)
+ if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them.
+ return FALSE
+ if(H.l_store)
+ return FALSE
+ var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_L_LEG)
+
+ if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
+ if(!disable_warning)
+ to_chat(H, "You need a jumpsuit before you can attach this [name].")
+ return FALSE
+ if(I.slot_flags & SLOT_DENYPOCKET)
+ return
+ if(I.w_class <= WEIGHT_CLASS_SMALL || (I.slot_flags & SLOT_POCKET))
+ return TRUE
+ if(slot_r_store)
+ if(I.flags & NODROP)
+ return FALSE
+ if(H.r_store)
+ return FALSE
+ var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_R_LEG)
+
+ if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
+ if(!disable_warning)
+ to_chat(H, "You need a jumpsuit before you can attach this [name].")
+ return FALSE
+ if(I.slot_flags & SLOT_DENYPOCKET)
+ return FALSE
+ if(I.w_class <= WEIGHT_CLASS_SMALL || (I.slot_flags & SLOT_POCKET))
+ return TRUE
+ return FALSE
+ if(slot_s_store)
+ if(I.flags & NODROP) //Suit storage NODROP items drop if you take a suit off, this is to prevent people exploiting this.
+ return FALSE
+ if(H.s_store)
+ return FALSE
+ if(!H.wear_suit)
+ if(!disable_warning)
+ to_chat(H, "You need a suit before you can attach this [name].")
+ return FALSE
+ if(!H.wear_suit.allowed)
+ if(!disable_warning)
+ to_chat(H, "You somehow have a suit with no defined allowed items for suit storage, stop that.")
+ return FALSE
+ if(I.w_class > WEIGHT_CLASS_BULKY)
+ if(!disable_warning)
+ to_chat(H, "The [name] is too big to attach.")
+ return FALSE
+ if(istype(I, /obj/item/pda) || istype(I, /obj/item/pen) || is_type_in_list(I, H.wear_suit.allowed))
+ return TRUE
+ return FALSE
+ if(slot_handcuffed)
+ return !H.handcuffed && istype(I, /obj/item/restraints/handcuffs)
+ if(slot_legcuffed)
+ return !H.legcuffed && istype(I, /obj/item/restraints/legcuffs)
+ if(slot_in_backpack)
+ if(H.back && istype(H.back, /obj/item/storage/backpack))
+ var/obj/item/storage/backpack/B = H.back
+ if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class)
+ return TRUE
+ return FALSE
+ if(slot_tie)
+ if(!H.w_uniform)
+ if(!disable_warning)
+ to_chat(H, "You need a jumpsuit before you can attach this [name].")
+ return FALSE
+ var/obj/item/clothing/under/uniform = H.w_uniform
+ if(uniform.accessories.len && !uniform.can_attach_accessory(H))
+ if(!disable_warning)
+ to_chat(H, "You already have an accessory of this type attached to your [uniform].")
+ return FALSE
+ if(!(I.slot_flags & SLOT_TIE))
+ return FALSE
+ return TRUE
+
+ return FALSE //Unsupported slot
/datum/species/proc/get_perceived_trauma(mob/living/carbon/human/H)
return H.health - H.getStaminaLoss()
diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm
index 81211b1c4b9..e8451d61cbb 100644
--- a/code/modules/mob/living/carbon/human/species/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/golem.dm
@@ -5,37 +5,41 @@
icobase = 'icons/mob/human_races/r_golem.dmi'
deform = 'icons/mob/human_races/r_golem.dmi'
- species_traits = list(NO_BREATHE, NO_BLOOD, NO_PAIN, RADIMMUNE, VIRUSIMMUNE, NOGUNS)
+ species_traits = list(NO_BREATHE, NO_BLOOD, NO_PAIN, RADIMMUNE, NOGUNS, PIERCEIMMUNE)
dies_at_threshold = TRUE
+ slowdown = 2
brute_mod = 0.45 //55% damage reduction
burn_mod = 0.45
tox_mod = 0.45
+ clone_mod = 0.45
+ brain_mod = 0.45
+ stamina_mod = 0.45
+ siemens_coeff = 0
+ punchdamagelow = 5
+ punchdamagehigh = 14
+ punchstunthreshold = 11 //about 40% chance to stun
+ no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform, slot_s_store)
+ nojumpsuit = TRUE
dietflags = DIET_OMNI //golems can eat anything because they are magic or something
reagent_tag = PROCESS_ORG
- punchdamagelow = 5
- punchdamagehigh = 14
- punchstunthreshold = 11 //about 40% chance to stun
+ warning_low_pressure = -INFINITY
+ hazard_low_pressure = -INFINITY
+ hazard_high_pressure = INFINITY
+ warning_high_pressure = INFINITY
- warning_low_pressure = -1
- hazard_low_pressure = -1
- hazard_high_pressure = 999999999
- warning_high_pressure = 999999999
+ cold_level_1 = -INFINITY
+ cold_level_2 = -INFINITY
+ cold_level_3 = -INFINITY
- cold_level_1 = -1
- cold_level_2 = -1
- cold_level_3 = -1
-
- heat_level_1 = 999999999
- heat_level_2 = 999999999
- heat_level_3 = 999999999
+ heat_level_1 = INFINITY
+ heat_level_2 = INFINITY
+ heat_level_3 = INFINITY
blood_color = "#515573"
flesh_color = "#137E8F"
skinned_type = /obj/item/stack/sheet/metal
- slowdown = 3
- siemens_coeff = 0
blacklisted = TRUE // To prevent golem subtypes from overwhelming the odds when random species changes, only the Random Golem type can be chosen
dangerous_existence = TRUE
@@ -45,6 +49,19 @@
"adamantine_resonator" = /obj/item/organ/internal/adamantine_resonator
) //Has standard darksight of 2.
+ has_limbs = list(
+ "chest" = list("path" = /obj/item/organ/external/chest/unbreakable/sturdy),
+ "groin" = list("path" = /obj/item/organ/external/groin/unbreakable/sturdy),
+ "head" = list("path" = /obj/item/organ/external/head/unbreakable/sturdy),
+ "l_arm" = list("path" = /obj/item/organ/external/arm/unbreakable/sturdy),
+ "r_arm" = list("path" = /obj/item/organ/external/arm/right/unbreakable/sturdy),
+ "l_leg" = list("path" = /obj/item/organ/external/leg/unbreakable/sturdy),
+ "r_leg" = list("path" = /obj/item/organ/external/leg/right/unbreakable/sturdy),
+ "l_hand" = list("path" = /obj/item/organ/external/hand/unbreakable/sturdy),
+ "r_hand" = list("path" = /obj/item/organ/external/hand/right/unbreakable/sturdy),
+ "l_foot" = list("path" = /obj/item/organ/external/foot/unbreakable/sturdy),
+ "r_foot" = list("path" = /obj/item/organ/external/foot/right/unbreakable/sturdy))
+
suicide_messages = list(
"is crumbling into dust!",
"is smashing their body apart!")
@@ -79,27 +96,8 @@
H.mind.special_role = SPECIAL_ROLE_FREE_GOLEM
H.real_name = get_random_name()
H.name = H.real_name
- H.equip_to_slot_or_del(new /obj/item/clothing/under/golem(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/golem(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/golem(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/golem(H), slot_wear_mask)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/golem(H), slot_gloves)
- H.regenerate_icons()
to_chat(H, info_text)
-/datum/species/golem/on_species_loss(mob/living/carbon/human/H)
- ..()
- if(istype(H.w_uniform, /obj/item/clothing/under/golem)) // Doing these if checks here just in case the golem is somehow wearing something other than their golem shell, which should be impossible but you never know.
- qdel(H.w_uniform)
- if(istype(H.wear_suit, /obj/item/clothing/suit/golem))
- qdel(H.wear_suit)
- if(istype(H.shoes, /obj/item/clothing/shoes/golem))
- qdel(H.shoes)
- if(istype(H.wear_mask, /obj/item/clothing/mask/gas/golem))
- qdel(H.wear_mask)
- if(istype(H.gloves, /obj/item/clothing/gloves/golem))
- qdel(H.gloves)
-
//Random Golem
/datum/species/golem/random
@@ -204,6 +202,9 @@
brute_mod = 0.3 //70% damage reduction up from 55%
burn_mod = 0.3
tox_mod = 0.3
+ clone_mod = 0.3
+ brain_mod = 0.3
+ stamina_mod = 0.3
skinned_type = /obj/item/stack/ore/diamond
info_text = "As a Diamond Golem, you are more resistant than the average golem."
prefix = "Diamond"
@@ -213,10 +214,13 @@
/datum/species/golem/gold
name = "Gold Golem"
golem_colour = rgb(204, 204, 0)
- slowdown = 2
+ slowdown = 1
brute_mod = 0.75 //25% damage reduction down from 55%
burn_mod = 0.75
tox_mod = 0.75
+ clone_mod = 0.75
+ brain_mod = 0.75
+ stamina_mod = 0.75
skinned_type = /obj/item/stack/ore/gold
info_text = "As a Gold Golem, you are faster but less resistant than the average golem."
prefix = "Golden"
@@ -240,7 +244,7 @@
punchdamagelow = 12
punchdamagehigh = 21
punchstunthreshold = 18 //still 40% stun chance
- slowdown = 5 //diona speed
+ slowdown = 4 //pretty fucking slow
skinned_type = /obj/item/stack/ore/iron
info_text = "As a Plasteel Golem, you are slower, but harder to stun, and hit very hard when punching."
prefix = "Plasteel"
@@ -257,7 +261,7 @@
golem_colour = rgb(255, 255, 255)
skinned_type = /obj/item/stack/ore/titanium
info_text = "As a Titanium Golem, you are resistant to burn damage and immune to ash storms."
- burn_mod = 0.3
+ burn_mod = 0.405
prefix = "Titanium"
special_names = list("Dioxide")
@@ -275,7 +279,7 @@
golem_colour = rgb(136, 136, 136)
skinned_type = /obj/item/stack/ore/titanium
info_text = "As a Plastitanium Golem, you are very resistant to burn damage and immune to both ash storms and lava."
- burn_mod = 0.15
+ burn_mod = 0.36
prefix = "Plastitanium"
special_names = null
@@ -296,7 +300,7 @@
skinned_type = /obj/item/stack/sheet/mineral/abductor
language = "Golem Mindlink"
default_language = "Golem Mindlink"
- slowdown = 2 //faster
+ slowdown = 1 //faster
info_text = "As an Alloy Golem, you are made of advanced alien materials: you are faster and regenerate over time. You are, however, only able to speak telepathically to other alloy golems."
prefix = "Alien"
special_names = list("Outsider", "Technology", "Watcher", "Stranger") //ominous and unknown
@@ -323,10 +327,14 @@
name = "Wood Golem"
golem_colour = rgb(158, 112, 75)
skinned_type = /obj/item/stack/sheet/wood
- species_traits = list(NO_BREATHE, NO_BLOOD, NO_PAIN, RADIMMUNE, VIRUSIMMUNE, NOGUNS, IS_PLANT)
+ species_traits = list(NO_BREATHE, NO_BLOOD, NO_PAIN, RADIMMUNE, NOGUNS, PIERCEIMMUNE, IS_PLANT)
//Can burn and take damage from heat
brute_mod = 0.7 //30% damage reduction down from 55%
- burn_mod = 1
+ burn_mod = 0.875
+ tox_mod = 0.7
+ clone_mod = 0.7
+ brain_mod = 0.7
+ stamina_mod = 0.7
heatmod = 1.5
heat_level_1 = 300
@@ -343,25 +351,35 @@
special_name_chance = 100
/datum/species/golem/wood/handle_life(mob/living/carbon/human/H)
+ if(H.stat == DEAD)
+ return
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(H.loc)) //else, there's considered to be no light
var/turf/T = H.loc
- light_amount = min(T.get_lumcount() * 10, 5) //hardcapped so it's not abused by having a ton of flashlights
- H.nutrition = min(H.nutrition+light_amount, NUTRITION_LEVEL_WELL_FED+10)
+ light_amount = min(1, T.get_lumcount()) - 0.5
+ if(light_amount > 0)
+ H.clear_alert("nolight")
+ else
+ H.throw_alert("nolight", /obj/screen/alert/nolight)
+ H.nutrition += light_amount * 10
+ if(H.nutrition > NUTRITION_LEVEL_ALMOST_FULL)
+ H.nutrition = NUTRITION_LEVEL_ALMOST_FULL
+ if(light_amount > 0.2 && !H.suiciding) //if there's enough light, heal
+ H.adjustBruteLoss(-1)
+ H.adjustFireLoss(-1)
+ H.adjustToxLoss(-1)
+ H.adjustOxyLoss(-1)
- if(light_amount > 0)
- H.clear_alert("nolight")
- else
- H.throw_alert("nolight", /obj/screen/alert/nolight)
-
- if((light_amount >= 5) && !H.suiciding) //if there's enough light, heal
-
- H.adjustBruteLoss(-(light_amount/2))
- H.adjustFireLoss(-(light_amount/4))
- if(H.nutrition < NUTRITION_LEVEL_STARVING+50)
- H.take_overall_damage(10,0)
+ if(H.nutrition < NUTRITION_LEVEL_STARVING + 50)
+ H.adjustBruteLoss(2)
..()
+/datum/species/golem/wood/handle_reagents(mob/living/carbon/human/H, datum/reagent/R)
+ if(R.id == "glyphosate" || R.id == "atrazine")
+ H.adjustToxLoss(3) //Deal aditional damage
+ return TRUE
+ return ..()
+
//Radioactive
/datum/species/golem/uranium
name = "Uranium Golem"
@@ -392,7 +410,7 @@
/datum/species/golem/plastic/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
- C.ventcrawler = 1
+ C.ventcrawler = VENTCRAWLER_NUDE
/datum/species/golem/plastic/on_species_loss(mob/living/carbon/C)
. = ..()
@@ -404,7 +422,11 @@
golem_colour = rgb(255, 220, 143)
skinned_type = /obj/item/stack/ore/glass //this is sand
brute_mod = 0.25
- burn_mod = 3
+ burn_mod = 3 //melts easily
+ tox_mod = 1
+ clone_mod = 1
+ brain_mod = 1
+ stamina_mod = 1
info_text = "As a Sand Golem, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage and energy weapons. You will also turn to sand when dying, preventing any form of recovery."
unarmed_type = /datum/unarmed_attack/golem/sand
prefix = "Sand"
@@ -437,6 +459,10 @@
skinned_type = /obj/item/shard
brute_mod = 3 //very fragile
burn_mod = 0.25
+ tox_mod = 1
+ clone_mod = 1
+ brain_mod = 1
+ stamina_mod = 1
info_text = "As a Glass Golem, you reflect lasers and energy weapons, and are very resistant to burn damage. However, you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery."
unarmed_type = /datum/unarmed_attack/golem/glass
prefix = "Glass"
@@ -607,8 +633,8 @@
name = "Bananium Golem"
golem_colour = rgb(255, 255, 0)
punchdamagelow = 0
- punchdamagehigh = 0
- punchstunthreshold = 1 //Harmless and can't stun
+ punchdamagehigh = 1
+ punchstunthreshold = 2 //Harmless and can't stun
skinned_type = /obj/item/stack/ore/bananium
info_text = "As a Bananium Golem, you are made for pranking. Your body emits natural honks, and punching people will just harmlessly honk them. Your skin also bleeds banana peels when damaged."
prefix = "Bananium"
@@ -715,54 +741,4 @@
/datum/unarmed_attack/golem/tranquillite
attack_sound = null
- miss_sound = null
-
-//Golem abstract items
-
-/obj/item/clothing/under/golem
- name = "golem skin"
- desc = "a golem's skin"
- icon_state = "golem"
- item_state = "golem"
- item_color = "golem"
- has_sensor = 0
- flags = ABSTRACT | NODROP
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
-
-/obj/item/clothing/suit/golem
- name = "golem shell"
- desc = "a golem's thick outter shell"
- icon_state = "golem"
- item_state = "golem"
- gas_transfer_coefficient = 0.01
- permeability_coefficient = 0.02
- body_parts_covered = HEAD | UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
- flags_inv = HIDEGLOVES | HIDESHOES
- flags = STOPSPRESSUREDMAGE | ABSTRACT | NODROP | THICKMATERIAL
- flags_size = ONESIZEFITSALL
- cold_protection = HEAD | UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
- min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 0)
-
-/obj/item/clothing/shoes/golem
- name = "golem's feet"
- desc = "sturdy golem feet"
- icon_state = "golem"
- item_state = "golem"
- flags = ABSTRACT | NODROP
-
-/obj/item/clothing/mask/gas/golem
- name = "golem's face"
- desc = "the imposing face of a golem"
- icon_state = "golem"
- item_state = "golem"
- unacidable = 1
- flags = ABSTRACT | NODROP
- flags_inv = HIDEEARS | HIDEEYES
-
-/obj/item/clothing/gloves/golem
- name = "golem's hands"
- desc = "strong golem hands"
- icon_state = "golem"
- item_state = null
- flags = ABSTRACT | NODROP
+ miss_sound = null
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm
index 7eedf2520a3..4bfad7b15c9 100644
--- a/code/modules/mob/living/carbon/human/species/monkey.dm
+++ b/code/modules/mob/living/carbon/human/species/monkey.dm
@@ -13,6 +13,8 @@
species_traits = list(NO_EXAMINE)
skinned_type = /obj/item/stack/sheet/animalhide/monkey
greater_form = /datum/species/human
+ no_equip = list(slot_belt, slot_wear_id, slot_l_ear, slot_r_ear, slot_glasses, slot_gloves, slot_shoes, slot_wear_suit, slot_w_uniform, slot_l_store, slot_r_store, slot_s_store, slot_wear_pda)
+ can_craft = FALSE
is_small = 1
has_fine_manipulation = 0
ventcrawler = 1
@@ -58,44 +60,6 @@
H.dna.SetSEState(MONKEYBLOCK, TRUE)
genemutcheck(H, MONKEYBLOCK, null, MUTCHK_FORCED)
-/datum/species/monkey/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user)
- if(!user.has_organ_for_slot(slot))
- return 2
- switch(slot)
- if(slot_l_hand)
- if(user.l_hand)
- return 2
- return 1
- if(slot_r_hand)
- if(user.r_hand)
- return 2
- return 1
- if(slot_wear_mask)
- if(user.wear_mask)
- return 2
- if(!(I.slot_flags & SLOT_MASK))
- return 2
- return 1
- if(slot_back)
- if(user.back)
- return 2
- if(!(I.slot_flags & SLOT_BACK))
- return 2
- return 1
- if(slot_handcuffed)
- if(user.handcuffed)
- return 2
- if(!istype(I, /obj/item/restraints/handcuffs))
- return 2
- return 1
- if(slot_in_backpack)
- if(user.back && istype(user.back, /obj/item/storage/backpack))
- var/obj/item/storage/backpack/B = user.back
- if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class)
- return 1
- return 2
- return 2
-
/datum/species/monkey/tajaran
name = "Farwa"
name_plural = "Farwa"
diff --git a/code/modules/mob/living/carbon/human/species/skeleton.dm b/code/modules/mob/living/carbon/human/species/skeleton.dm
index 0199722d1f4..2ce5839123b 100644
--- a/code/modules/mob/living/carbon/human/species/skeleton.dm
+++ b/code/modules/mob/living/carbon/human/species/skeleton.dm
@@ -10,25 +10,25 @@
blood_color = "#FFFFFF"
flesh_color = "#E6E6C6"
- species_traits = list(NO_BREATHE, NO_BLOOD, RADIMMUNE, VIRUSIMMUNE)
+ species_traits = list(NO_BREATHE, NO_BLOOD, RADIMMUNE, VIRUSIMMUNE, PIERCEIMMUNE)
dies_at_threshold = TRUE
skinned_type = /obj/item/stack/sheet/bone
dietflags = DIET_OMNI
reagent_tag = PROCESS_ORG
- warning_low_pressure = -1
- hazard_low_pressure = -1
- hazard_high_pressure = 999999999
- warning_high_pressure = 999999999
+ warning_low_pressure = -INFINITY
+ hazard_low_pressure = -INFINITY
+ hazard_high_pressure = INFINITY
+ warning_high_pressure = INFINITY
- cold_level_1 = -1
- cold_level_2 = -1
- cold_level_3 = -1
+ cold_level_1 = -INFINITY
+ cold_level_2 = -INFINITY
+ cold_level_3 = -INFINITY
- heat_level_1 = 999999999
- heat_level_2 = 999999999
- heat_level_3 = 999999999
+ heat_level_1 = INFINITY
+ heat_level_2 = INFINITY
+ heat_level_3 = INFINITY
suicide_messages = list(
"is snapping their own bones!",
diff --git a/code/modules/mob/living/carbon/human/species/zombies.dm b/code/modules/mob/living/carbon/human/species/zombies.dm
index 81a462d9fab..fcc8d2feeb8 100644
--- a/code/modules/mob/living/carbon/human/species/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species/zombies.dm
@@ -37,7 +37,11 @@
mutanthands = /obj/item/zombie_hand
icobase = 'icons/mob/human_races/r_zombie.dmi'
deform = 'icons/mob/human_races/r_def_zombie.dmi'
- armor = 20 // 120 damage to KO a zombie, which kills it
+ brute_mod = 0.8 // 120 damage to KO a zombie, which kills it
+ burn_mod = 0.8
+ clone_mod = 0.8
+ brain_mod = 0.8
+ stamina_mod = 0.8
speedmod = 1.6
default_language = "Zombie"
var/heal_rate = 1
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index a9887483d20..7aa21b1974a 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -621,6 +621,19 @@
var/brightness_power = 1
var/brightness_color = null
+/obj/item/light/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/caltrop, force)
+
+/obj/item/light/Crossed(mob/living/L)
+ if(istype(L) && has_gravity(loc))
+ if(L.incorporeal_move || L.flying)
+ return
+ playsound(loc, 'sound/effects/glass_step.ogg', 50, TRUE)
+ if(status == LIGHT_BURNED || status == LIGHT_OK)
+ shatter()
+ return ..()
+
/obj/item/light/tube
name = "light tube"
desc = "A replacement light tube."
diff --git a/code/modules/surgery/organs/subtypes/unbreakable.dm b/code/modules/surgery/organs/subtypes/unbreakable.dm
index 74dc1ae3de7..327a25de405 100644
--- a/code/modules/surgery/organs/subtypes/unbreakable.dm
+++ b/code/modules/surgery/organs/subtypes/unbreakable.dm
@@ -1,34 +1,66 @@
-// Slime limbs.
/obj/item/organ/external/chest/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/groin/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/arm/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/arm/right/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/leg/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/leg/right/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/foot/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/foot/right/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/hand/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/hand/right/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
/obj/item/organ/external/head/unbreakable
- cannot_break = 1
+ cannot_break = TRUE
+// Cannot dismember or break
+/obj/item/organ/external/chest/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/groin/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/arm/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/arm/right/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/leg/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/leg/right/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/foot/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/foot/right/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/hand/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/hand/right/unbreakable/sturdy
+ cannot_amputate = TRUE
+
+/obj/item/organ/external/head/unbreakable/sturdy
+ cannot_amputate = TRUE
\ No newline at end of file
diff --git a/paradise.dme b/paradise.dme
index 72ff653afde..bdb77b45dd0 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -141,7 +141,6 @@
#include "code\_onclick\hud\guardian.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
-#include "code\_onclick\hud\monkey.dm"
#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\other_mobs.dm"
#include "code\_onclick\hud\parallax.dm"
@@ -278,6 +277,7 @@
#include "code\datums\cache\crew.dm"
#include "code\datums\cache\powermonitor.dm"
#include "code\datums\components\_component.dm"
+#include "code\datums\components\caltrop.dm"
#include "code\datums\components\decal.dm"
#include "code\datums\components\ducttape.dm"
#include "code\datums\components\jestosterone.dm"