diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm
index 2c6eda9f90..d01e4f8da1 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm
@@ -18,6 +18,9 @@
/obj/item/mining_scanner,
/obj/item/flashlight/lantern,
/obj/item/card/id/mining,
+/obj/item/gps/mining{
+ tracking = 0
+ },
/turf/open/floor/plating,
/area/ruin/powered/golem_ship)
"d" = (
@@ -31,6 +34,9 @@
/obj/item/mining_scanner,
/obj/item/flashlight/lantern,
/obj/item/card/id/mining,
+/obj/item/gps/mining{
+ tracking = 0
+ },
/turf/open/floor/plating,
/area/ruin/powered/golem_ship)
"e" = (
@@ -150,6 +156,9 @@
"x" = (
/obj/structure/table/wood,
/obj/machinery/reagentgrinder,
+/obj/item/gps/mining{
+ tracking = 0
+ },
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
"z" = (
diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm
index a05e6f6160..affa23d30a 100644
--- a/code/__DEFINES/robots.dm
+++ b/code/__DEFINES/robots.dm
@@ -53,4 +53,10 @@
//Checks to determine borg availability depending on the server's config. These are defines in the interest of reducing copypasta
-#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
\ No newline at end of file
+#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
+
+//silicon_priviledges flags
+#define PRIVILEDGES_SILICON (1<<0)
+#define PRIVILEDGES_PAI (1<<1)
+#define PRIVILEDGES_BOT (1<<2)
+#define PRIVILEDGES_DRONE (1<<3)
diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm
index dc18107a95..9638b040f9 100644
--- a/code/_onclick/drag_drop.dm
+++ b/code/_onclick/drag_drop.dm
@@ -42,7 +42,7 @@
selected_target[1] = object
selected_target[2] = params
while(selected_target[1])
- Click(selected_target[1], location, control, selected_target[2])
+ Click(selected_target[1], location, control, selected_target[2], TRUE)
sleep(delay)
active_mousedown_item = mob.canMobMousedown(object, location, params)
if(active_mousedown_item)
@@ -145,4 +145,4 @@
if (middragatom == src_object)
middragtime = 0
middragatom = null
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index fe994facdc..606aca2d3a 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -486,8 +486,9 @@ SUBSYSTEM_DEF(ticker)
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = INSTANT_RUNOFF_VOTING)
if("SCORE")
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING)
+ else
+ SSvote.initiate_vote("map","server",hideresults=TRUE)
// fallback
- SSvote.initiate_vote("map","server",hideresults=TRUE)
/datum/controller/subsystem/ticker/proc/HasRoundStarted()
return current_state >= GAME_STATE_PLAYING
diff --git a/code/datums/components/crafting/guncrafting.dm b/code/datums/components/crafting/guncrafting.dm
index d96be9be10..d421a6e42a 100644
--- a/code/datums/components/crafting/guncrafting.dm
+++ b/code/datums/components/crafting/guncrafting.dm
@@ -13,3 +13,9 @@
desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood."
icon = 'icons/obj/improvised.dmi'
icon_state = "riflestock"
+
+/obj/item/weaponcrafting/silkstring
+ name = "silkstring"
+ desc = "A long pice of silk looks like cable coil."
+ icon = 'icons/obj/improvised.dmi'
+ icon_state = "silkstring"
\ No newline at end of file
diff --git a/code/datums/components/crafting/recipes/recipes_primal.dm b/code/datums/components/crafting/recipes/recipes_primal.dm
index 1fc684eddc..ae611e5855 100644
--- a/code/datums/components/crafting/recipes/recipes_primal.dm
+++ b/code/datums/components/crafting/recipes/recipes_primal.dm
@@ -89,4 +89,31 @@
parts = list(/obj/item/bodypart/head = 1,
/obj/item/twohanded/bonespear = 1)
result = /obj/structure/headpike/bone
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/quiver
+ name = "Quiver"
+ always_availible = FALSE
+ result = /obj/item/storage/belt/quiver
+ time = 80
+ reqs = list(/obj/item/stack/sheet/leather = 3,
+ /obj/item/stack/sheet/sinew = 4)
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/bone_bow
+ name = "Bone Bow"
+ result = /obj/item/gun/ballistic/bow/ashen
+ time = 200
+ always_availible = FALSE
+ reqs = list(/obj/item/stack/sheet/bone = 8,
+ /obj/item/stack/sheet/sinew = 4)
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/bow_tablet
+ name = "Sandstone Bow Making Manual"
+ result = /obj/item/book/granter/crafting_recipe/bone_bow
+ time = 600 //Scribing
+ always_availible = FALSE
+ reqs = list(/obj/item/stack/rods = 1,
+ /obj/item/stack/sheet/mineral/sandstone = 4)
category = CAT_PRIMAL
\ No newline at end of file
diff --git a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm
index 104b58ca28..76f8f119e0 100644
--- a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm
+++ b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm
@@ -199,6 +199,16 @@
//////////////////
+/datum/crafting_recipe/pipebow
+ name = "Pipe Bow"
+ result = /obj/item/gun/ballistic/bow/pipe
+ reqs = list(/obj/item/pipe = 5,
+ /obj/item/stack/sheet/plastic = 15,
+ /obj/item/weaponcrafting/silkstring = 10)
+ time = 450
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
+
/datum/crafting_recipe/smartdartgun
name = "Smart dartgun"
result = /obj/item/gun/syringe/dart
@@ -278,6 +288,37 @@
///AMMO CRAFTING//
//////////////////
+/datum/crafting_recipe/arrow
+ name = "Arrow"
+ result = /obj/item/ammo_casing/caseless/arrow
+ time = 40
+ reqs = list(/obj/item/stack/sheet/mineral/wood = 1,
+ /obj/item/weaponcrafting/silkstring = 1,
+ /obj/item/stack/rods = 3) // 1 metal sheet is worth 1.5 arrows
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
+/datum/crafting_recipe/bone_arrow
+ name = "Bone Arrow"
+ result = /obj/item/ammo_casing/caseless/arrow/bone
+ time = 40
+ always_availible = FALSE
+ reqs = list(/obj/item/stack/sheet/bone = 1,
+ /obj/item/stack/sheet/sinew = 1,
+ /obj/item/ammo_casing/caseless/arrow/ashen = 1)
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
+/datum/crafting_recipe/ashen_arrow
+ name = "Harden Arrow"
+ result = /obj/item/ammo_casing/caseless/arrow/ashen
+ tools = list(/obj/structure/bonfire)
+ time = 20
+ always_availible = FALSE
+ reqs = list(/obj/item/ammo_casing/caseless/arrow = 1)
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
/datum/crafting_recipe/smartdart
name = "Medical smartdart"
result = /obj/item/reagent_containers/syringe/dart
diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm
index e33c430198..8687d89b2f 100644
--- a/code/datums/elements/mob_holder.dm
+++ b/code/datums/elements/mob_holder.dm
@@ -93,7 +93,7 @@
lefthand_file = left_hand
if(right_hand)
righthand_file = right_hand
- slot_flags = slots
+ slot_flags = slots
/obj/item/clothing/head/mob_holder/proc/assimilate(mob/living/target)
target.setDir(SOUTH)
@@ -114,16 +114,14 @@
w_class = WEIGHT_CLASS_NORMAL
if(MOB_SIZE_LARGE)
w_class = WEIGHT_CLASS_HUGE
- RegisterSignal(src, COMSIG_CLICK_SHIFT, .proc/examine_held_mob)
/obj/item/clothing/head/mob_holder/Destroy()
if(held_mob)
release()
return ..()
-/obj/item/clothing/head/mob_holder/proc/examine_held_mob(datum/source, mob/user)
- held_mob.ShiftClick(user)
- return COMPONENT_DENY_EXAMINATE
+/obj/item/clothing/head/mob_holder/examine(mob/user)
+ return held_mob?.examine(user) || ..()
/obj/item/clothing/head/mob_holder/Exited(atom/movable/AM, atom/newloc)
. = ..()
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 459ff2f3d6..20a45b2102 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -1096,7 +1096,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
var/approved_targets = list()
check_sabotages:
for(var/datum/sabotage_objective/possible_sabotage in GLOB.possible_sabotages)
- if(!is_unique_objective(possible_sabotage.sabotage_type) || possible_sabotage.check_conditions())
+ if(!is_unique_objective(possible_sabotage.sabotage_type) || possible_sabotage.check_conditions() || !possible_sabotage.can_run())
continue
for(var/datum/mind/M in owners)
if(M.current.mind.assigned_role in possible_sabotage.excludefromjob)
diff --git a/code/game/gamemodes/objective_sabotage.dm b/code/game/gamemodes/objective_sabotage.dm
index 248524f1d2..1094dd2f36 100644
--- a/code/game/gamemodes/objective_sabotage.dm
+++ b/code/game/gamemodes/objective_sabotage.dm
@@ -12,6 +12,9 @@
/datum/sabotage_objective/proc/check_conditions()
return TRUE
+/datum/sabotage_objective/proc/can_run()
+ return TRUE
+
/datum/sabotage_objective/processing
var/won = FALSE
@@ -79,6 +82,9 @@
won = max(1-((S.get_integrity()-50)/50),won)
return FALSE
+/datum/sabotage_objective/processing/supermatter/can_run()
+ return (locate(/obj/machinery/power/supermatter_crystal) in GLOB.machines)
+
/datum/sabotage_objective/station_integrity
name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal."
sabotage_type = "integrity"
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index b5ab859797..19a20f0cfa 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -264,7 +264,7 @@
if(blood_id)
data["occupant"]["blood"] = list() // We can start populating this list.
var/blood_type = C.dna.blood_type
- if(blood_id != "blood") // special blood substance
+ if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(R)
blood_type = R.name
diff --git a/code/game/machinery/bloodbankgen.dm b/code/game/machinery/bloodbankgen.dm
index cb25adc126..19632711fc 100644
--- a/code/game/machinery/bloodbankgen.dm
+++ b/code/game/machinery/bloodbankgen.dm
@@ -274,20 +274,20 @@
return TRUE
-/obj/machinery/bloodbankgen/proc/detachinput()
+/obj/machinery/bloodbankgen/proc/detachinput(mob/user)
if(bag)
bag.forceMove(drop_location())
- if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
- usr.put_in_hands(bag)
+ if(user && Adjacent(usr) && user.can_hold_items())
+ user.put_in_hands(bag)
bag = null
draining = null
update_icon()
-/obj/machinery/bloodbankgen/proc/detachoutput()
+/obj/machinery/bloodbankgen/proc/detachoutput(mob/user)
if(outbag)
outbag.forceMove(drop_location())
- if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
- usr.put_in_hands(outbag)
+ if(user && Adjacent(user) && user.can_hold_items())
+ user.put_in_hands(outbag)
outbag = null
filling = null
update_icon()
@@ -325,12 +325,12 @@
activateinput()
else if(href_list["detachinput"])
- detachinput()
+ detachinput(usr)
else if(href_list["activateoutput"])
activateoutput()
else if(href_list["detachoutput"])
- detachoutput()
+ detachoutput(usr)
updateUsrDialog()
diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm
index e5ac9a0f78..5fe62ebb76 100644
--- a/code/game/machinery/computer/camera_advanced.dm
+++ b/code/game/machinery/computer/camera_advanced.dm
@@ -72,7 +72,7 @@
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
/obj/machinery/computer/camera_advanced/check_eye(mob/user)
- if( (stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && !user.has_unlimited_silicon_privilege) || user.eye_blind || user.incapacitated() )
+ if( (stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && hasSiliconAccessInArea(user)) || user.eye_blind || user.incapacitated() )
user.unset_machine()
/obj/machinery/computer/camera_advanced/Destroy()
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index b33b87f8b1..92927d047d 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -116,7 +116,7 @@
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
I.forceMove(drop_location())
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
user.put_in_hands(I)
frozen_items -= I
updateUsrDialog()
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index 6d19776d86..b3f0ce9693 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -184,7 +184,7 @@
if(usr.incapacitated())
return
if(beaker)
- if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
+ if(usr && Adjacent(usr) && usr.can_hold_items())
if(!usr.put_in_hands(beaker))
beaker.forceMove(drop_location())
beaker = null
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 3f57fa7cdf..3fad8cc53d 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -196,7 +196,7 @@ RLD
/obj/item/construction/rcd/verb/change_airlock_access(mob/user)
- if (!ishuman(user) && !user.has_unlimited_silicon_privilege)
+ if (!ishuman(user) && !user.silicon_privileges)
return
var/t1 = ""
diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm
index 70cd503ef4..986090212e 100644
--- a/code/game/objects/items/granters.dm
+++ b/code/game/objects/items/granters.dm
@@ -490,7 +490,13 @@
oneuse = FALSE
remarks = list("Looks like these would sell much better in a plasma fire...", "Using glass bowls rather then cones?", "Mixing soda and ice-cream?", "Tall glasses with of liquids and solids...", "Just add a bit of icecream and cherry on top?")
-//Later content when I have free time - Trilby Date:24-Aug-2019
+/obj/item/book/granter/crafting_recipe/bone_bow //Bow crafting for non-ashwalkers
+ name = "Sandstone manual on bows"
+ desc = "A standstone slab with everything you need to know for making bows and arrows just like an ashwalker would."
+ crafting_recipe_types = list(/datum/crafting_recipe/bone_arrow, /datum/crafting_recipe/bone_bow, /datum/crafting_recipe/ashen_arrow, /datum/crafting_recipe/quiver, /datum/crafting_recipe/bow_tablet)
+ icon_state = "stone_tablet"
+ oneuse = FALSE
+ remarks = list("Sticking burning arrows into the sand makes them stronger?", "Breaking the bone apart to get shards, not sharpening the bone.", "Sinew is just like rope?")
/obj/item/book/granter/crafting_recipe/under_the_oven //Illegal cook book
name = "Under The Oven"
diff --git a/code/game/objects/items/implants/implant_hijack.dm b/code/game/objects/items/implants/implant_hijack.dm
index 8a08232859..5dd610059c 100644
--- a/code/game/objects/items/implants/implant_hijack.dm
+++ b/code/game/objects/items/implants/implant_hijack.dm
@@ -37,18 +37,18 @@
eye_color = H.eye_color
return TRUE
-/obj/item/implant/hijack/removed(mob/target, silent = FALSE, special = 0)
+/obj/item/implant/hijack/removed(mob/living/source, silent = FALSE, special = 0)
if(..())
- REMOVE_TRAIT(target, TRAIT_HIJACKER, "implant")
- for (var/area/area in imp_in.siliconaccessareas)
- imp_in.toggleSiliconAccessArea(area)
+ REMOVE_TRAIT(source, TRAIT_HIJACKER, "implant")
+ for (var/area/area in source.siliconaccessareas)
+ source.toggleSiliconAccessArea(area)
var/obj/machinery/power/apc/apc = area.get_apc()
if (apc)
apc.hijacker = null
apc.set_hijacked_lighting()
apc.update_icon()
- if (ishuman(target))
- var/mob/living/carbon/human/H = target
+ if (ishuman(source))
+ var/mob/living/carbon/human/H = source
H.eye_color = eye_color
return TRUE
@@ -118,4 +118,4 @@
imp_in.light_range = 0
imp_in.light_color = COLOR_YELLOW
imp_in.update_light()
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index 7879f50ada..934273ae46 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -258,6 +258,9 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
merge_type = /obj/item/stack/sheet/plastitaniumglass
shard_type = /obj/item/shard
+/obj/item/stack/sheet/plastitaniumglass/fifty
+ amount = 50
+
/obj/item/stack/sheet/plastitaniumglass/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.plastitaniumglass_recipes
return ..()
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index 828ed96387..6ff6cdfbbf 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -323,6 +323,9 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \
point_value = 45
merge_type = /obj/item/stack/sheet/mineral/plastitanium
+/obj/item/stack/sheet/mineral/plastitanium/fifty
+ amount = 50
+
GLOBAL_LIST_INIT(plastitanium_recipes, list ( \
new/datum/stack_recipe("plastitanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20), \
))
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 45911afc73..64875a4cc3 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -376,6 +376,14 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
/*
* Silk
*/
+
+ GLOBAL_LIST_INIT(silk_recipes, list ( \
+ new/datum/stack_recipe("white jumpsuit", /obj/item/clothing/under/color/white, 4, time = 40), \
+ new/datum/stack_recipe("white gloves", /obj/item/clothing/gloves/color/white, 2, time = 40), \
+ null, \
+ new/datum/stack_recipe("silk string", /obj/item/weaponcrafting/silkstring, 2, time = 40), \
+ ))
+
/obj/item/stack/sheet/silk
name = "silk"
desc = "A long soft material. This one is just made out of cotton rather then any spiders or wyrms"
@@ -385,14 +393,14 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
novariants = TRUE
merge_type = /obj/item/stack/sheet/silk
-//obj/item/stack/sheet/silk/Initialize(mapload, new_amount, merge = TRUE)
-// recipes = GLOB.silk_recipes
-// return ..()
+/obj/item/stack/sheet/silk/Initialize(mapload, new_amount, merge = TRUE)
+ recipes = GLOB.silk_recipes
+ return ..()
/*
* Durathread
*/
- GLOBAL_LIST_INIT(durathread_recipes, list ( \
+GLOBAL_LIST_INIT(durathread_recipes, list ( \
new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/durathread, 4, time = 40),
new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \
new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 2762be8edf..311657aba9 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -173,23 +173,25 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
var/unholy2clean = A.reagents.get_reagent_amount(/datum/reagent/fuel/unholywater)
A.reagents.del_reagent(/datum/reagent/fuel/unholywater)
A.reagents.add_reagent(/datum/reagent/water/holywater,unholy2clean)
- if(istype(A, /obj/item/twohanded/required/cult_bastard) && !iscultist(user))
- var/obj/item/twohanded/required/cult_bastard/sword = A
- to_chat(user, "You begin to exorcise [sword].")
+ if(istype(A, /obj/item/twohanded/required/cult_bastard) || istype(A, /obj/item/melee/cultblade) && !iscultist(user))
+ to_chat(user, "You begin to exorcise [A].")
playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,1)
- if(do_after(user, 40, target = sword))
+ if(do_after(user, 40, target = A))
playsound(src,'sound/effects/pray_chaplain.ogg',60,1)
- for(var/obj/item/soulstone/SS in sword.contents)
- SS.usability = TRUE
- for(var/mob/living/simple_animal/shade/EX in SS)
- SSticker.mode.remove_cultist(EX.mind, 1, 0)
- EX.icon_state = "ghost1"
- EX.name = "Purified [EX.name]"
- SS.release_shades(user)
- qdel(SS)
- new /obj/item/nullrod/claymore(get_turf(sword))
- user.visible_message("[user] has purified the [sword]!")
- qdel(sword)
+ if(istype(A, /obj/item/twohanded/required/cult_bastard))
+ for(var/obj/item/soulstone/SS in A.contents)
+ SS.usability = TRUE
+ for(var/mob/living/simple_animal/shade/EX in SS)
+ SSticker.mode.remove_cultist(EX.mind, 1, 0)
+ EX.icon_state = "ghost1"
+ EX.name = "Purified [EX.name]"
+ SS.release_shades(user)
+ qdel(SS)
+ new /obj/item/nullrod/claymore(get_turf(A))
+ else
+ new /obj/item/claymore/purified(get_turf(A))
+ user.visible_message("[user] has purified [A]!")
+ qdel(A)
else if(istype(A, /obj/item/soulstone) && !iscultist(user))
var/obj/item/soulstone/SS = A
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index cd6cc5f520..ea9899b2c2 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -79,6 +79,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return(BRUTELOSS)
+/obj/item/claymore/purified
+ name = "purified longsword"
+ desc = "A hastily-purified longsword. While not as holy as it could be, it's still a formidable weapon against those who would rather see you dead."
+ force = 25
+
/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim."
flags_1 = CONDUCT_1
diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm
index 290e69370b..602adfb367 100644
--- a/code/game/objects/structures/crates_lockers/crates/secure.dm
+++ b/code/game/objects/structures/crates_lockers/crates/secure.dm
@@ -70,3 +70,8 @@
name = "secure science crate"
desc = "A crate with a lock on it, painted in the scheme of the station's scientists."
icon_state = "scisecurecrate"
+
+/obj/structure/closet/crate/secure/medical
+ desc = "A secure medical crate."
+ name = "medical crate"
+ icon_state = "medical_secure_crate"
\ No newline at end of file
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index 483b8fccbe..116c598235 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -19,21 +19,20 @@
Estimated time of last contact: Deployment, 5000 millennia ago."
assignedrole = "Lifebringer"
-/obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn)
- var/plant_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \
- "Venus", "Sprout","Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
- new_spawn.real_name = plant_name
- if(ishuman(new_spawn))
- var/mob/living/carbon/human/H = new_spawn
- H.underwear = "Nude" //You're a plant, partner
- H.update_body()
-
/obj/effect/mob_spawn/human/seed_vault/Destroy()
new/obj/structure/fluff/empty_terrarium(get_turf(src))
return ..()
/obj/effect/mob_spawn/human/seed_vault/special(mob/living/carbon/human/new_spawn)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
+ var/plant_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \
+ "Venus", "Sprout","Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
+ new_spawn.real_name = plant_name //why this works when moving it from one function to another is beyond me
+ new_spawn.underwear = "Nude" //You're a plant, partner
+ new_spawn.undershirt = "Nude" //changing underwear/shirt/socks doesn't seem to function correctly right now because of some bug elsewhere?
+ new_spawn.socks = "Nude"
+ new_spawn.update_body()
+
//Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers.
/obj/effect/mob_spawn/human/ash_walker
@@ -67,6 +66,14 @@
var/datum/language_holder/holder = new_spawn.get_language_holder()
holder.selected_default_language = /datum/language/draconic
+//Ash walkers on birth understand how to make bone bows, bone arrows and ashen arrows
+
+ new_spawn.mind.teach_crafting_recipe(/datum/crafting_recipe/bone_arrow)
+ new_spawn.mind.teach_crafting_recipe(/datum/crafting_recipe/bone_bow)
+ new_spawn.mind.teach_crafting_recipe(/datum/crafting_recipe/ashen_arrow)
+ new_spawn.mind.teach_crafting_recipe(/datum/crafting_recipe/quiver)
+ new_spawn.mind.teach_crafting_recipe(/datum/crafting_recipe/bow_tablet)
+
if(ishuman(new_spawn))
var/mob/living/carbon/human/H = new_spawn
H.underwear = "Nude"
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index e8f53f551d..578d6d10ae 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -552,6 +552,8 @@
//if the vomit combined, apply toxicity and reagents to the old vomit
if (QDELETED(V))
V = locate() in src
+ if(!V) //the decal was spawned on a wall or groundless turf and promptly qdeleted.
+ return
// Make toxins and blazaam vomit look different
if(toxvomit == VOMIT_PURPLE)
V.icon_state = "vomitpurp_[pick(1,4)]"
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index f23fc5c070..3ccd113864 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -714,7 +714,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
AI_Interact = !AI_Interact
if(mob && IsAdminGhost(mob))
- mob.has_unlimited_silicon_privilege = AI_Interact
+ mob.silicon_privileges = AI_Interact ? ALL : NONE
log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact")
message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction")
diff --git a/code/modules/antagonists/bloodsucker/powers/feed.dm b/code/modules/antagonists/bloodsucker/powers/feed.dm
index 2da84b6075..f9ff31d94a 100644
--- a/code/modules/antagonists/bloodsucker/powers/feed.dm
+++ b/code/modules/antagonists/bloodsucker/powers/feed.dm
@@ -170,7 +170,7 @@
// Warn Feeder about Witnesses...
var/was_unnoticed = TRUE
for(var/mob/living/M in viewers(notice_range, owner))
- if(M != owner && M != target && iscarbon(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
+ if(M != owner && M != target && iscarbon(M) && M.mind && !M.silicon_privileges && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
was_unnoticed = FALSE
break
if(was_unnoticed)
diff --git a/code/modules/antagonists/bloodsucker/powers/go_home.dm b/code/modules/antagonists/bloodsucker/powers/go_home.dm
index 87c3d4ab0d..3fa8a07299 100644
--- a/code/modules/antagonists/bloodsucker/powers/go_home.dm
+++ b/code/modules/antagonists/bloodsucker/powers/go_home.dm
@@ -65,7 +65,7 @@
if(T && T.lighting_object && T.get_lumcount()>= 0.1)
// B) Check for Viewers
for(var/mob/living/M in viewers(get_turf(owner)))
- if(M != owner && isliving(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind) // M.client <--- add this in after testing!
+ if(M != owner && isliving(M) && M.mind && !M.silicon_privileges && !M.eye_blind) // M.client <--- add this in after testing!
am_seen = TRUE
if (!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
drop_item = TRUE
diff --git a/code/modules/antagonists/clockcult/clockcult.dm b/code/modules/antagonists/clockcult/clockcult.dm
index d68e9b594d..1869414ab6 100644
--- a/code/modules/antagonists/clockcult/clockcult.dm
+++ b/code/modules/antagonists/clockcult/clockcult.dm
@@ -120,7 +120,7 @@
hierophant_network.Grant(current)
current.throw_alert("clockinfo", /obj/screen/alert/clockwork/infodump)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- if(G.active && ishuman(current))
+ if(G && G.active && ishuman(current))
current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
/datum/antagonist/clockcult/remove_innate_effects(mob/living/mob_override)
@@ -174,9 +174,12 @@
log_admin("[key_name(admin)] has made [new_owner.current] into a servant of Ratvar.")
/datum/antagonist/clockcult/admin_remove(mob/user)
- remove_servant_of_ratvar(owner.current, TRUE)
- message_admins("[key_name_admin(user)] has removed clockwork servant status from [owner.current].")
- log_admin("[key_name(user)] has removed clockwork servant status from [owner.current].")
+ var/mob/target = owner.current
+ if(!target)
+ return
+ remove_servant_of_ratvar(target, TRUE)
+ message_admins("[key_name_admin(user)] has removed clockwork servant status from [target].")
+ log_admin("[key_name(user)] has removed clockwork servant status from [target].")
/datum/antagonist/clockcult/get_admin_commands()
. = ..()
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index e85cf1efa6..36a128f2eb 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -229,7 +229,7 @@
. += "Alt-click to [locked ? "unlock" : "lock"] the interface."
/obj/machinery/airalarm/ui_status(mob/user)
- if(user.has_unlimited_silicon_privilege && aidisabled)
+ if(hasSiliconAccessInArea(user) && aidisabled)
to_chat(user, "AI control has been disabled.")
else if(!shorted)
return ..()
@@ -245,7 +245,7 @@
/obj/machinery/airalarm/ui_data(mob/user)
var/data = list(
"locked" = locked,
- "siliconUser" = user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user),
+ "siliconUser" = hasSiliconAccessInArea(user),
"emagged" = (obj_flags & EMAGGED ? 1 : 0),
"danger_level" = danger_level,
)
@@ -288,7 +288,7 @@
"danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure)
))
- if(!locked || user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user))
+ if(!locked || hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE))
data["vents"] = list()
for(var/id_tag in A.air_vent_names)
var/long_name = A.air_vent_names[id_tag]
@@ -368,12 +368,14 @@
/obj/machinery/airalarm/ui_act(action, params)
if(..() || buildstage != 2)
return
- if((locked && !usr.has_unlimited_silicon_privilege && !hasSiliconAccessInArea(usr)) || (usr.has_unlimited_silicon_privilege && aidisabled))
+ var/silicon_access = hasSiliconAccessInArea(usr)
+ var/bot_priviledges = silicon_access || (usr.silicon_privileges & PRIVILEDGES_DRONE)
+ if((locked && !bot_priviledges) || (silicon_access && aidisabled))
return
var/device_id = params["id_tag"]
switch(action)
if("lock")
- if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN))
+ if(bot_priviledges && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
. = TRUE
if("power", "toggle_filter", "widenet", "scrubbing")
diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm
index bf67286f11..b7bdcb1f59 100644
--- a/code/modules/cargo/exports/large_objects.dm
+++ b/code/modules/cargo/exports/large_objects.dm
@@ -24,13 +24,13 @@
export_types = list(/obj/structure/ore_box)
/datum/export/large/crate/wood
- cost = 140 //
+ cost = 140
unit_name = "wooden crate"
export_types = list(/obj/structure/closet/crate/wooden)
exclude_types = list()
/datum/export/large/barrel
- cost = 500 //150 to make meaning proffit of 350
+ cost = 300 //double the wooden cost of a coffin.
unit_name = "wooden barrel"
export_types = list(/obj/structure/fermenting_barrel)
@@ -40,19 +40,11 @@
export_types = list(/obj/structure/closet/crate/coffin)
/datum/export/large/reagent_dispenser
- cost = 100 // +0-400 depending on amount of reagents left
- var/contents_cost = 400
-
-/datum/export/large/reagent_dispenser/get_cost(obj/O)
- var/obj/structure/reagent_dispensers/D = O
- var/ratio = D.reagents.total_volume / D.reagents.maximum_volume
-
- return ..() + round(contents_cost * ratio)
+ cost = 100
/datum/export/large/reagent_dispenser/water
unit_name = "watertank"
export_types = list(/obj/structure/reagent_dispensers/watertank)
- contents_cost = 200
/datum/export/large/reagent_dispenser/fuel
unit_name = "fueltank"
@@ -60,7 +52,6 @@
/datum/export/large/reagent_dispenser/beer
unit_name = "beer keg"
- contents_cost = 700
export_types = list(/obj/structure/reagent_dispensers/beerkeg)
/datum/export/large/pipedispenser
diff --git a/code/modules/cargo/exports/materials.dm b/code/modules/cargo/exports/materials.dm
index d8fc5f22ab..1b38a809cf 100644
--- a/code/modules/cargo/exports/materials.dm
+++ b/code/modules/cargo/exports/materials.dm
@@ -65,11 +65,6 @@
material_id = MAT_TITANIUM
message = "cm3 of titanium"
-/datum/export/material/plastitanium
- cost = 165 // plasma + titanium costs
- material_id = MAT_TITANIUM // code can only check for one material_id; plastitanium is half plasma, half titanium
- message = "cm3 of plastitanium"
-
/datum/export/material/plastic
cost = 5
material_id = MAT_PLASTIC
diff --git a/code/modules/cargo/exports/sheets.dm b/code/modules/cargo/exports/sheets.dm
index f784083097..df1704d660 100644
--- a/code/modules/cargo/exports/sheets.dm
+++ b/code/modules/cargo/exports/sheets.dm
@@ -67,6 +67,16 @@
message = "of plasteel"
export_types = list(/obj/item/stack/sheet/plasteel)
+/datum/export/material/plastitanium
+ cost = 165 // plasma + titanium costs
+ export_types = list(/obj/item/stack/sheet/mineral/plastitanium)
+ message = "of plastitanium"
+
+/datum/export/material/plastitanium_glass
+ cost = 168 // plasma + titanium + glass costs
+ export_types = list(/obj/item/stack/sheet/plastitaniumglass)
+ message = "of plastitanium glass"
+
// 1 glass + 0.5 metal, cost is rounded up.
/datum/export/stack/rglass
cost = 6
diff --git a/code/modules/cargo/exports/weapons.dm b/code/modules/cargo/exports/weapons.dm
index 5b78a5d630..c75a1c0bff 100644
--- a/code/modules/cargo/exports/weapons.dm
+++ b/code/modules/cargo/exports/weapons.dm
@@ -199,6 +199,31 @@
unit_name = "advanced shotgun shell"
export_types = list(/obj/item/ammo_casing/shotgun/dragonsbreath, /obj/item/ammo_casing/shotgun/meteorslug, /obj/item/ammo_casing/shotgun/pulseslug, /obj/item/ammo_casing/shotgun/frag12, /obj/item/ammo_casing/shotgun/ion, /obj/item/ammo_casing/shotgun/laserslug)
+/////////////////////////
+//Bow and Arrows/////////
+/////////////////////////
+
+/datum/export/weapon/bows
+ cost = 450
+ unit_name = "bow"
+ export_types = list(/obj/item/gun/ballistic/bow)
+
+/datum/export/weapon/arrows
+ cost = 150
+ unit_name = "arrow"
+ export_types = list(/obj/item/ammo_casing/caseless/arrow, /obj/item/ammo_casing/caseless/arrow/bone, /obj/item/ammo_casing/caseless/arrow/ashen)
+
+/datum/export/weapon/bow_teaching
+ cost = 500
+ unit_name = "stone tablets"
+ export_types = list(/obj/item/book/granter/crafting_recipe/bone_bow)
+
+/datum/export/weapon/quiver
+ cost = 100
+ unit_name = "quiver"
+ export_types = list(/obj/item/storage/belt/quiver)
+
+
/////////////////////////
//The Traitor Sell Outs//
/////////////////////////
diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm
index 264f9ac22e..a65d8cad40 100644
--- a/code/modules/cargo/expressconsole.dm
+++ b/code/modules/cargo/expressconsole.dm
@@ -97,7 +97,7 @@
var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location?
var/list/data = list()
data["locked"] = locked//swipe an ID to unlock
- data["siliconUser"] = user.has_unlimited_silicon_privilege
+ data["siliconUser"] = hasSiliconAccessInArea(user)
data["beaconzone"] = beacon ? get_area(beacon) : ""//where is the beacon located? outputs in the tgui
data["usingBeacon"] = usingBeacon //is the mode set to deliver to the beacon or the cargobay?
data["canBeacon"] = !usingBeacon || canBeacon //is the mode set to beacon delivery, and is the beacon in a valid location?
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 4c9ddfe3bc..07a75bbfaf 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -2,7 +2,7 @@
var/name = "Crate"
var/group = ""
var/hidden = FALSE //Aka emag only
- var/contraband = FALSE //Hacking the console with a multitool
+ var/contraband = FALSE //Requires a hacked console UNLESS DropPodOnly = TRUE, in which case it requires an emag
var/cost = 700 // Minimum cost, or infinite points are possible.
var/access = FALSE //What access does the Crate itself need?
var/access_any = FALSE //Do we care about access?
diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm
index ea8ef8ba0f..fc95b05007 100644
--- a/code/modules/cargo/packs/armory.dm
+++ b/code/modules/cargo/packs/armory.dm
@@ -178,7 +178,7 @@
/datum/supply_pack/security/armory/russian
name = "Russian Surplus Crate"
desc = "Hello Comrade, we have the most modern russian military equipment the black market can offer, for the right price of course. Sadly we couldnt remove the lock so it requires Armory access to open."
- cost = 5000
+ cost = 7500
contraband = TRUE
contains = list(/obj/item/reagent_containers/food/snacks/rationpack,
/obj/item/ammo_box/a762,
@@ -192,12 +192,11 @@
/obj/item/clothing/mask/russian_balaclava,
/obj/item/clothing/head/helmet/rus_ushanka,
/obj/item/clothing/suit/armor/vest/russian_coat,
- /obj/item/gun/ballistic/shotgun/boltaction,
/obj/item/gun/ballistic/shotgun/boltaction)
crate_name = "surplus military crate"
/datum/supply_pack/security/armory/russian/fill(obj/structure/closet/crate/C)
- for(var/i in 1 to 10)
+ for(var/i in 1 to 5)
var/item = pick(contains)
new item(C)
@@ -218,7 +217,7 @@
crate_name = "swat crate"
/datum/supply_pack/security/armory/swattasers //Lesser AEG tbh
- name = "SWAT tatical tasers Crate"
+ name = "SWAT tactical tasers Crate"
desc = "Contains two tactical energy gun, these guns are able to tase, disable and lethal as well as hold a seclight. Requires Armory access to open."
cost = 7000
contains = list(/obj/item/gun/energy/e_gun/stun,
diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm
index 4a64979502..c559e7925a 100644
--- a/code/modules/cargo/packs/costumes_toys.dm
+++ b/code/modules/cargo/packs/costumes_toys.dm
@@ -63,6 +63,7 @@
/obj/item/toy/cards/deck/syndicate,
/obj/item/reagent_containers/food/drinks/bottle/absinthe,
/obj/item/clothing/under/syndicate/tacticool,
+ /obj/item/clothing/under/syndicate/skirt,
/obj/item/clothing/under/syndicate,
/obj/item/suppressor,
/obj/item/storage/fancy/cigarettes/cigpack_syndicate,
diff --git a/code/modules/cargo/packs/emergency.dm b/code/modules/cargo/packs/emergency.dm
index e32811f2d0..be81da3b92 100644
--- a/code/modules/cargo/packs/emergency.dm
+++ b/code/modules/cargo/packs/emergency.dm
@@ -130,7 +130,7 @@
/datum/supply_pack/emergency/bomb
name = "Explosive Emergency Crate"
- desc = "Science gone bonkers? Beeping behind the airlock? Buy now and be the hero the station des... I mean needs! (Time not included.)"
+ desc = "Science gone bonkers? Beeping behind the airlock? Buy now and become the hero the station des... I mean needs! Time not included, but a full bomb suit and hood, as well as a mask and defusal kit are! Non-Nuclear ordnances only."
cost = 1500
contains = list(/obj/item/clothing/head/bomb_hood,
/obj/item/clothing/suit/bomb_suit,
diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm
index ea327ae820..5d02bbe60f 100644
--- a/code/modules/cargo/packs/medical.dm
+++ b/code/modules/cargo/packs/medical.dm
@@ -88,6 +88,7 @@
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/hardsuit/medical)
crate_name = "medical hardsuit"
+ crate_type = /obj/structure/closet/crate/secure/medical
/datum/supply_pack/medical/supplies
name = "Medical Supplies Crate"
@@ -125,7 +126,7 @@
/obj/item/reagent_containers/medspray/synthflesh,
/obj/item/reagent_containers/medspray/sterilizine)
crate_name = "medco surgery tools"
- crate_type = /obj/structure/closet/crate/medical
+ crate_type = /obj/structure/closet/crate/secure/medical
/datum/supply_pack/medical/surgery
name = "Surgical Supplies Crate"
diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm
index 4aa991fc3f..cdac6f49f2 100644
--- a/code/modules/cargo/packs/organic.dm
+++ b/code/modules/cargo/packs/organic.dm
@@ -193,6 +193,7 @@
/obj/item/reagent_containers/food/snacks/meat/slab/bear,
/obj/item/reagent_containers/food/snacks/meat/slab/xeno,
/obj/item/reagent_containers/food/snacks/meat/slab/spider,
+ /obj/item/reagent_containers/food/snacks/meat/rawcrab,
/obj/item/reagent_containers/food/snacks/meat/rawbacon,
/obj/item/reagent_containers/food/snacks/spiderleg,
/obj/item/reagent_containers/food/snacks/carpmeat,
@@ -327,7 +328,7 @@
/datum/supply_pack/organic/seeds
name = "Seeds Crate"
- desc = "Big things have small beginnings. Contains thirteen different seeds."
+ desc = "Big things have small beginnings. Contains fourteen different seeds."
cost = 1250
contains = list(/obj/item/seeds/chili,
/obj/item/seeds/berry,
diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm
index 8852a7e945..e6671a02ea 100644
--- a/code/modules/cargo/packs/science.dm
+++ b/code/modules/cargo/packs/science.dm
@@ -84,7 +84,7 @@
/datum/supply_pack/science/glasswork
name = "Glass Blower Kit Crate"
- desc = "Learn and make glassworks of usefull things for a profit! Contains glassworking tools and blowing rods. Glass not included."
+ desc = "Learn and make glassworks of useful things for a profit! Contains glassworking tools and blowing rods. Glass not included."
cost = 1000
contains = list(/obj/item/glasswork/glasskit,
/obj/item/glasswork/glasskit,
@@ -111,9 +111,9 @@
/datum/supply_pack/science/nuke_b_gone
name = "Nuke Defusal Kit"
desc = "Contains set of tools to defuse a nuke."
- cost = 7500 //Usefull for traitors/nukies that fucked up
+ cost = 7500 //Useful for traitors/nukies that fucked up
dangerous = TRUE
- DropPodOnly = TRUE
+ hidden = TRUE
contains = list(/obj/item/nuke_core_container/nt,
/obj/item/screwdriver/nuke/nt,
/obj/item/paper/guides/nt/nuke_instructions)
@@ -194,7 +194,7 @@
/datum/supply_pack/science/supermater
name = "Supermatter Extraction Tools Crate"
desc = "Contains a set of tools to extract a sliver of supermatter. Consult your CE today!"
- cost = 7500 //Usefull for traitors that fucked up
+ cost = 7500 //Useful for traitors that fucked up
hidden = TRUE
contains = list(/obj/item/nuke_core_container/supermatter,
/obj/item/scalpel/supermatter,
diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm
index fd7e07a66c..90bc837767 100644
--- a/code/modules/cargo/packs/security.dm
+++ b/code/modules/cargo/packs/security.dm
@@ -103,7 +103,7 @@
desc = "An old russian Minutemen crate, comes with a full russian outfit, a mosin and a stripper clip."
contraband = TRUE
access = FALSE
- cost = 5500 //
+ cost = 6500 //
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/head/ushanka,
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index e05cee3487..dc550179f8 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -737,13 +737,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
message_admins("Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.")
ip_intel = res.intel
-/client/Click(atom/object, atom/location, control, params)
+/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE)
var/ab = FALSE
var/list/L = params2list(params)
if (object && object == middragatom && L["left"])
ab = max(0, 5 SECONDS-(world.time-middragtime)*0.1)
var/mcl = CONFIG_GET(number/minute_click_limit)
- if (!holder && mcl)
+ if (!holder && !ignore_spam && mcl)
var/minute = round(world.time, 600)
if (!clicklimiter)
clicklimiter = new(LIMITER_SIZE)
@@ -768,7 +768,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
return
var/scl = CONFIG_GET(number/second_click_limit)
- if (!holder && scl)
+ if (!holder && !ignore_spam && scl)
var/second = round(world.time, 10)
if (!clicklimiter)
clicklimiter = new(LIMITER_SIZE)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
index 71becf0542..4fc55ba4c3 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
@@ -319,7 +319,7 @@
/obj/machinery/icecream_vat/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
beaker.forceMove(drop_location())
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
user.put_in_hands(beaker)
if(new_beaker)
beaker = new_beaker
diff --git a/code/modules/mob/dead/observer/login.dm b/code/modules/mob/dead/observer/login.dm
index 1b328dbc69..8daf8ec052 100644
--- a/code/modules/mob/dead/observer/login.dm
+++ b/code/modules/mob/dead/observer/login.dm
@@ -6,7 +6,7 @@
var/preferred_form = null
if(IsAdminGhost(src))
- has_unlimited_silicon_privilege = 1
+ silicon_privileges = ALL
if(client.prefs.unlock_content)
preferred_form = client.prefs.ghost_form
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 6460d8331d..b5e9e4f1d7 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -987,3 +987,6 @@
return TRUE
if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS))
return TRUE
+
+/mob/living/carbon/can_hold_items()
+ return TRUE
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index ef3d4cbb98..94e8cd22fa 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -823,9 +823,6 @@
. += dna.species.check_weakness(weapon, attacker)
/mob/living/carbon/human/is_literate()
- return 1
-
-/mob/living/carbon/human/can_hold_items()
return TRUE
/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
@@ -834,7 +831,7 @@
..()
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = 0, stun = 1, distance = 0, message = 1, toxic = 0)
- if(blood && (NOBLOOD in dna.species.species_traits))
+ if(blood && dna?.species && (NOBLOOD in dna.species.species_traits))
if(message)
visible_message("[src] dry heaves!", \
"You try to throw up, but there's nothing in your stomach!")
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index accaab3ac1..57b8f59780 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -20,7 +20,7 @@
/mob/living/carbon/human/proc/checkarmor(obj/item/bodypart/def_zone, d_type)
- if(!d_type)
+ if(!d_type || !def_zone)
return 0
var/protection = 0
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index 1bed3b08d4..b29890a97d 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -71,14 +71,42 @@
if(/obj/item/projectile/energy/florayield)
H.nutrition = min(H.nutrition+30, NUTRITION_LEVEL_FULL)
+
/datum/species/pod/pseudo_weak
name = "Anthromorphic Plant"
id = "podweak"
- limbs_id = "pod"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
mutant_bodyparts = list("mam_tail", "mam_ears", "mam_body_markings", "mam_snouts", "taur", "legs")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
+ limbs_id = "pod"
light_nutrition_gain_factor = 7.5
light_bruteheal = 0.2
light_burnheal = 0.2
light_toxheal = 0.7
+
+/datum/species/pod/pseudo_weak/spec_death(gibbed, mob/living/carbon/human/H)
+ if(H)
+ stop_wagging_tail(H)
+
+/datum/species/pod/pseudo_weak/spec_stun(mob/living/carbon/human/H,amount)
+ if(H)
+ stop_wagging_tail(H)
+ . = ..()
+
+/datum/species/pod/pseudo_weak/can_wag_tail(mob/living/carbon/human/H)
+ return ("mam_tail" in mutant_bodyparts) || ("mam_waggingtail" in mutant_bodyparts)
+
+/datum/species/pod/pseudo_weak/is_wagging_tail(mob/living/carbon/human/H)
+ return ("mam_waggingtail" in mutant_bodyparts)
+
+/datum/species/pod/pseudo_weak/start_wagging_tail(mob/living/carbon/human/H)
+ if("mam_tail" in mutant_bodyparts)
+ mutant_bodyparts -= "mam_tail"
+ mutant_bodyparts |= "mam_waggingtail"
+ H.update_body()
+
+/datum/species/pod/pseudo_weak/stop_wagging_tail(mob/living/carbon/human/H)
+ if("mam_waggingtail" in mutant_bodyparts)
+ mutant_bodyparts -= "mam_waggingtail"
+ mutant_bodyparts |= "mam_tail"
+ H.update_body()
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index bbae050bba..24acccdd2e 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -72,7 +72,7 @@
put_in_hands(I)
update_inv_hands()
if(SLOT_IN_BACKPACK)
- if(!SEND_SIGNAL(back, COMSIG_TRY_STORAGE_INSERT, I, src, TRUE))
+ if(!back || !SEND_SIGNAL(back, COMSIG_TRY_STORAGE_INSERT, I, src, TRUE))
not_handled = TRUE
else
not_handled = TRUE
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 433f6a43b5..ccca90807b 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -357,8 +357,8 @@
if(istype(loc, /obj/structure/closet/crate/coffin)|| istype(loc, /obj/structure/closet/body_bag) || istype(loc, /obj/structure/bodycontainer))
return
- // No decay if formaldehyde in corpse or when the corpse is charred
- if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || HAS_TRAIT(src, TRAIT_HUSK))
+ // No decay if formaldehyde/preservahyde in corpse or when the corpse is charred
+ if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || HAS_TRAIT(src, TRAIT_HUSK) || reagents.has_reagent(/datum/reagent/preservahyde, 1))
return
// Also no decay if corpse chilled or not organic/undead
@@ -397,7 +397,7 @@
if(O)
O.on_life()
else
- if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1)) // No organ decay if the body contains formaldehyde.
+ if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || reagents.has_reagent(/datum/reagent/preservahyde, 1)) // No organ decay if the body contains formaldehyde. Or preservahyde.
return
for(var/V in internal_organs)
var/obj/item/organ/O = V
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 409665f792..ee78a8a5d6 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -11,6 +11,7 @@
health = 500
maxHealth = 500
layer = BELOW_MOB_LAYER
+ silicon_privileges = PRIVILEDGES_PAI
var/datum/element/mob_holder/current_mob_holder //because only a few of their chassis can be actually held.
var/network = "ss13"
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 72e98e348c..531faff056 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -1,6 +1,6 @@
/mob/living/silicon
gender = NEUTER
- has_unlimited_silicon_privilege = 1
+ silicon_privileges = PRIVILEDGES_SILICON
verb_say = "states"
verb_ask = "queries"
verb_exclaim = "declares"
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 7da0ad13da..d5e6f687fb 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -15,7 +15,7 @@
maxbodytemp = INFINITY
minbodytemp = 0
blood_volume = 0
- has_unlimited_silicon_privilege = 1
+ silicon_privileges = PRIVILEDGES_BOT
sentience_type = SENTIENCE_ARTIFICIAL
status_flags = NONE //no default canpush
verb_say = "states"
@@ -194,10 +194,12 @@
if(locked) //First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again.
locked = FALSE
emagged = 1
- to_chat(user, "You bypass [src]'s controls.")
+ if(user)
+ to_chat(user, "You bypass [src]'s controls.")
return TRUE
if(!open)
- to_chat(user, "You need to open maintenance panel first!")
+ if(user)
+ to_chat(user, "You need to open maintenance panel first!")
return
emagged = 2
remote_disabled = 1 //Manually emagging the bot locks out the AI built in panel.
@@ -205,7 +207,8 @@
bot_reset()
turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP.
to_chat(src, "(#$*#$^^( OVERRIDE DETECTED")
- log_combat(user, src, "emagged")
+ if(user)
+ log_combat(user, src, "emagged")
return TRUE
/mob/living/simple_animal/bot/examine(mob/user)
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index b23f3f2baa..b5aa8b6967 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -123,7 +123,8 @@
emagged = TRUE
if(!open)
locked = !locked
- to_chat(user, "You [locked ? "lock" : "unlock"] [src]'s controls!")
+ if(user)
+ to_chat(user, "You [locked ? "lock" : "unlock"] [src]'s controls!")
flick("mulebot-emagged", src)
playsound(src, "sparks", 100, FALSE)
@@ -180,7 +181,7 @@
var/list/data = list()
data["on"] = on
data["locked"] = locked
- data["siliconUser"] = user.has_unlimited_silicon_privilege
+ data["siliconUser"] = hasSiliconAccessInArea(usr)
data["mode"] = mode ? mode_name[mode] : "Ready"
data["modeStatus"] = ""
switch(mode)
@@ -205,11 +206,12 @@
return data
/mob/living/simple_animal/bot/mulebot/ui_act(action, params)
- if(..() || (locked && !usr.has_unlimited_silicon_privilege))
+ var/silicon_access = hasSiliconAccessInArea(usr)
+ if(..() || (locked && silicon_access))
return
switch(action)
if("lock")
- if(usr.has_unlimited_silicon_privilege)
+ if(silicon_access)
locked = !locked
. = TRUE
if("power")
@@ -766,4 +768,3 @@
/obj/machinery/bot_core/mulebot
req_access = list(ACCESS_CARGO)
-
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 7dd373b49f..43149e6ba7 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -41,7 +41,7 @@
bubble_icon = "machine"
initial_language_holder = /datum/language_holder/drone
mob_size = MOB_SIZE_SMALL
- has_unlimited_silicon_privilege = 1
+ silicon_privileges = PRIVILEDGES_DRONE
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
unique_name = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index 5ad787b143..2bab332cd0 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -126,7 +126,7 @@
// This loop will, at most, loop twice.
for(var/atom/check in check_list)
for(var/mob/living/M in viewers(world.view + 1, check) - src)
- if(M.client && CanAttack(M) && !M.has_unlimited_silicon_privilege)
+ if(M.client && CanAttack(M) && !M.silicon_privileges)
if(!M.eye_blind)
return M
for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 6d5ae72e77..c45f6eec13 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -95,7 +95,7 @@
var/digitalinvis = 0 //Are they ivisible to the AI?
var/image/digitaldisguise = null //what does the AI see instead of them?
- var/has_unlimited_silicon_privilege = 0 // Can they interact with station electronics
+ var/silicon_privileges = NONE // Can they interact with station electronics
var/obj/control_object //Used by admins to possess objects. All mobs should have this var
var/atom/movable/remote_control //Calls relaymove() to whatever it is
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index b25531f0e0..12d74d2f8f 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -406,8 +406,8 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return
return TRUE
-/atom/proc/hasSiliconAccessInArea(mob/user)
- return user && (issilicon(user) || (user.siliconaccesstoggle && (get_area(src) in user.siliconaccessareas)))
+/atom/proc/hasSiliconAccessInArea(mob/user, flags = PRIVILEDGES_SILICON)
+ return user.silicon_privileges & (flags) || (user.siliconaccesstoggle && (get_area(src) in user.siliconaccessareas))
/mob/proc/toggleSiliconAccessArea(area/area)
if (area in siliconaccessareas)
@@ -555,4 +555,4 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
//Can the mob see reagents inside of containers?
/mob/proc/can_see_reagents()
- return stat == DEAD || has_unlimited_silicon_privilege //Dead guys and silicons can always see reagents
+ return stat == DEAD || silicon_privileges //Dead guys and silicons can always see reagents
diff --git a/code/modules/oracle_ui/hookup_procs.dm b/code/modules/oracle_ui/hookup_procs.dm
index 18d7bbfd8c..30db9d92b9 100644
--- a/code/modules/oracle_ui/hookup_procs.dm
+++ b/code/modules/oracle_ui/hookup_procs.dm
@@ -5,7 +5,7 @@
return "Default Implementation"
/datum/proc/oui_canuse(mob/user)
- if(isobserver(user) && !user.has_unlimited_silicon_privilege)
+ if(isobserver(user) && !user.silicon_privileges)
return FALSE
return oui_canview(user)
@@ -35,7 +35,7 @@
return ..()
/obj/machinery/oui_canview(mob/user)
- if(user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user))
+ if(hasSiliconAccessInArea(user, ALL))
return TRUE
if(!can_interact(user))
return FALSE
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 982afa49c8..db3e3c83c6 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -846,7 +846,7 @@
return
/obj/machinery/power/apc/oui_canview(mob/user)
- if(user.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(user))
+ if(area.hasSiliconAccessInArea(user)) //some APCs are mapped outside their assigned area, so this is required.
return TRUE
return ..()
@@ -864,7 +864,7 @@
if (H && !H.stealthmode && H.toggled)
abilitiesavail = TRUE
var/list/data = list(
- "locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user),
+ "locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE),
"lock_nightshift" = nightshift_requires_auth,
"failTime" = failure_timer,
"isOperating" = operating,
@@ -874,7 +874,7 @@
"chargingStatus" = charging,
"totalLoad" = DisplayPower(lastused_total),
"coverLocked" = coverlocked,
- "siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console() || area.hasSiliconAccessInArea(user),
+ "siliconUser" = user.using_power_flow_console() || area.hasSiliconAccessInArea(user),
"malfStatus" = get_malf_status(user),
"emergencyLights" = !emergency_lights,
"nightshiftLights" = nightshift_lights,
@@ -951,7 +951,7 @@
return TRUE
if (user == hijacker || (area.hasSiliconAccessInArea(user) && !aidisabled))
return TRUE
- if(user.has_unlimited_silicon_privilege)
+ if(user.silicon_privileges & PRIVILEDGES_SILICON)
var/mob/living/silicon/ai/AI = user
var/mob/living/silicon/robot/robot = user
if (src.aidisabled || malfhack && istype(malfai) && ((istype(AI) && (malfai!=AI && malfai != AI.parent)) || (istype(robot) && (robot in malfai.connected_robots))))
@@ -985,7 +985,7 @@
if (action == "hijack" && can_use(usr, 1)) //don't need auth for hijack button
hijack(usr)
return
- var/authorized = (!locked || usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr) || (integration_cog && (is_servant_of_ratvar(usr))))
+ var/authorized = (!locked || area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE) || (integration_cog && (is_servant_of_ratvar(usr))))
if((action == "toggle_nightshift") && (!nightshift_requires_auth || authorized))
toggle_nightshift_lights()
return TRUE
@@ -993,7 +993,7 @@
return
switch(action)
if("lock")
- if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr))
+ if(area.hasSiliconAccessInArea(usr))
if((obj_flags & EMAGGED) || (stat & (BROKEN|MAINT)))
to_chat(usr, "The APC does not respond to the command.")
else
@@ -1027,7 +1027,7 @@
update()
return TRUE
if("overload")
- if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr))
+ if(area.hasSiliconAccessInArea(usr))
overload_lighting()
return TRUE
if("hack")
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index e6d44de194..a0eeae1ea9 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -24,7 +24,16 @@
/obj/machinery/power/solar/Initialize(mapload, obj/item/solar_assembly/S)
. = ..()
- Make(S)
+ if(!S)
+ assembly = new /obj/item/solar_assembly
+ assembly.glass_type = new /obj/item/stack/sheet/glass(null, 2)
+ assembly.anchored = TRUE
+ else
+ S.moveToNullspace()
+ assembly = S
+ assembly.glass_type.on_solar_construction(src)
+ obj_integrity = max_integrity
+ update_icon()
connect_to_network()
/obj/machinery/power/solar/Destroy()
@@ -45,17 +54,6 @@
control.connected_panels.Remove(src)
control = null
-/obj/machinery/power/solar/proc/Make(obj/item/solar_assembly/S)
- if(!S)
- S = new /obj/item/solar_assembly
- S.glass_type = new /obj/item/stack/sheet/glass(null, 2)
- S.anchored = TRUE
- else
- S.moveToNullspace()
- S.glass_type.on_solar_construction(src)
- obj_integrity = max_integrity
- update_icon()
-
/obj/machinery/power/solar/crowbar_act(mob/user, obj/item/I)
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
user.visible_message("[user] begins to take the glass off [src].", "You begin to take the glass off [src]...")
@@ -201,7 +199,7 @@
new shard(Tsec)
new shard(Tsec)
else if(glass_type)
- forceMove(glass_type, Tsec)
+ glass_type.forceMove(Tsec)
glass_type = null
/obj/item/solar_assembly/attackby(obj/item/W, mob/user, params)
@@ -226,7 +224,8 @@
var/obj/item/stack/sheet/G = S.change_stack(null, 2)
if(G)
glass_type = G
- playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ G.moveToNullspace()
+ playsound(loc, 'sound/machines/click.ogg', 50, 1)
user.visible_message("[user] places the glass on the solar assembly.", "You place the glass on the solar assembly.")
if(tracker)
new /obj/machinery/power/tracker(get_turf(src), src)
diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm
index c25ece3594..8701dfea7f 100644
--- a/code/modules/power/tracker.dm
+++ b/code/modules/power/tracker.dm
@@ -20,7 +20,15 @@
/obj/machinery/power/tracker/Initialize(mapload, obj/item/solar_assembly/S)
. = ..()
- Make(S)
+ if(!S)
+ assembly = new /obj/item/solar_assembly
+ assembly.glass_type = new /obj/item/stack/sheet/glass(null, 2)
+ assembly.tracker = TRUE
+ assembly.anchored = TRUE
+ else
+ S.moveToNullspace()
+ assembly = S
+ update_icon()
connect_to_network()
/obj/machinery/power/tracker/Destroy()
@@ -41,16 +49,6 @@
control.connected_tracker = null
control = null
-/obj/machinery/power/tracker/proc/Make(obj/item/solar_assembly/S)
- if(!S)
- S = new /obj/item/solar_assembly
- S.glass_type = new /obj/item/stack/sheet/glass(null, 2)
- S.tracker = TRUE
- S.anchored = TRUE
- else
- S.moveToNullspace()
- update_icon()
-
//updates the tracker icon and the facing angle for the control computer
/obj/machinery/power/tracker/proc/set_angle(angle)
sun_angle = angle
diff --git a/code/modules/projectiles/ammunition/caseless/arrow.dm b/code/modules/projectiles/ammunition/caseless/arrow.dm
index e0ca637a8b..57f47e2ad9 100644
--- a/code/modules/projectiles/ammunition/caseless/arrow.dm
+++ b/code/modules/projectiles/ammunition/caseless/arrow.dm
@@ -5,4 +5,22 @@
caliber = "arrow"
icon_state = "arrow"
throwforce = 3 //good luck hitting someone with the pointy end of the arrow
- throw_speed = 3
\ No newline at end of file
+ throw_speed = 3
+
+/obj/item/ammo_casing/caseless/arrow/ashen
+ name = "ashen arrow"
+ desc = "Fire harderned wooden arrow."
+ icon_state = "asharrow"
+ projectile_type = /obj/item/projectile/bullet/reusable/arrow/ashen
+
+/obj/item/ammo_casing/caseless/arrow/bone
+ name = "bone arrow"
+ desc = "Arrow made of bone and sinew. The tip is sharp enough to pierce into a goliath plate."
+ icon_state = "bonearrow"
+ projectile_type = /obj/item/projectile/bullet/reusable/arrow/bone
+
+/obj/item/ammo_casing/caseless/arrow/bronze
+ name = "bronze arrow"
+ desc = "Bronze tipped arrow."
+ icon_state = "bronzearrow"
+ projectile_type = /obj/item/projectile/bullet/reusable/arrow/bronze
diff --git a/code/modules/projectiles/guns/ballistic/bow.dm b/code/modules/projectiles/guns/ballistic/bow.dm
index 448e2915d9..540ea722b9 100644
--- a/code/modules/projectiles/guns/ballistic/bow.dm
+++ b/code/modules/projectiles/guns/ballistic/bow.dm
@@ -50,4 +50,19 @@
icon_state = "bow_[get_ammo() ? (chambered ? "firing" : "loaded") : "unloaded"]"
/obj/item/gun/ballistic/bow/can_shoot()
- return chambered
\ No newline at end of file
+ return chambered
+
+/obj/item/gun/ballistic/bow/ashen
+ name = "bone bow"
+ desc = "Some sort of primitive projectile weapon made of bone and sinew. Used to fire arrows."
+ icon_state = "ashenbow"
+ item_state = "ashenbow"
+ force = 8
+
+/obj/item/gun/ballistic/bow/pipe
+ name = "pipe bow"
+ desc = "Some sort of pipe made projectile weapon made of a silk string and lots of bending. Used to fire arrows."
+ icon_state = "pipebow"
+ item_state = "pipebow"
+ inaccuracy_modifier = 1.1 //Made of pipe and in a rush
+ force = 0
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index be43bc48fd..401678512b 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -67,7 +67,8 @@
/obj/item/gun/energy/Destroy()
if(flags_1 & INITIALIZED_1)
QDEL_NULL(cell)
- QDEL_LIST(ammo_type)
+ if(!(flags_1 & HOLOGRAM_1)) //holodeck stuff.
+ QDEL_LIST(ammo_type)
STOP_PROCESSING(SSobj, src)
return ..()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 4521e4ea13..139f5a051c 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -52,7 +52,6 @@
var/hitscan = FALSE //Whether this is hitscan. If it is, speed is basically ignored.
var/list/beam_segments //assoc list of datum/point or datum/point/vector, start = end. Used for hitscan effect generation.
var/datum/point/beam_index
- var/turf/hitscan_last //last turf touched during hitscanning.
var/tracer_type
var/muzzle_type
var/impact_type
@@ -492,8 +491,6 @@
process_homing()
var/forcemoved = FALSE
for(var/i in 1 to SSprojectiles.global_iterations_per_move)
- if(QDELETED(src))
- return
trajectory.increment(trajectory_multiplier)
var/turf/T = trajectory.return_turf()
if(!istype(T))
@@ -506,14 +503,16 @@
forceMove(T)
trajectory_ignore_forcemove = FALSE
after_z_change(old, loc)
+ forcemoved = TRUE
+ if(QDELETED(src))
+ return
if(!hitscanning)
pixel_x = trajectory.return_px()
pixel_y = trajectory.return_py()
- forcemoved = TRUE
- hitscan_last = loc
else if(T != loc)
step_towards(src, T)
- hitscan_last = loc
+ if(QDELETED(src))
+ return
if(!hitscanning && !forcemoved)
pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier * SSprojectiles.global_iterations_per_move
pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier * SSprojectiles.global_iterations_per_move
diff --git a/code/modules/projectiles/projectile/energy/tesla.dm b/code/modules/projectiles/projectile/energy/tesla.dm
index 43c31816cd..2439cee429 100644
--- a/code/modules/projectiles/projectile/energy/tesla.dm
+++ b/code/modules/projectiles/projectile/energy/tesla.dm
@@ -7,10 +7,11 @@
var/zap_range = 3
var/power = 10000
-/obj/item/projectile/energy/tesla/fire(setAngle)
- if(firer)
- chain = firer.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
- ..()
+/obj/item/projectile/energy/tesla/fire(setAngle, atom/direct_target)
+ var/atom/source = fired_from || firer
+ if(source)
+ chain = source.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
+ return ..()
/obj/item/projectile/energy/tesla/on_hit(atom/target)
. = ..()
diff --git a/code/modules/projectiles/projectile/reusable/arrow.dm b/code/modules/projectiles/projectile/reusable/arrow.dm
index f1c9638fd9..d00de79eb1 100644
--- a/code/modules/projectiles/projectile/reusable/arrow.dm
+++ b/code/modules/projectiles/projectile/reusable/arrow.dm
@@ -3,4 +3,23 @@
desc = "Woosh!"
damage = 15
icon_state = "arrow"
- ammo_type = /obj/item/ammo_casing/caseless/arrow
\ No newline at end of file
+ ammo_type = /obj/item/ammo_casing/caseless/arrow
+
+/obj/item/projectile/bullet/reusable/arrow/ashen
+ name = "ashen arrow"
+ desc = "Fire harderned arrow."
+ damage = 25
+ ammo_type = /obj/item/ammo_casing/caseless/arrow/ashen
+
+/obj/item/projectile/bullet/reusable/arrow/bone //AP for ashwalkers
+ name = "bone arrow"
+ desc = "Arrow made of bone and sinew."
+ damage = 35
+ armour_penetration = 40
+ ammo_type = /obj/item/ammo_casing/caseless/arrow/bone
+
+/obj/item/projectile/bullet/reusable/arrow/bronze //Just some AP shots
+ name = "bronze arrow"
+ desc = "Bronze tipped arrow."
+ armour_penetration = 10
+ ammo_type = /obj/item/ammo_casing/caseless/arrow/bronze
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index ed68c25cb6..be15bb70cf 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -408,7 +408,7 @@
if(beaker)
var/obj/item/reagent_containers/B = beaker
B.forceMove(drop_location())
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
user.put_in_hands(B)
if(new_beaker)
beaker = new_beaker
diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm
index 189d09b06f..4c4d0fdb6e 100644
--- a/code/modules/reagents/chemistry/machinery/chem_heater.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm
@@ -38,7 +38,7 @@
/obj/machinery/chem_heater/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
beaker.forceMove(drop_location())
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
user.put_in_hands(beaker)
if(new_beaker)
beaker = new_beaker
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 66c663e2e4..abfd00ed90 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -129,7 +129,7 @@
if(beaker)
var/obj/item/reagent_containers/B = beaker
B.forceMove(drop_location())
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
user.put_in_hands(B)
if(new_beaker)
beaker = new_beaker
@@ -139,7 +139,7 @@
if(bottle)
var/obj/item/storage/pill_bottle/B = bottle
B.forceMove(drop_location())
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
user.put_in_hands(B)
else
adjust_item_drop_location(B)
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 3dea44cf40..7b25aa769d 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -192,7 +192,7 @@
update_icon()
var/turf/source_turf = get_turf(src)
log_virus("A culture bottle was printed for the virus [A.admin_details()] at [loc_name(source_turf)] by [key_name(usr)]")
-
+
. = TRUE
if("create_vaccine_bottle")
wait = TRUE
@@ -202,9 +202,9 @@
var/obj/item/reagent_containers/glass/bottle/B = new(drop_location())
B.name = "[D.name] vaccine bottle"
B.reagents.add_reagent(/datum/reagent/vaccine, 15, list(id))
-
+
update_icon()
-
+
. = TRUE
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
@@ -229,7 +229,7 @@
/obj/machinery/computer/pandemic/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
if(!user.put_in_hands(beaker))
beaker.forceMove(drop_location())
if(new_beaker)
diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
index b17c2dfb37..85cdc33e72 100644
--- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
+++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
@@ -75,7 +75,7 @@
/obj/machinery/reagentgrinder/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
beaker.forceMove(drop_location())
- if(user && Adjacent(user) && !issiliconoradminghost(user))
+ if(user && Adjacent(user) && user.can_hold_items())
user.put_in_hands(beaker)
if(new_beaker)
beaker = new_beaker
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 6d37f30884..0a040a4f17 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -1482,14 +1482,14 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/polypyr //This is intended to be an ingredient in advanced chems.
name = "Polypyrylium Oligomers"
- description = "A�purple mixture of short polyelectrolyte chains not easily synthesized in the laboratory. It is valued as an intermediate in the synthesis of the cutting edge pharmaceuticals."
+ description = "A purple mixture of short polyelectrolyte chains not easily synthesized in the laboratory. It is valued as an intermediate in the synthesis of the cutting edge pharmaceuticals."
reagent_state = SOLID
color = "#9423FF"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
overdose_threshold = 50
taste_description = "numbing bitterness"
-/datum/reagent/medicine/polypyr/on_mob_life(mob/living/carbon/M) //I w�nted a collection of small positive effects, this is as hard to obtain as coniine after all.
+/datum/reagent/medicine/polypyr/on_mob_life(mob/living/carbon/M) //I wanted a collection of small positive effects, this is as hard to obtain as coniine after all.
M.adjustOrganLoss(ORGAN_SLOT_LUNGS, -0.25)
M.adjustBruteLoss(-0.35, 0)
if(prob(50))
@@ -1511,4 +1511,3 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
M.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.5)
..()
. = 1
-
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 0e9c148446..adc30ecdc9 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -2108,3 +2108,10 @@
to_chat(M, "You feel like playing with your [G.name]!")
..()
+
+/datum/reagent/preservahyde
+ name = "Preservahyde"
+ description = "A powerful preservation agent, utilizing the preservative effects of formaldehyde with significantly less of the histamine."
+ reagent_state = LIQUID
+ color = "#f7685e"
+ metabolization_rate = REAGENTS_METABOLISM * 0.25
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index e649caafb5..946cb1307c 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -504,7 +504,7 @@
toxpwr = 0
/datum/reagent/toxin/itching_powder/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
- if(method == TOUCH || method == VAPOR)
+ if((method == TOUCH || method == VAPOR) && M.reagents)
M.reagents.add_reagent(/datum/reagent/toxin/itching_powder, reac_volume)
/datum/reagent/toxin/itching_powder/on_mob_life(mob/living/carbon/M)
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index d92e7819e4..57748acb1a 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -47,6 +47,12 @@
results = list(/datum/reagent/consumable/sodiumchloride = 3)
required_reagents = list(/datum/reagent/water = 1, /datum/reagent/sodium = 1, /datum/reagent/chlorine = 1)
+/datum/chemical_reaction/preservahyde
+ name = "Preservahyde"
+ id = "preservahyde"
+ results = list(/datum/reagent/preservahyde = 3)
+ required_reagents = list(/datum/reagent/water = 1, /datum/reagent/toxin/formaldehyde = 1, /datum/reagent/bromine = 1)
+
/datum/chemical_reaction/plasmasolidification
name = "Solid Plasma"
id = "solidplasma"
diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm
index c05f4f3e78..e4741bb858 100644
--- a/code/modules/reagents/reagent_containers/bottle.dm
+++ b/code/modules/reagents/reagent_containers/bottle.dm
@@ -431,4 +431,4 @@
/obj/item/reagent_containers/glass/bottle/hexacamphor
name = "Hexacamphor bottle"
desc = "A bottle of strong anaphrodisiac. Reduces libido."
- list_reagents = list(/datum/reagent/drug/anaphrodisiacplus = 30)
\ No newline at end of file
+ list_reagents = list(/datum/reagent/drug/anaphrodisiacplus = 30)
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index fd4282b1b0..f29b785c95 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -95,7 +95,7 @@
ignore_flags = 1 //so you can medipen through hardsuits
reagent_flags = DRAWABLE
flags_1 = null
- list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/toxin/formaldehyde = 3)
+ list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/preservahyde = 3)
/obj/item/reagent_containers/hypospray/medipen/suicide_act(mob/living/carbon/user)
user.visible_message("[user] begins to choke on \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
diff --git a/code/modules/research/designs/biogenerator_designs.dm b/code/modules/research/designs/biogenerator_designs.dm
index dd55697bee..ab0460974c 100644
--- a/code/modules/research/designs/biogenerator_designs.dm
+++ b/code/modules/research/designs/biogenerator_designs.dm
@@ -3,7 +3,7 @@
///////////////////////////////////
/datum/design/milk
- name = "10 Milk"
+ name = "10u Milk"
id = "milk"
build_type = BIOGENERATOR
materials = list(MAT_BIOMASS = 20)
@@ -11,7 +11,7 @@
category = list("initial","Food")
/datum/design/cream
- name = "10 Cream"
+ name = "10u Cream"
id = "cream"
build_type = BIOGENERATOR
materials = list(MAT_BIOMASS = 30)
@@ -123,6 +123,22 @@
build_path = /obj/item/reagent_containers/glass/bottle/killer/pestkiller
category = list("initial","Botany Chemicals")
+/datum/design/ammonia
+ name = "10u Ammonia"
+ id = "ammonia_biogen"
+ build_type = BIOGENERATOR
+ materials = list(MAT_BIOMASS = 25)
+ make_reagents = list(/datum/reagent/ammonia = 10)
+ category = list("initial","Botany Chemicals")
+
+/datum/design/saltpetre
+ name = "10u Saltpetre"
+ id = "saltpetre_biogen"
+ build_type = BIOGENERATOR
+ materials = list(MAT_BIOMASS = 75)
+ make_reagents = list(/datum/reagent/saltpetre = 10)
+ category = list("initial","Botany Chemicals")
+
/datum/design/botany_bottle
name = "Empty Bottle"
id = "botany_bottle"
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index 0838e70bfd..9efbe58a29 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -890,8 +890,8 @@ datum/status_effect/stabilized/blue/on_remove()
healing_types += TOX
if(owner.getCloneLoss() > 0)
healing_types += CLONE
-
- owner.apply_damage_type(-heal_amount, damagetype=pick(healing_types))
+ if(length(healing_types))
+ owner.apply_damage_type(-heal_amount, damagetype=pick(healing_types))
owner.nutrition += 3
M.adjustCloneLoss(heal_amount * 1.2) //This way, two people can't just convert each other's damage away.
else
diff --git a/code/modules/spells/spell_types/bloodcrawl.dm b/code/modules/spells/spell_types/bloodcrawl.dm
index e4c33380b2..49d73b445b 100644
--- a/code/modules/spells/spell_types/bloodcrawl.dm
+++ b/code/modules/spells/spell_types/bloodcrawl.dm
@@ -13,6 +13,7 @@
action_icon_state = "bloodcrawl"
action_background_icon_state = "bg_demon"
var/phased = 0
+ charge_max = 6
/obj/effect/proc_holder/spell/bloodcrawl/choose_targets(mob/user = usr)
for(var/obj/effect/decal/cleanable/target in range(range, get_turf(user)))
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 44e92e464b..bdd1a444bb 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -56,7 +56,7 @@
var/mob/living/carbon/human/H = C
H.eye_color = old_eye_color
if(!special)
- H.dna.species.handle_body()
+ H.dna.species.handle_body(H)
if(!special)
C.update_tint()
C.update_sight()
diff --git a/html/changelogs/AutoChangeLog-pr-10904.yml b/html/changelogs/AutoChangeLog-pr-10904.yml
new file mode 100644
index 0000000000..112c0bc593
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10904.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - rscadd: "The ships often crashed by Free Golems on Lavaland now have GPSes. They're off, by default, but an awakening Golem could easily turn one on."
diff --git a/html/changelogs/AutoChangeLog-pr-10910.yml b/html/changelogs/AutoChangeLog-pr-10910.yml
new file mode 100644
index 0000000000..2b11650c80
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10910.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed a little issue with sleeper UI and blood types."
diff --git a/html/changelogs/AutoChangeLog-pr-10953.yml b/html/changelogs/AutoChangeLog-pr-10953.yml
new file mode 100644
index 0000000000..67c2c915ad
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10953.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Missing words replacement file for the gondola mask."
diff --git a/html/changelogs/AutoChangeLog-pr-10980.yml b/html/changelogs/AutoChangeLog-pr-10980.yml
new file mode 100644
index 0000000000..3701aea6e1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10980.yml
@@ -0,0 +1,7 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "Medical locked crates"
+ - balance: "Russian gear crates have less gear in some cases but all will cost more"
+ - bugfix: "Medical locked crates that were not locked"
+ - spellcheck: "Crates that were out of date are corrected"
diff --git a/html/changelogs/AutoChangeLog-pr-11082.yml b/html/changelogs/AutoChangeLog-pr-11082.yml
new file mode 100644
index 0000000000..89d9b4ca52
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11082.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - rscadd: "Preservahyde! Made with water, bromine, and formaldehyde, it doesn't decay into histamine. Instead, it just prevents your organs from rotting into nothing."
diff --git a/html/changelogs/AutoChangeLog-pr-11083.yml b/html/changelogs/AutoChangeLog-pr-11083.yml
new file mode 100644
index 0000000000..757d9fcb63
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11083.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - balance: "You can now purify eldritch longswords with a bible. This creates purified longswords, which do not have anti-magic properties, but are still good for swinging at cultists."
diff --git a/html/changelogs/AutoChangeLog-pr-11087.yml b/html/changelogs/AutoChangeLog-pr-11087.yml
new file mode 100644
index 0000000000..179ef6a2b7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11087.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed solar panels/trackers (de)construction being a bit wonky."
diff --git a/html/changelogs/AutoChangeLog-pr-11091.yml b/html/changelogs/AutoChangeLog-pr-11091.yml
new file mode 100644
index 0000000000..5d43d7dbdf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11091.yml
@@ -0,0 +1,5 @@
+author: "BlueWildrose"
+delete-after: True
+changes:
+ - bugfix: "podpeople tail wagging"
+ - tweak: "lifebringer ghost role fixes"
diff --git a/html/changelogs/AutoChangeLog-pr-11098.yml b/html/changelogs/AutoChangeLog-pr-11098.yml
new file mode 100644
index 0000000000..5ca7b7dd1e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11098.yml
@@ -0,0 +1,4 @@
+author: "Raiq & Linzolle"
+delete-after: True
+changes:
+ - rscadd: "Bone bow - Ash walkers crafting , bone arrows - Ash walkers crafting, silk string used in bow crafting, harden arrows - Ash walkers crafting, ash walker only crafting book, basic pipe bow, and bow & arrow selling. Quivers for ash walkers as well, just to hold some arrows well out on the hunt!"
diff --git a/html/changelogs/AutoChangeLog-pr-11103.yml b/html/changelogs/AutoChangeLog-pr-11103.yml
new file mode 100644
index 0000000000..f38e23f76e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11103.yml
@@ -0,0 +1,5 @@
+author: "PersianXerxes"
+delete-after: True
+changes:
+ - rscadd: "Better clarified the comment explaining the contraband tag."
+ - tweak: "Cargo nuclear defusal kits now require an emag'd drop pod console to be purchased."
diff --git a/html/changelogs/AutoChangeLog-pr-11113.yml b/html/changelogs/AutoChangeLog-pr-11113.yml
new file mode 100644
index 0000000000..b3c0bb34a8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11113.yml
@@ -0,0 +1,4 @@
+author: "CameronWoof"
+delete-after: True
+changes:
+ - rscadd: "Ammonia and saltpetre can now be made at the biogenerator."
diff --git a/html/changelogs/AutoChangeLog-pr-11131.yml b/html/changelogs/AutoChangeLog-pr-11131.yml
new file mode 100644
index 0000000000..9a14049c2f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11131.yml
@@ -0,0 +1,4 @@
+author: "Seris02"
+delete-after: True
+changes:
+ - balance: "bloodcrawl's cooldown"
diff --git a/html/changelogs/AutoChangeLog-pr-11133.yml b/html/changelogs/AutoChangeLog-pr-11133.yml
new file mode 100644
index 0000000000..8cedc300c7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11133.yml
@@ -0,0 +1,5 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - balance: "Nerfed the fermenting barrel export industry."
+ - tweak: "Reagent dispensers selling price no longer takes in account the reagents volume. It's already handled by reagents export."
diff --git a/html/changelogs/AutoChangeLog-pr-11134.yml b/html/changelogs/AutoChangeLog-pr-11134.yml
new file mode 100644
index 0000000000..8ec6c97164
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11134.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - bugfix: "mechs with stock parts now have icons"
diff --git a/html/changelogs/AutoChangeLog-pr-11138.yml b/html/changelogs/AutoChangeLog-pr-11138.yml
new file mode 100644
index 0000000000..fd0e53bb73
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11138.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - tweak: "the game's built in autoclicker aka CanMobAutoclick no longer triggers client/Click()'s anti clickspam guard."
diff --git a/html/changelogs/AutoChangeLog-pr-11145.yml b/html/changelogs/AutoChangeLog-pr-11145.yml
new file mode 100644
index 0000000000..2ad26003fb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11145.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "pAIs are yet again unable to perform certain silicon interactions with machineries yet again."
diff --git a/html/changelogs/AutoChangeLog-pr-11147.yml b/html/changelogs/AutoChangeLog-pr-11147.yml
new file mode 100644
index 0000000000..0978b2b184
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11147.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - tweak: "Supermatter sabotage objective no longer shows up with no supermatter"
diff --git a/icons/mecha/mech_construction.dmi b/icons/mecha/mech_construction.dmi
index 42cc8eeb57..d7f0f3e054 100644
Binary files a/icons/mecha/mech_construction.dmi and b/icons/mecha/mech_construction.dmi differ
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index 55cbcc66e0..a26b01883e 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/obj/crates.dmi b/icons/obj/crates.dmi
index ca81686e94..ecb66d0119 100644
Binary files a/icons/obj/crates.dmi and b/icons/obj/crates.dmi differ
diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi
index b85c769bcd..58e427a3fb 100644
Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ
diff --git a/icons/obj/improvised.dmi b/icons/obj/improvised.dmi
index a6dfa330e8..b90e3cb3bb 100644
Binary files a/icons/obj/improvised.dmi and b/icons/obj/improvised.dmi differ
diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi
index 45181b7c8d..be12ab5f8b 100644
Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ
diff --git a/strings/spurdo_replacement.json b/strings/spurdo_replacement.json
new file mode 100644
index 0000000000..71c7c8d356
--- /dev/null
+++ b/strings/spurdo_replacement.json
@@ -0,0 +1,14 @@
+{
+
+ "spurdo": {
+ "epic": "ebin",
+ "c": "g",
+ "ck": "gg",
+ "k": "g",
+ "t": "d",
+ "p": "b",
+ "x": "gs"
+ }
+
+
+}
\ No newline at end of file