Merge remote-tracking branch 'citadel/master' into vampire_haste

This commit is contained in:
kevinz000
2020-02-19 19:16:58 -07:00
110 changed files with 564 additions and 201 deletions
+7 -1
View File
@@ -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))
#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)
+2 -2
View File
@@ -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
..()
..()
+2 -1
View File
@@ -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
@@ -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"
@@ -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
@@ -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
+3 -5
View File
@@ -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)
. = ..()
+1 -1
View File
@@ -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)
@@ -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"
+1 -1
View File
@@ -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
+8 -8
View File
@@ -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()
@@ -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()
+1 -1
View File
@@ -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()
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 = ""
+7 -1
View File
@@ -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"
@@ -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
return TRUE
@@ -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 ..()
@@ -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), \
))
@@ -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), \
+17 -15
View File
@@ -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, "<span class='notice'>You begin to exorcise [sword].</span>")
if(istype(A, /obj/item/twohanded/required/cult_bastard) || istype(A, /obj/item/melee/cultblade) && !iscultist(user))
to_chat(user, "<span class='notice'>You begin to exorcise [A].</span>")
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("<span class='notice'>[user] has purified the [sword]!</span>")
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("<span class='notice'>[user] has purified [A]!</span>")
qdel(A)
else if(istype(A, /obj/item/soulstone) && !iscultist(user))
var/obj/item/soulstone/SS = A
+5
View File
@@ -79,6 +79,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.visible_message("<span class='suicide'>[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
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 = "<b><i>THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!</i></b>\nActivate it in your hand to point to the nearest victim."
flags_1 = CONDUCT_1
@@ -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"
@@ -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"
+2
View File
@@ -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)]"
+1 -1
View File
@@ -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")
@@ -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)
@@ -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
@@ -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()
. = ..()
@@ -229,7 +229,7 @@
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] the interface.</span>"
/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")
+3 -12
View File
@@ -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
-5
View File
@@ -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
+10
View File
@@ -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
+25
View File
@@ -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//
/////////////////////////
+1 -1
View File
@@ -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?
+1 -1
View File
@@ -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?
+3 -4
View File
@@ -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,
@@ -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,
+1 -1
View File
@@ -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,
+2 -1
View File
@@ -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"
+2 -1
View File
@@ -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,
+4 -4
View File
@@ -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,
+1 -1
View File
@@ -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,
+3 -3
View File
@@ -737,13 +737,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.</span>")
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)
@@ -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
+1 -1
View File
@@ -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
+3
View File
@@ -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
@@ -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("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
@@ -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)
@@ -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()
+1 -1
View File
@@ -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
+3 -3
View File
@@ -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
@@ -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"
+1 -1
View File
@@ -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"
@@ -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, "<span class='notice'>You bypass [src]'s controls.</span>")
if(user)
to_chat(user, "<span class='notice'>You bypass [src]'s controls.</span>")
return TRUE
if(!open)
to_chat(user, "<span class='warning'>You need to open maintenance panel first!</span>")
if(user)
to_chat(user, "<span class='warning'>You need to open maintenance panel first!</span>")
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, "<span class='userdanger'>(#$*#$^^( OVERRIDE DETECTED</span>")
log_combat(user, src, "emagged")
if(user)
log_combat(user, src, "emagged")
return TRUE
/mob/living/simple_animal/bot/examine(mob/user)
@@ -123,7 +123,8 @@
emagged = TRUE
if(!open)
locked = !locked
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
if(user)
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
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)
@@ -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
@@ -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
+1 -1
View File
@@ -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
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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
+7 -7
View File
@@ -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")
+13 -14
View File
@@ -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].", "<span class='notice'>You begin to take the glass off [src]...</span>")
@@ -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.", "<span class='notice'>You place the glass on the solar assembly.</span>")
if(tracker)
new /obj/machinery/power/tracker(get_turf(src), src)
+9 -11
View File
@@ -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
@@ -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
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
+16 -1
View File
@@ -50,4 +50,19 @@
icon_state = "bow_[get_ammo() ? (chambered ? "firing" : "loaded") : "unloaded"]"
/obj/item/gun/ballistic/bow/can_shoot()
return chambered
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
+2 -1
View File
@@ -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 ..()
+5 -6
View File
@@ -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
@@ -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)
. = ..()
@@ -3,4 +3,23 @@
desc = "Woosh!"
damage = 15
icon_state = "arrow"
ammo_type = /obj/item/ammo_casing/caseless/arrow
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
@@ -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
@@ -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
@@ -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)
@@ -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)
@@ -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
@@ -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 = "Apurple 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 wnted 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
@@ -2108,3 +2108,10 @@
to_chat(M, "<span class='userlove'>You feel like playing with your [G.name]!</span>")
..()
/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
@@ -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)
@@ -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"
@@ -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)
list_reagents = list(/datum/reagent/drug/anaphrodisiacplus = 30)
@@ -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("<span class='suicide'>[user] begins to choke on \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -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"
@@ -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
@@ -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)))
+1 -1
View File
@@ -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()