mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-21 19:19:12 +01:00
Gadgets & Gizmos
This commit is contained in:
@@ -88,6 +88,14 @@
|
||||
if(get_dist(user, src) == 0)
|
||||
. += "It has a tiny camera inside. Needs to be both configured and brought in contact with monitor device to be fully functional."
|
||||
|
||||
/obj/item/device/camerabug/update_icon()
|
||||
..()
|
||||
|
||||
if(anchored) // Standard versions are relatively obvious if not hidden in a container. Anchoring them is advised, to disguise them.
|
||||
alpha = 50
|
||||
else
|
||||
alpha = 255
|
||||
|
||||
/obj/item/device/camerabug/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(istype(W, /obj/item/device/bug_monitor))
|
||||
var/obj/item/device/bug_monitor/SM = W
|
||||
@@ -101,6 +109,15 @@
|
||||
linkedmonitor = null
|
||||
else
|
||||
to_chat(user, "Error: The device is linked to another monitor.")
|
||||
|
||||
else if(W.is_wrench() && user.a_intent != I_HURT)
|
||||
if(isturf(loc))
|
||||
anchored = !anchored
|
||||
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "" : "un"]secure \the [src].</span>")
|
||||
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
if(W.force >= 5)
|
||||
visible_message("\The [src] lens shatters!")
|
||||
|
||||
@@ -56,3 +56,6 @@
|
||||
name = "Bandage Synthesizer"
|
||||
max_energy = 10
|
||||
recharge_rate = 1
|
||||
|
||||
/datum/matter_synth/cloth
|
||||
name = "Cloth Synthesizer"
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/obj/item/stack/sandbags
|
||||
name = "sandbag"
|
||||
desc = "Filled sandbags. Fortunately pre-filled."
|
||||
singular_name = "sandbag"
|
||||
icon = 'icons/obj/sandbags.dmi'
|
||||
icon_state = "sandbag"
|
||||
w_class = ITEMSIZE_LARGE
|
||||
force = 10.0
|
||||
throwforce = 20.0
|
||||
throw_speed = 5
|
||||
throw_range = 3
|
||||
drop_sound = 'sound/items/drop/clothing.ogg'
|
||||
pickup_sound = 'sound/items/pickup/clothing.ogg'
|
||||
matter = list(MAT_CLOTH = SHEET_MATERIAL_AMOUNT * 2)
|
||||
max_amount = 30
|
||||
attack_verb = list("hit", "bludgeoned", "pillowed")
|
||||
no_variants = TRUE
|
||||
stacktype = /obj/item/stack/sandbags
|
||||
|
||||
pass_color = TRUE
|
||||
|
||||
var/bag_material = "cloth"
|
||||
|
||||
/obj/item/stack/sandbags/cyborg
|
||||
name = "sandbag synthesizer"
|
||||
desc = "A device that makes filled sandbags. Don't ask how."
|
||||
gender = NEUTER
|
||||
matter = null
|
||||
uses_charge = 1
|
||||
charge_costs = list(500)
|
||||
stacktype = /obj/item/stack/sandbags
|
||||
|
||||
bag_material = MAT_SYNCLOTH
|
||||
|
||||
/obj/item/stack/sandbags/New(var/newloc, var/amt, var/bag_mat)
|
||||
..()
|
||||
recipes = sandbag_recipes
|
||||
update_icon()
|
||||
|
||||
if(bag_mat)
|
||||
bag_material = bag_mat
|
||||
|
||||
var/datum/material/M = get_material_by_name("[bag_material]")
|
||||
if(!M)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
color = M.icon_colour
|
||||
|
||||
/obj/item/stack/sandbags/update_icon()
|
||||
var/amount = get_amount()
|
||||
|
||||
slowdown = round(amount / 10, 0.1)
|
||||
|
||||
var/global/list/datum/stack_recipe/sandbag_recipes = list( \
|
||||
new/datum/stack_recipe("barricade", /obj/structure/barricade/sandbag, 3, time = 5 SECONDS, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE))
|
||||
|
||||
/obj/item/stack/sandbags/produce_recipe(datum/stack_recipe/recipe, var/quantity, mob/user)
|
||||
var/required = quantity*recipe.req_amount
|
||||
var/produced = min(quantity*recipe.res_amount, recipe.max_res_amount)
|
||||
|
||||
if (!can_use(required))
|
||||
if (produced>1)
|
||||
to_chat(user, "<span class='warning'>You haven't got enough [src] to build \the [produced] [recipe.title]\s!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You haven't got enough [src] to build \the [recipe.title]!</span>")
|
||||
return
|
||||
|
||||
if (recipe.one_per_turf && (locate(recipe.result_type) in user.loc))
|
||||
to_chat(user, "<span class='warning'>There is another [recipe.title] here!</span>")
|
||||
return
|
||||
|
||||
if (recipe.on_floor && !isfloor(user.loc))
|
||||
to_chat(user, "<span class='warning'>\The [recipe.title] must be constructed on the floor!</span>")
|
||||
return
|
||||
|
||||
if (recipe.time)
|
||||
to_chat(user, "<span class='notice'>Building [recipe.title] ...</span>")
|
||||
if (!do_after(user, recipe.time))
|
||||
return
|
||||
|
||||
if (use(required))
|
||||
var/atom/O = new recipe.result_type(user.loc, bag_material)
|
||||
|
||||
if(istype(O, /obj))
|
||||
var/obj/Ob = O
|
||||
|
||||
if(LAZYLEN(Ob.matter)) // Law of equivalent exchange.
|
||||
Ob.matter.Cut()
|
||||
|
||||
else
|
||||
Ob.matter = list()
|
||||
|
||||
var/mattermult = istype(Ob, /obj/item) ? min(2000, 400 * Ob.w_class) : 2000
|
||||
|
||||
Ob.matter[recipe.use_material] = mattermult / produced * required
|
||||
|
||||
O.set_dir(user.dir)
|
||||
O.add_fingerprint(user)
|
||||
|
||||
if (istype(O, /obj/item/stack))
|
||||
var/obj/item/stack/S = O
|
||||
S.amount = produced
|
||||
S.add_to_stacks(user)
|
||||
|
||||
if (istype(O, /obj/item/weapon/storage)) //BubbleWrap - so newly formed boxes are empty
|
||||
for (var/obj/item/I in O)
|
||||
qdel(I)
|
||||
|
||||
if ((pass_color || recipe.pass_color))
|
||||
if(!color)
|
||||
if(recipe.use_material)
|
||||
var/datum/material/MAT = get_material_by_name(recipe.use_material)
|
||||
if(MAT.icon_colour)
|
||||
O.color = MAT.icon_colour
|
||||
else
|
||||
return
|
||||
else
|
||||
O.color = color
|
||||
|
||||
// Empty bags. Yes, you need to fill them.
|
||||
|
||||
/obj/item/stack/emptysandbag
|
||||
name = "sandbag"
|
||||
desc = "Empty sandbags. You know what must be done."
|
||||
singular_name = "sandbag"
|
||||
icon = 'icons/obj/sandbags.dmi'
|
||||
icon_state = "sandbag_e"
|
||||
w_class = ITEMSIZE_LARGE
|
||||
|
||||
strict_color_stacking = TRUE
|
||||
max_amount = 30
|
||||
stacktype = /obj/item/stack/emptysandbag
|
||||
|
||||
pass_color = TRUE
|
||||
|
||||
var/bag_material = "cloth"
|
||||
|
||||
/obj/item/stack/emptysandbag/New(var/newloc, var/amt, var/bag_mat)
|
||||
..(newloc, amt)
|
||||
|
||||
if(bag_mat)
|
||||
bag_material = bag_mat
|
||||
|
||||
var/datum/material/M = get_material_by_name("[bag_material]")
|
||||
if(!M)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
color = M.icon_colour
|
||||
|
||||
/obj/item/stack/emptysandbag/attack_self(var/mob/user)
|
||||
while(do_after(user, 1 SECOND) && can_use(1) && istype(get_turf(src), /turf/simulated/floor/outdoors))
|
||||
use(1)
|
||||
var/obj/item/stack/sandbags/SB = new (get_turf(src), 1, bag_material)
|
||||
SB.color = color
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You fill a sandbag.</span>")
|
||||
@@ -97,6 +97,8 @@
|
||||
|
||||
/obj/item/weapon/material/proc/check_health(var/consumed)
|
||||
if(health<=0)
|
||||
health = 0
|
||||
|
||||
if(fragile)
|
||||
shatter(consumed)
|
||||
else if(!dulled && can_dull)
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
|
||||
/*
|
||||
* Beartraps.
|
||||
* Buckles crossing individuals, doing moderate brute damage.
|
||||
*/
|
||||
|
||||
/obj/item/weapon/beartrap
|
||||
name = "mechanical trap"
|
||||
throw_speed = 2
|
||||
@@ -158,3 +164,238 @@
|
||||
color = "#C9DCE1"
|
||||
|
||||
origin_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_PHORON = 2, TECH_ARCANE = 1)
|
||||
|
||||
/*
|
||||
* Barbed-Wire.
|
||||
* Slows individuals crossing it. Barefoot individuals will be cut. Can be electrified by placing over a cable node.
|
||||
*/
|
||||
|
||||
/obj/item/weapon/material/barbedwire
|
||||
name = "barbed wire"
|
||||
desc = "A coil of wire."
|
||||
icon = 'icons/obj/trap.dmi'
|
||||
icon_state = "barbedwire"
|
||||
anchored = FALSE
|
||||
layer = TABLE_LAYER
|
||||
w_class = ITEMSIZE_LARGE
|
||||
explosion_resistance = 1
|
||||
can_dull = TRUE
|
||||
fragile = TRUE
|
||||
force_divisor = 0.20
|
||||
thrown_force_divisor = 0.25
|
||||
|
||||
sharp = TRUE
|
||||
|
||||
/obj/item/weapon/material/barbedwire/set_material(var/new_material)
|
||||
..()
|
||||
|
||||
if(!QDELETED(src))
|
||||
health = round(material.integrity / 3)
|
||||
name = (material.get_edge_damage() * force_divisor > 15) ? "[material.display_name] razor wire" : "[material.display_name] [initial(name)]"
|
||||
|
||||
/obj/item/weapon/material/barbedwire/proc/can_use(mob/user)
|
||||
return (user.IsAdvancedToolUser() && !issilicon(user) && !user.stat && !user.restrained())
|
||||
|
||||
/obj/item/weapon/material/barbedwire/attack_hand(mob/user as mob)
|
||||
if(anchored && can_use(user))
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] starts to collect \the [src].</span>",
|
||||
"<span class='notice'>You begin collecting \the [src]!</span>",
|
||||
"You hear the sound of rustling [material.name]."
|
||||
)
|
||||
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
||||
|
||||
if(do_after(user, health))
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] has collected \the [src].</span>",
|
||||
"<span class='notice'>You have collected \the [src]!</span>"
|
||||
)
|
||||
anchored = 0
|
||||
update_icon()
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/barbedwire/attack_self(mob/user as mob)
|
||||
..()
|
||||
if(!anchored && can_use(user))
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] starts to deploy \the [src].</span>",
|
||||
"<span class='danger'>You begin deploying \the [src]!</span>",
|
||||
"You hear the rustling of [material.name]."
|
||||
)
|
||||
|
||||
if (do_after(user, 60))
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] has deployed \the [src].</span>",
|
||||
"<span class='danger'>You have deployed \the [src]!</span>",
|
||||
"You hear the rustling of [material.name]."
|
||||
)
|
||||
playsound(src, 'sound/items/Wirecutter.ogg',70, 1)
|
||||
spawn(2)
|
||||
playsound(src, 'sound/items/Wirecutter.ogg',40, 1)
|
||||
user.drop_from_inventory(src)
|
||||
forceMove(get_turf(src))
|
||||
anchored = 1
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/material/barbedwire/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(!istype(W))
|
||||
return
|
||||
|
||||
if((W.flags & NOCONDUCT) || !shock(user, 70, pick(BP_L_HAND, BP_R_HAND)))
|
||||
user.setClickCooldown(user.get_attack_speed(W))
|
||||
user.do_attack_animation(src)
|
||||
playsound(src, 'sound/effects/grillehit.ogg', 40, 1)
|
||||
|
||||
var/inc_damage = W.force
|
||||
|
||||
if(W.is_wirecutter())
|
||||
if(!shock(user, 100, pick(BP_L_HAND, BP_R_HAND)))
|
||||
playsound(src, W.usesound, 100, 1)
|
||||
inc_damage *= 3
|
||||
|
||||
if(W.damtype != BRUTE)
|
||||
inc_damage *= 0.3
|
||||
|
||||
health -= inc_damage
|
||||
|
||||
check_health()
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/barbedwire/update_icon()
|
||||
..()
|
||||
|
||||
if(anchored)
|
||||
icon_state = "[initial(icon_state)]-out"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
/obj/item/weapon/material/barbedwire/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(anchored && isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.m_intent == "run")
|
||||
L.visible_message(
|
||||
"<span class='danger'>[L] steps in \the [src].</span>",
|
||||
"<span class='danger'>You step in \the [src]!</span>",
|
||||
"<b>You hear a sharp rustling!</b>"
|
||||
)
|
||||
attack_mob(L)
|
||||
update_icon()
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/barbedwire/proc/shock(mob/user as mob, prb, var/target_zone = BP_TORSO)
|
||||
if(!anchored || health == 0) // anchored/destroyed grilles are never connected
|
||||
return 0
|
||||
if(material.conductivity <= 0)
|
||||
return 0
|
||||
if(!prob(prb))
|
||||
return 0
|
||||
if(!in_range(src, user))//To prevent TK and mech users from getting shocked
|
||||
return 0
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/structure/cable/C = T.get_cable_node()
|
||||
if(C)
|
||||
if(C.powernet)
|
||||
var/datum/powernet/PN = C.powernet
|
||||
|
||||
if(PN)
|
||||
PN.trigger_warning()
|
||||
|
||||
var/PN_damage = PN.get_electrocute_damage() * (material.conductivity / 50)
|
||||
|
||||
var/drained_energy = PN_damage * 10 / CELLRATE
|
||||
|
||||
PN.draw_power(drained_energy)
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
var/obj/item/organ/external/affected = H.get_organ(check_zone(target_zone))
|
||||
|
||||
H.electrocute_act(PN_damage, src, H.get_siemens_coefficient_organ(affected))
|
||||
|
||||
else
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
L.electrocute_act(PN_damage, src, 0.8)
|
||||
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(user.stunned)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/material/barbedwire/proc/attack_mob(mob/living/L)
|
||||
var/target_zone
|
||||
if(L.lying)
|
||||
target_zone = ran_zone()
|
||||
else
|
||||
target_zone = pick("l_foot", "r_foot", "l_leg", "r_leg")
|
||||
|
||||
//armour
|
||||
var/blocked = L.run_armor_check(target_zone, "melee")
|
||||
var/soaked = L.get_armor_soak(target_zone, "melee")
|
||||
|
||||
if(blocked >= 100)
|
||||
return
|
||||
|
||||
if(soaked >= 30)
|
||||
return
|
||||
|
||||
if(L.buckled) //wheelchairs, office chairs, rollerbeds
|
||||
return
|
||||
|
||||
shock(L, 100, target_zone)
|
||||
|
||||
L.add_modifier(/datum/modifier/entangled, 3 SECONDS)
|
||||
|
||||
if(!L.apply_damage(force * (issilicon(L) ? 0.25 : 1), BRUTE, target_zone, blocked, soaked, src, sharp, edge))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/effects/glass_step.ogg', 50, 1) // not sure how to handle metal shards with sounds
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
|
||||
if(H.species.siemens_coefficient<0.5) //Thick skin.
|
||||
return
|
||||
|
||||
if( H.shoes || ( H.wear_suit && (H.wear_suit.body_parts_covered & FEET) ) )
|
||||
return
|
||||
|
||||
if(H.species.flags & NO_MINOR_CUT)
|
||||
return
|
||||
|
||||
to_chat(H, "<span class='danger'>You step directly on \the [src]!</span>")
|
||||
|
||||
var/list/check = list("l_foot", "r_foot")
|
||||
while(check.len)
|
||||
var/picked = pick(check)
|
||||
var/obj/item/organ/external/affecting = H.get_organ(picked)
|
||||
if(affecting)
|
||||
if(affecting.robotic >= ORGAN_ROBOT)
|
||||
return
|
||||
if(affecting.take_damage(force, 0))
|
||||
H.UpdateDamageIcon()
|
||||
H.updatehealth()
|
||||
if(affecting.organ_can_feel_pain())
|
||||
H.Weaken(3)
|
||||
return
|
||||
check -= picked
|
||||
|
||||
if(material.is_brittle() && prob(material.hardness))
|
||||
health = 0
|
||||
else if(!prob(material.hardness))
|
||||
health--
|
||||
check_health()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/barbedwire/plastic
|
||||
name = "snare wire"
|
||||
default_material = MAT_PLASTIC
|
||||
|
||||
Reference in New Issue
Block a user