diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index f9a1624f8f..a7b3bd86f8 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -157,6 +157,8 @@ #define MAT_GRAPHITE "graphite" #define MAT_LEATHER "leather" #define MAT_CHITIN "chitin" +#define MAT_CLOTH "cloth" +#define MAT_SYNCLOTH "syncloth" #define SHARD_SHARD "shard" #define SHARD_SHRAPNEL "shrapnel" diff --git a/code/datums/autolathe/devices.dm b/code/datums/autolathe/devices.dm index 9c6ab5bb97..eed4839159 100644 --- a/code/datums/autolathe/devices.dm +++ b/code/datums/autolathe/devices.dm @@ -26,6 +26,12 @@ name = "mechanical trap" path =/obj/item/weapon/beartrap +/datum/category_item/autolathe/devices/barbedwire + name = "barbed wire" + path = /obj/item/weapon/material/barbedwire + hidden = 1 + resources = list(DEFAULT_WALL_MATERIAL = 10000) + /datum/category_item/autolathe/devices/electropack name = "electropack" path =/obj/item/device/radio/electropack diff --git a/code/datums/autolathe/tools.dm b/code/datums/autolathe/tools.dm index 9e9a87ea71..9b88a496fa 100644 --- a/code/datums/autolathe/tools.dm +++ b/code/datums/autolathe/tools.dm @@ -48,6 +48,11 @@ path = /obj/item/weapon/reagent_containers/spray resources = list(MAT_PLASTIC = 2000) +/datum/category_item/autolathe/devices/slowwire + name = "snare wire" + path = /obj/item/weapon/material/barbedwire/plastic + resources = list(MAT_PLASTIC = 10000) + /datum/category_item/autolathe/tools/spraynozzle name = "spray nozzle" path = /obj/item/weapon/reagent_containers/spray diff --git a/code/datums/uplink/tools.dm b/code/datums/uplink/tools.dm index 51d7ec7cd2..eee41e9699 100644 --- a/code/datums/uplink/tools.dm +++ b/code/datums/uplink/tools.dm @@ -92,6 +92,12 @@ desc = "A device which is capable of disrupting subspace communications, preventing the use of headsets, PDAs, and communicators within \ a radius of seven meters. It runs off weapon cells, which can be replaced as needed. One cell will last for approximately ten minutes." +/datum/uplink_item/item/tools/wall_elecrtifier + name = "Wall Electrifier" + item_cost = 10 + path = /obj/item/weapon/cell/spike + desc = "A modified powercell which will electrify walls and reinforced floors in a 3x3 tile range around it. Always active." + /datum/uplink_item/item/tools/emag name = "Cryptographic Sequencer" item_cost = 30 diff --git a/code/datums/wires/mines.dm b/code/datums/wires/mines.dm index 209fcc4c30..5e757ad16c 100644 --- a/code/datums/wires/mines.dm +++ b/code/datums/wires/mines.dm @@ -1,5 +1,5 @@ /datum/wires/mines - wire_count = 6 + wire_count = 7 randomize = TRUE holder_type = /obj/effect/mine proper_name = "Explosive Wires" @@ -7,6 +7,7 @@ /datum/wires/mines/New(atom/_holder) wires = list(WIRE_EXPLODE, WIRE_EXPLODE_DELAY, WIRE_DISARM, WIRE_BADDISARM) return ..() +#define WIRE_TRAP 64 /datum/wires/mines/get_status() . = ..() @@ -29,7 +30,13 @@ if(WIRE_DISARM) C.visible_message("[bicon(C)] *click!*", "[bicon(C)] *click!*") - new C.mineitemtype(get_turf(C)) + var/obj/effect/mine/MI = new C.mineitemtype(get_turf(C)) + + if(C.trap) + MI.trap = C.trap + C.trap = null + MI.trap.forceMove(MI) + spawn(0) qdel(C) @@ -37,6 +44,15 @@ C.visible_message("[bicon(C)] *BEEPBEEPBEEP*", "[bicon(C)] *BEEPBEEPBEEP*") spawn(20) C.explode() + + if(WIRE_TRAP) + C.visible_message("[bicon(C)] *click!*", "[bicon(C)] *click!*") + + if(mend) + C.visible_message("[bicon(C)] - The mine recalibrates[C.camo_net ? ", revealing \the [C.trap] inside." : "."]") + + C.alpha = 255 + ..() /datum/wires/mines/on_pulse(wire) @@ -57,6 +73,10 @@ if(WIRE_BADDISARM) C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*") + + if(WIRE_TRAP) + C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*") + ..() /datum/wires/mines/interactable(mob/user) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index db27559796..64a3cc1fc7 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -1,111 +1,8 @@ /* CONTAINS: Deployable items -Barricades */ -//Barricades! -/obj/structure/barricade - name = "barricade" - desc = "This space is blocked off by a barricade." - icon = 'icons/obj/structures.dmi' - icon_state = "barricade" - anchored = 1.0 - density = 1.0 - var/health = 100 - var/maxhealth = 100 - var/datum/material/material - -/obj/structure/barricade/New(var/newloc, var/material_name) - ..(newloc) - if(!material_name) - material_name = "wood" - material = get_material_by_name("[material_name]") - if(!material) - qdel(src) - return - name = "[material.display_name] barricade" - desc = "This space is blocked off by a barricade made of [material.display_name]." - color = material.icon_colour - maxhealth = material.integrity - health = maxhealth - -/obj/structure/barricade/get_material() - return material - -/obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob) - user.setClickCooldown(user.get_attack_speed(W)) - if(istype(W, /obj/item/stack)) - var/obj/item/stack/D = W - if(D.get_material_name() != material.name) - return //hitting things with the wrong type of stack usually doesn't produce messages, and probably doesn't need to. - if(health < maxhealth) - if(D.get_amount() < 1) - to_chat(user, "You need one sheet of [material.display_name] to repair \the [src].") - return - visible_message("[user] begins to repair \the [src].") - if(do_after(user,20) && health < maxhealth) - if(D.use(1)) - health = maxhealth - visible_message("[user] repairs \the [src].") - return - return - else - switch(W.damtype) - if("fire") - health -= W.force * 1 - if("brute") - health -= W.force * 0.75 - if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) - playsound(src, 'sound/effects/woodcutting.ogg', 100, 1) - else - playsound(src, 'sound/weapons/smash.ogg', 50, 1) - CheckHealth() - ..() - -/obj/structure/barricade/proc/CheckHealth() - if(health <= 0) - dismantle() - return - -/obj/structure/barricade/take_damage(var/damage) - health -= damage - CheckHealth() - return - -/obj/structure/barricade/attack_generic(var/mob/user, var/damage, var/attack_verb) - visible_message("[user] [attack_verb] the [src]!") - if(material == get_material_by_name("resin")) - playsound(src, 'sound/effects/attackblob.ogg', 100, 1) - else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) - playsound(src, 'sound/effects/woodcutting.ogg', 100, 1) - else - playsound(src, 'sound/weapons/smash.ogg', 50, 1) - user.do_attack_animation(src) - health -= damage - CheckHealth() - return - -/obj/structure/barricade/proc/dismantle() - material.place_dismantled_product(get_turf(src)) - visible_message("\The [src] falls apart!") - qdel(src) - return - -/obj/structure/barricade/ex_act(severity) - switch(severity) - if(1.0) - dismantle() - if(2.0) - health -= 25 - CheckHealth() - -/obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff. - if(istype(mover) && mover.checkpass(PASSTABLE)) - return TRUE - return FALSE - -//Actual Deployable machinery stuff /obj/machinery/deployable name = "deployable" desc = "deployable" diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index c522b4300e..c5e1f26c61 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -7,16 +7,32 @@ icon_state = "uglymine" var/triggered = 0 var/smoke_strength = 3 - var/mineitemtype = /obj/item/weapon/mine + var/obj/item/weapon/mine/mineitemtype = /obj/item/weapon/mine var/panel_open = 0 var/datum/wires/mines/wires = null register_as_dangerous_object = TRUE + var/camo_net = FALSE // Will the mine 'cloak' on deployment? + + // The trap item will be triggered in some manner when detonating. Default only checks for grenades. + var/obj/item/trap = null + /obj/effect/mine/New() icon_state = "uglyminearmed" wires = new(src) + if(ispath(trap)) + trap = new trap(src) + +/obj/effect/mine/Initialize() + ..() + + if(camo_net) + alpha = 50 + /obj/effect/mine/Destroy() + if(trap) + QDEL_NULL(trap) qdel_null(wires) return ..() @@ -25,11 +41,33 @@ triggered = 1 s.set_up(3, 1, src) s.start() - explosion(loc, 0, 2, 3, 4) //land mines are dangerous, folks. - visible_message("\The [src.name] detonates!") + + if(trap) + trigger_trap(M) + visible_message("\The [src.name] flashes as it is triggered!") + + else + explosion(loc, 0, 2, 3, 4) //land mines are dangerous, folks. + visible_message("\The [src.name] detonates!") + qdel(s) qdel(src) +/obj/effect/mine/proc/trigger_trap(var/mob/living/victim) + if(istype(trap, /obj/item/weapon/grenade)) + var/obj/item/weapon/grenade/G = trap + trap = null + G.forceMove(get_turf(src)) + if(victim.ckey) + msg_admin_attack("[key_name_admin(victim)] stepped on \a [src.name], triggering [trap]") + G.activate() + + if(istype(trap, /obj/item/device/transfer_valve)) + var/obj/item/device/transfer_valve/TV = trap + trap = null + TV.forceMove(get_turf(src)) + TV.toggle_valve() + /obj/effect/mine/bullet_act() if(prob(50)) explode() @@ -63,6 +101,9 @@ "You very carefully screw the mine's panel [panel_open ? "open" : "closed"].") playsound(src, W.usesound, 50, 1) + // Panel open, stay uncloaked, or uncloak if already cloaked. If you don't cloak on place, ignore it and just be normal alpha. + alpha = camo_net ? (panel_open ? 255 : 50) : 255 + else if((W.is_wirecutter() || istype(W, /obj/item/device/multitool)) && panel_open) interact(user) else @@ -74,6 +115,9 @@ user.set_machine(src) wires.Interact(user) +/obj/effect/mine/camo + camo_net = TRUE + /obj/effect/mine/dnascramble mineitemtype = /obj/item/weapon/mine/dnascramble @@ -193,6 +237,9 @@ spawn(0) qdel(src) +/obj/effect/mine/emp/camo + camo_net = TRUE + /obj/effect/mine/incendiary mineitemtype = /obj/item/weapon/mine/incendiary @@ -208,6 +255,26 @@ spawn(0) qdel(src) +/obj/effect/mine/gadget + mineitemtype = /obj/item/weapon/mine/gadget + +/obj/effect/mine/gadget/explode(var/mob/living/M) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + triggered = 1 + s.set_up(3, 1, src) + s.start() + + if(trap) + trigger_trap(M) + visible_message("\The [src.name] flashes as it is triggered!") + + else + explosion(loc, 0, 0, 2, 2) + visible_message("\The [src.name] detonates!") + + qdel(s) + qdel(src) + ///////////////////////////////////////////// // The held item version of the above mines ///////////////////////////////////////////// @@ -219,6 +286,10 @@ var/countdown = 10 var/minetype = /obj/effect/mine //This MUST be an /obj/effect/mine type, or it'll runtime. + var/obj/item/trap = null + + var/list/allowed_gadgets = null + /obj/item/weapon/mine/attack_self(mob/user as mob) // You do not want to move or throw a land mine while priming it... Explosives + Sudden Movement = Bad Times add_fingerprint(user) msg_admin_attack("[key_name_admin(user)] primed \a [src]") @@ -231,11 +302,39 @@ prime(user, TRUE) return +/obj/item/weapon/mine/attackby(obj/item/W as obj, mob/living/user as mob) + if(W.is_screwdriver() && trap) + to_chat(user, "You begin removing \the [trap].") + if(do_after(user, 10 SECONDS)) + to_chat(user, "You finish disconnecting the mine's trigger.") + trap.forceMove(get_turf(src)) + trap = null + return + + if(LAZYLEN(allowed_gadgets) && !trap) + var/allowed = FALSE + + for(var/path in allowed_gadgets) + if(istype(W, path)) + allowed = TRUE + break + + if(allowed) + user.drop_from_inventory(W) + W.forceMove(src) + trap = W + + ..() + /obj/item/weapon/mine/proc/prime(mob/user as mob, var/explode_now = FALSE) visible_message("\The [src.name] beeps as the priming sequence completes.") var/obj/effect/mine/R = new minetype(get_turf(src)) src.transfer_fingerprints_to(R) R.add_fingerprint(user) + if(trap) + R.trap = trap + trap = null + R.trap.forceMove(R) if(explode_now) R.explode(user) spawn(0) @@ -286,8 +385,14 @@ desc = "A small explosive mine with a fire symbol on the side." minetype = /obj/effect/mine/incendiary +/obj/item/weapon/mine/gadget + name = "gadget mine" + desc = "A small pressure-triggered device. If no component is added, the internal release bolts will detonate in unison when triggered." + + allowed_gadgets = list(/obj/item/weapon/grenade, /obj/item/device/transfer_valve) + // This tells AI mobs to not be dumb and step on mines willingly. /obj/item/weapon/mine/is_safe_to_step(mob/living/L) if(!L.hovering) return FALSE - return ..() \ No newline at end of file + return ..() diff --git a/code/game/objects/items/devices/spy_bug.dm b/code/game/objects/items/devices/spy_bug.dm index 03d0bdd60c..60ca5cc1a2 100644 --- a/code/game/objects/items/devices/spy_bug.dm +++ b/code/game/objects/items/devices/spy_bug.dm @@ -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, "You [anchored ? "" : "un"]secure \the [src].") + + update_icon() + return else if(W.force >= 5) visible_message("\The [src] lens shatters!") diff --git a/code/game/objects/items/stacks/matter_synth.dm b/code/game/objects/items/stacks/matter_synth.dm index d92cd5f8dd..02c6518374 100644 --- a/code/game/objects/items/stacks/matter_synth.dm +++ b/code/game/objects/items/stacks/matter_synth.dm @@ -56,3 +56,6 @@ name = "Bandage Synthesizer" max_energy = 10 recharge_rate = 1 + +/datum/matter_synth/cloth + name = "Cloth Synthesizer" diff --git a/code/game/objects/items/stacks/sandbags.dm b/code/game/objects/items/stacks/sandbags.dm new file mode 100644 index 0000000000..c4e755c485 --- /dev/null +++ b/code/game/objects/items/stacks/sandbags.dm @@ -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, "You haven't got enough [src] to build \the [produced] [recipe.title]\s!") + else + to_chat(user, "You haven't got enough [src] to build \the [recipe.title]!") + return + + if (recipe.one_per_turf && (locate(recipe.result_type) in user.loc)) + to_chat(user, "There is another [recipe.title] here!") + return + + if (recipe.on_floor && !isfloor(user.loc)) + to_chat(user, "\The [recipe.title] must be constructed on the floor!") + return + + if (recipe.time) + to_chat(user, "Building [recipe.title] ...") + 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, "You fill a sandbag.") diff --git a/code/game/objects/items/weapons/material/material_weapons.dm b/code/game/objects/items/weapons/material/material_weapons.dm index 23c04f2a81..5563b71689 100644 --- a/code/game/objects/items/weapons/material/material_weapons.dm +++ b/code/game/objects/items/weapons/material/material_weapons.dm @@ -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) diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index 0ec9bc7af3..c583ce1eef 100644 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -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( + "[user] starts to collect \the [src].", + "You begin collecting \the [src]!", + "You hear the sound of rustling [material.name]." + ) + playsound(src, 'sound/machines/click.ogg', 50, 1) + + if(do_after(user, health)) + user.visible_message( + "[user] has collected \the [src].", + "You have collected \the [src]!" + ) + anchored = 0 + update_icon() + else + ..() + +/obj/item/weapon/material/barbedwire/attack_self(mob/user as mob) + ..() + if(!anchored && can_use(user)) + user.visible_message( + "[user] starts to deploy \the [src].", + "You begin deploying \the [src]!", + "You hear the rustling of [material.name]." + ) + + if (do_after(user, 60)) + user.visible_message( + "[user] has deployed \the [src].", + "You have deployed \the [src]!", + "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( + "[L] steps in \the [src].", + "You step in \the [src]!", + "You hear a sharp rustling!" + ) + 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, "You step directly on \the [src]!") + + 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 diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm index 16be9dff94..4d40578c1e 100644 --- a/code/game/objects/random/mapping.dm +++ b/code/game/objects/random/mapping.dm @@ -92,6 +92,8 @@ return pick(prob(30);/obj/effect/mine, prob(25);/obj/effect/mine/frag, prob(25);/obj/effect/mine/emp, + prob(15);/obj/effect/mine/camo, + prob(15);/obj/effect/mine/emp/camo, prob(10);/obj/effect/mine/stun, prob(10);/obj/effect/mine/incendiary,) diff --git a/code/game/objects/structures/barricades.dm b/code/game/objects/structures/barricades.dm new file mode 100644 index 0000000000..34ab6025c7 --- /dev/null +++ b/code/game/objects/structures/barricades.dm @@ -0,0 +1,185 @@ +//Barricades! +/obj/structure/barricade + name = "barricade" + desc = "This space is blocked off by a barricade." + icon = 'icons/obj/structures.dmi' + icon_state = "barricade" + anchored = 1.0 + density = 1.0 + var/health = 100 + var/maxhealth = 100 + var/datum/material/material + +/obj/structure/barricade/New(var/newloc, var/material_name) + ..(newloc) + if(!material_name) + material_name = "wood" + material = get_material_by_name("[material_name]") + if(!material) + qdel(src) + return + name = "[material.display_name] barricade" + desc = "This space is blocked off by a barricade made of [material.display_name]." + color = material.icon_colour + maxhealth = material.integrity + health = maxhealth + +/obj/structure/barricade/get_material() + return material + +/obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob) + user.setClickCooldown(user.get_attack_speed(W)) + if(istype(W, /obj/item/stack)) + var/obj/item/stack/D = W + if(D.get_material_name() != material.name) + return //hitting things with the wrong type of stack usually doesn't produce messages, and probably doesn't need to. + if(health < maxhealth) + if(D.get_amount() < 1) + to_chat(user, "You need one sheet of [material.display_name] to repair \the [src].") + return + visible_message("[user] begins to repair \the [src].") + if(do_after(user,20) && health < maxhealth) + if(D.use(1)) + health = maxhealth + visible_message("[user] repairs \the [src].") + return + return + else + switch(W.damtype) + if("fire") + health -= W.force * 1 + if("brute") + health -= W.force * 0.75 + if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) + playsound(src, 'sound/effects/woodcutting.ogg', 100, 1) + else + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + CheckHealth() + ..() + +/obj/structure/barricade/proc/CheckHealth() + if(health <= 0) + dismantle() + + health = min(health, maxhealth) + + return + +/obj/structure/barricade/take_damage(var/damage) + health -= damage + CheckHealth() + return + +/obj/structure/barricade/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + if(material == get_material_by_name("resin")) + playsound(src, 'sound/effects/attackblob.ogg', 100, 1) + else if(material == (get_material_by_name(MAT_CLOTH) || get_material_by_name(MAT_SYNCLOTH))) + playsound(src, 'sound/items/drop/clothing.ogg', 100, 1) + else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) + playsound(src, 'sound/effects/woodcutting.ogg', 100, 1) + else + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + user.do_attack_animation(src) + health -= damage + CheckHealth() + return + +/obj/structure/barricade/proc/dismantle() + material.place_dismantled_product(get_turf(src)) + visible_message("\The [src] falls apart!") + qdel(src) + return + +/obj/structure/barricade/ex_act(severity) + switch(severity) + if(1.0) + dismantle() + if(2.0) + health -= 25 + CheckHealth() + +/obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff. + if(istype(mover) && mover.checkpass(PASSTABLE)) + return TRUE + return FALSE + +/obj/structure/barricade/sandbag + name = "sandbags" + desc = "Bags. Bags of sand. It's rough and coarse and somehow stays in the bag." + icon = 'icons/obj/sandbags.dmi' + icon_state = "blank" + +/obj/structure/barricade/sandbag/New(var/newloc, var/material_name) + if(!material_name) + material_name = "cloth" + ..(newloc, material_name) + material = get_material_by_name("[material_name]") + if(!material) + qdel(src) + return + name = "[material.display_name] [initial(name)]" + desc = "This space is blocked off by a barricade made of [material.display_name]." + color = null + maxhealth = material.integrity * 2 // These things are, commonly, used to stop bullets where possible. + health = maxhealth + update_connections(1) + +/obj/structure/barricade/sandbag/Destroy() + update_connections(1, src) + ..() + +/obj/structure/barricade/sandbag/dismantle() + update_connections(1, src) + material.place_dismantled_product(get_turf(src)) + visible_message("\The [src] falls apart!") + qdel(src) + return + +/obj/structure/barricade/sandbag/update_icon() + if(!material) + return + + cut_overlays() + var/image/I + + for(var/i = 1 to 4) + I = image('icons/obj/sandbags.dmi', "sandbags[connections[i]]", dir = 1<<(i-1)) + I.color = material.icon_colour + add_overlay(I) + + return + +/obj/structure/barricade/sandbag/update_connections(propagate = 0, var/obj/structure/barricade/sandbag/ignore = null) + if(!material) + return + var/list/dirs = list() + for(var/obj/structure/barricade/sandbag/S in orange(src, 1)) + if(!S.material) + continue + if(S == ignore) + continue + if(propagate >= 1) + S.update_connections(propagate - 1, ignore) + if(can_join_with(S)) + dirs += get_dir(src, S) + + connections = dirs_to_corner_states(dirs) + + update_icon() + +/obj/structure/barricade/sandbag/proc/can_join_with(var/obj/structure/barricade/sandbag/S) + if(material == S.material) + return 1 + return 0 + +/obj/structure/barricade/sandbag/CanPass(atom/movable/mover, turf/target) + . = ..() + + if(.) + if(istype(mover, /obj/item/projectile)) + var/obj/item/projectile/P = mover + + if(P.firer && get_dist(P.firer, src) > 1) // If you're firing from adjacent turfs, you are unobstructed. + if(P.armor_penetration < (material.protectiveness + material.hardness) || prob(33)) + return FALSE diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 6e4b7c741f..a33d1f8e68 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -28,6 +28,7 @@ recipes += new/datum/stack_recipe("[display_name] fork", /obj/item/weapon/material/kitchen/utensil/fork/plastic, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) recipes += new/datum/stack_recipe("[display_name] knife", /obj/item/weapon/material/knife/plastic, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) recipes += new/datum/stack_recipe("[display_name] blade", /obj/item/weapon/material/butterflyblade, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) + recipes += new/datum/stack_recipe("[display_name] defense wire", /obj/item/weapon/material/barbedwire, 10, time = 1 MINUTE, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) /datum/material/steel/generate_recipes() ..() @@ -222,6 +223,7 @@ /datum/material/cloth/generate_recipes() recipes = list() +<<<<<<< HEAD recipes += new/datum/stack_recipe("woven net", /obj/item/weapon/material/fishing_net, 10, time = 30 SECONDS, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("bedsheet", /obj/item/weapon/bedsheet, 10, time = 30 SECONDS, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("uniform", /obj/item/clothing/under/color/white, 8, time = 15 SECONDS, pass_stack_color = TRUE) @@ -237,6 +239,24 @@ recipes += new/datum/stack_recipe("baggy pants", /obj/item/clothing/under/pants/baggy/white, 8, time = 10 SECONDS, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("belt pouch", /obj/item/weapon/storage/belt/fannypack/white, 25, time = 1 MINUTE, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("crude bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE) +======= + recipes += new/datum/stack_recipe("woven net", /obj/item/weapon/material/fishing_net, 10, time = 30 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]") + recipes += new/datum/stack_recipe("bedsheet", /obj/item/weapon/bedsheet, 10, time = 30 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("uniform", /obj/item/clothing/under/color/white, 8, time = 15 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("foot wraps", /obj/item/clothing/shoes/footwraps, 2, time = 5 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("gloves", /obj/item/clothing/gloves/white, 2, time = 5 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("wig", /obj/item/clothing/head/powdered_wig, 4, time = 10 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("philosopher's wig", /obj/item/clothing/head/philosopher_wig, 50, time = 2 MINUTES, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("taqiyah", /obj/item/clothing/head/taqiyah, 3, time = 6 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("turban", /obj/item/clothing/head/turban, 3, time = 6 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("hijab", /obj/item/clothing/head/hijab, 3, time = 6 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("kippa", /obj/item/clothing/head/kippa, 3, time = 6 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("scarf", /obj/item/clothing/accessory/scarf/white, 4, time = 5 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("baggy pants", /obj/item/clothing/under/pants/baggy/white, 8, time = 10 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("belt pouch", /obj/item/weapon/storage/belt/fannypack/white, 25, time = 1 MINUTE, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("crude bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]") + recipes += new/datum/stack_recipe("empty sandbag", /obj/item/stack/emptysandbag, 2, time = 2 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]") +>>>>>>> bd9f63a... Gadgets & Gizmos (#7786) /datum/material/resin/generate_recipes() recipes = list() @@ -269,4 +289,5 @@ recipes += new/datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) recipes += new/datum/stack_recipe("[display_name] bracelet", /obj/item/clothing/accessory/bracelet/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) + recipes += new/datum/stack_recipe("empty sandbag", /obj/item/stack/emptysandbag, 2, time = 2 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]") recipes += new/datum/stack_recipe("whip", /obj/item/weapon/material/whip, 5, time = 15 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]") diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 068a745cbb..572438107d 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -1010,6 +1010,19 @@ var/list/name_to_material pass_stack_colors = TRUE supply_conversion_value = 2 +/datum/material/cloth/syncloth + name = "syncloth" + stack_origin_tech = list(TECH_MATERIAL = 3, TECH_BIO = 2) + door_icon_base = "wood" + ignition_point = T0C+532 + melting_point = T0C+600 + integrity = 200 + protectiveness = 15 // 4% + flags = MATERIAL_PADDING + conductive = 0 + pass_stack_colors = TRUE + supply_conversion_value = 3 + /datum/material/cult name = "cult" display_name = "disturbing stone" diff --git a/code/modules/mob/_modifiers/modifiers_misc.dm b/code/modules/mob/_modifiers/modifiers_misc.dm index 3b9663d855..fee761cf30 100644 --- a/code/modules/mob/_modifiers/modifiers_misc.dm +++ b/code/modules/mob/_modifiers/modifiers_misc.dm @@ -426,4 +426,14 @@ the artifact triggers the rage. heat_protection = -0.5 cold_protection = -0.5 - siemens_coefficient = 1.5 \ No newline at end of file + siemens_coefficient = 1.5 + +/datum/modifier/entangled + name = "entangled" + desc = "Its hard to move." + + on_created_text = "You're caught in something! It's hard to move." + on_expired_text = "Your movement is freed." + stacks = MODIFIER_STACK_EXTEND + + slowdown = 2 diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm index 7c6f22d6b9..fe39040432 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -37,6 +37,12 @@ src.modules += new /obj/item/weapon/pinpointer/shuttle/merc(src) src.modules += new /obj/item/weapon/melee/energy/sword(src) + var/datum/matter_synth/cloth = new /datum/matter_synth/cloth(40000) + synths += cloth + + var/obj/item/stack/sandbags/cyborg/SB = new /obj/item/stack/sandbags/cyborg(src) + SB.synths += list(cloth) + var/jetpack = new/obj/item/weapon/tank/jetpack/carbondioxide(src) src.modules += jetpack R.internals = jetpack diff --git a/code/modules/power/cells/esoteric_cells.dm b/code/modules/power/cells/esoteric_cells.dm new file mode 100644 index 0000000000..b45c19a783 --- /dev/null +++ b/code/modules/power/cells/esoteric_cells.dm @@ -0,0 +1,74 @@ + +/obj/item/weapon/cell/spike + name = "modified power cell" + desc = "A modified power cell sitting in a highly conductive chassis." + origin_tech = list(TECH_POWER = 2) + icon_state = "spikecell" + maxcharge = 10000 + matter = list(DEFAULT_WALL_MATERIAL = 1000, MAT_GLASS = 80, MAT_SILVER = 100) + self_recharge = TRUE + charge_amount = 150 + +/obj/item/weapon/cell/spike/process() + ..() + + var/turf/Center = get_turf(src) + + var/shock_count = 0 + for(var/turf/T in range(Center, 1)) + + if(prob(round(charge / 250)) && charge >= (maxcharge / 4)) + + if(locate(/obj/effect/temporary_effect/pulse/staticshock) in T) + continue + + var/conductive = FALSE + + if(istype(T, /turf/simulated/wall)) + var/turf/simulated/wall/WT = T + + if(WT.material.conductive) + conductive = TRUE + else if(WT.girder_material.conductive) + conductive = TRUE + else if(WT.reinf_material && WT.reinf_material.conductive) + conductive = TRUE + + if(istype(T, /turf/simulated/floor)) + var/turf/simulated/floor/F = T + if(istype(F.flooring, /decl/flooring/reinforced)) + conductive = TRUE + + if(conductive) + shock_count += 1 + new /obj/effect/temporary_effect/pulse/staticshock(T) + + if(shock_count) + while(shock_count) + use(200) + shock_count-- + +/obj/effect/temporary_effect/pulse/staticshock + name = "electric field" + desc = "Caution: Do not touch." + pulses_remaining = 10 + pulse_delay = 2 SECONDS + icon_state = "blue_static" + +/obj/effect/temporary_effect/pulse/staticshock/on_pulse() + ..() + + for(var/mob/living/L in view(1, src)) + if(!issilicon(L) && prob(L.mob_size)) + var/obj/item/projectile/beam/shock/weak/P = new (get_turf(src)) + P.launch_projectile_from_turf(L, BP_TORSO) + + var/obj/item/weapon/plastique/C4 = locate() in get_turf(src) + + if(C4) + C4.visible_message("The current fries \the [C4]!") + + if(prob(10)) + C4.explode(get_turf(src)) + else + qdel(C4) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 41430bea38..8c888fee3e 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -261,3 +261,7 @@ agony = 15 eyeblur = 2 hitsound = 'sound/weapons/zapbang.ogg' + +/obj/item/projectile/beam/shock/weak + damage = 5 + agony = 10 diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index e8905467f6..f578e1f9ac 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/obj/power.dmi b/icons/obj/power.dmi index 732bb44e00..c806ec99be 100644 Binary files a/icons/obj/power.dmi and b/icons/obj/power.dmi differ diff --git a/icons/obj/sandbags.dmi b/icons/obj/sandbags.dmi new file mode 100644 index 0000000000..0a5c24598a Binary files /dev/null and b/icons/obj/sandbags.dmi differ diff --git a/icons/obj/trap.dmi b/icons/obj/trap.dmi new file mode 100644 index 0000000000..108bc46726 Binary files /dev/null and b/icons/obj/trap.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 5d1aabd37b..a9ecbfab29 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1194,6 +1194,7 @@ #include "code\game\objects\items\stacks\nanopaste.dm" #include "code\game\objects\items\stacks\nanopaste_vr.dm" #include "code\game\objects\items\stacks\rods.dm" +#include "code\game\objects\items\stacks\sandbags.dm" #include "code\game\objects\items\stacks\stack.dm" #include "code\game\objects\items\stacks\telecrystal.dm" #include "code\game\objects\items\stacks\tickets.dm" @@ -1385,6 +1386,7 @@ #include "code\game\objects\random\mob_vr.dm" #include "code\game\objects\random\spacesuits.dm" #include "code\game\objects\random\unidentified\medicine.dm" +#include "code\game\objects\structures\barricades.dm" #include "code\game\objects\structures\barsign.dm" #include "code\game\objects\structures\bedsheet_bin.dm" #include "code\game\objects\structures\bedsheet_bin_vr.dm" @@ -3184,7 +3186,11 @@ #include "code\modules\power\antimatter\control.dm" #include "code\modules\power\antimatter\shielding.dm" #include "code\modules\power\cells\device_cells.dm" +<<<<<<< HEAD:vorestation.dme #include "code\modules\power\cells\device_cells_vr.dm" +======= +#include "code\modules\power\cells\esoteric_cells.dm" +>>>>>>> bd9f63a... Gadgets & Gizmos (#7786):polaris.dme #include "code\modules\power\cells\power_cells.dm" #include "code\modules\power\fusion\_setup.dm" #include "code\modules\power\fusion\fusion_circuits.dm"