diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm index e7853f7059..d497391d3f 100644 --- a/code/__defines/belly_modes_vr.dm +++ b/code/__defines/belly_modes_vr.dm @@ -19,6 +19,7 @@ #define DM_FLAG_STRIPPING 0x2 #define DM_FLAG_LEAVEREMAINS 0x4 #define DM_FLAG_THICKBELLY 0x8 +#define DM_FLAG_AFFECTWORN 0x10 //Item related modes #define IM_HOLD "Hold" diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index fba42c15fd..69e949e495 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/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm index 0406099616..946cd9de0e 100644 --- a/code/_helpers/global_lists_vr.dm +++ b/code/_helpers/global_lists_vr.dm @@ -8,6 +8,7 @@ var/global/list/tail_styles_list = list() // Stores /datum/sprite_accessory/tail var/global/list/wing_styles_list = list() // Stores /datum/sprite_accessory/wing indexed by type var/global/list/negative_traits = list() // Negative custom species traits, indexed by path var/global/list/neutral_traits = list() // Neutral custom species traits, indexed by path +var/global/list/everyone_traits = list() // Neutral traits available to all species, indexed by path var/global/list/positive_traits = list() // Positive custom species traits, indexed by path var/global/list/traits_costs = list() // Just path = cost list, saves time in char setup var/global/list/all_traits = list() // All of 'em at once (same instances) @@ -457,7 +458,7 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN, for(var/path in paths) var/datum/sprite_accessory/hair_accessory/instance = new path() hair_accesories_list[path] = instance - + // Custom species traits paths = typesof(/datum/trait) - /datum/trait for(var/path in paths) @@ -472,6 +473,8 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN, negative_traits[path] = instance if(0) neutral_traits[path] = instance + if(!(instance.custom_only)) + everyone_traits[path] = instance if(0.1 to INFINITY) positive_traits[path] = instance diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 6a4579f191..b29a1192d9 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -354,19 +354,13 @@ facedir(direction) /obj/screen/click_catcher + name = "Darkness" icon = 'icons/mob/screen_gen.dmi' icon_state = "click_catcher" plane = CLICKCATCHER_PLANE + layer = LAYER_HUD_UNDER mouse_opacity = 2 - screen_loc = "CENTER-7,CENTER-7" - -/obj/screen/click_catcher/proc/MakeGreed() - . = list() - for(var/i = 0, i<15, i++) - for(var/j = 0, j<15, j++) - var/obj/screen/click_catcher/CC = new() - CC.screen_loc = "NORTH-[i],EAST-[j]" - . += CC + screen_loc = "SOUTHWEST to NORTHEAST" /obj/screen/click_catcher/Click(location, control, params) var/list/modifiers = params2list(params) @@ -374,7 +368,8 @@ var/mob/living/carbon/C = usr C.swap_hand() else - var/turf/T = screen_loc2turf(screen_loc, get_turf(usr)) + var/list/P = params2list(params) + var/turf/T = screen_loc2turf(P["screen-loc"], get_turf(usr)) if(T) T.Click(location, control, params) . = 1 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/dna/dna2.dm b/code/game/dna/dna2.dm index 1ffaab1793..34180bf329 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -206,23 +206,9 @@ var/global/list/datum/dna/gene/dna_genes[0] // Technically custom_species is not part of the UI, but this place avoids merge problems. src.custom_species = character.custom_species - if(istype(character.species,/datum/species/custom)) - var/datum/species/custom/CS = character.species - src.species_traits = CS.traits.Copy() - src.base_species = CS.base_species - src.blood_color = CS.blood_color - - if(istype(character.species,/datum/species/xenochimera)) - var/datum/species/xenochimera/CS = character.species - //src.species_traits = CS.traits.Copy() //No traits - src.base_species = CS.base_species - src.blood_color = CS.blood_color - - if(istype(character.species,/datum/species/alraune)) - var/datum/species/alraune/CS = character.species - //src.species_traits = CS.traits.Copy() //No traits - src.base_species = CS.base_species - src.blood_color = CS.blood_color + src.base_species = character.species.base_species + src.blood_color = character.species.blood_color + src.species_traits = character.species.traits.Copy() // +1 to account for the none-of-the-above possibility SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 0edc6bb636..758f74d873 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -237,20 +237,9 @@ // Technically custom_species is not part of the UI, but this place avoids merge problems. H.custom_species = dna.custom_species - if(istype(H.species,/datum/species/custom)) - var/datum/species/custom/CS = H.species - var/datum/species/custom/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src) - new_CS.blood_color = dna.blood_color - - if(istype(H.species,/datum/species/xenochimera)) - var/datum/species/xenochimera/CS = H.species - var/datum/species/xenochimera/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src) - new_CS.blood_color = dna.blood_color - - if(istype(H.species,/datum/species/alraune)) - var/datum/species/alraune/CS = H.species - var/datum/species/alraune/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src) - new_CS.blood_color = dna.blood_color + H.species.blood_color = dna.blood_color + var/datum/species/S = H.species + S.produceCopy(dna.base_species,dna.species_traits,src) // VOREStation Edit End H.force_update_organs() //VOREStation Add - Gotta do this too 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/sahoc_ch.dm b/code/game/objects/items/sahoc_ch.dm new file mode 100644 index 0000000000..69674eb59b --- /dev/null +++ b/code/game/objects/items/sahoc_ch.dm @@ -0,0 +1,149 @@ +/obj/item/device/buttonofnormal + name = "Chaos button" + desc = "It radiates an aura of chaotic size energy." + icon = 'icons/obj/mobcap.dmi' + icon_state = "mobcap0" + matter = list(DEFAULT_WALL_MATERIAL = 1000) + throwforce = 00 + throw_speed = 4 + throw_range = 20 + force = 0 + var/colorindex = 0 + var/mob/living/capsuleowner = null //taken from Capsule Code + var/sizetouse = 0.25 + + pickup(mob/user) + if(!capsuleowner) + capsuleowner = user + + attack_self(mob/user) + if(colorindex) + nonrandom() + sleep(10) + capsuleowner.resize(sizetouse) + sizetouse = rand(25,200)/100 //randmization occurs after press + + throw_impact(atom/A, speed, mob/user) + ..() + if(isliving(A)) + if(colorindex) + nonrandom() + sleep(5) + var/mob/living/capsulehit = A + capsulehit.resize(sizetouse) + sizetouse = rand(25,200)/100 //randmization occurs after press + + attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/pen)) + colorindex = (colorindex + 1) % 6 + icon_state = "mobcap[colorindex]" + update_icon() + if(istype(W, /obj/item/weapon/card/id)) + capsuleowner = null + ..() + +/obj/item/device/buttonofnormal/proc/nonrandom() //Secret ball randmoizer rig code + switch(colorindex) + if(1) sizetouse = RESIZE_HUGE + if(2) sizetouse = RESIZE_BIG + if(3) sizetouse = RESIZE_NORMAL + if(4) sizetouse = RESIZE_SMALL + if(5) sizetouse = RESIZE_TINY + +/obj/item/device/daredevice + name = "Dare button" + desc = "A strange button, the only distinguishing feature being an engraved text reading 'Suffer to Gain.'." + icon = 'icons/obj/mobcap.dmi' + icon_state = "mobcap1" + matter = list(DEFAULT_WALL_MATERIAL = 5000) + throwforce = 00 + throw_speed = 2 + throw_range = 20 + force = 0 + var/luckynumber7 = 0 + var/colorindex = 1 + + var/list/winitems = list( + /obj/item/weapon/reagent_containers/food/snacks/cookie, + /obj/item/weapon/spacecasinocash, + /obj/item/weapon/reagent_containers/syringe/drugs, + ) + + attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/pen)) + colorindex += 1 + if(colorindex >= 6) + colorindex = 0 + icon_state = "mobcap[colorindex]" + update_icon() + ..() + + attack_self(mob/user) + var/mob/living/capsuleowner = user + playsound(src, 'sound/effects/splat.ogg', 30, 1) + var/item = pick(winitems) + sleep(100) + switch(luckynumber7) + if(1) capsuleowner.resize(RESIZE_TINY) //Loss Shrinking! + if(2) capsuleowner.apply_damage(5, BRUTE) //Loss Damaging! + if(3) capsuleowner.Weaken(5) //Loss Knee spaghetti! + if(4) capsuleowner.hallucination += 66 //loss woah, dude. + if(5) new item(capsuleowner.loc) //Win! + if(7) + new /obj/item/weapon/material/butterfly/switchblade(capsuleowner.loc) + capsuleowner.apply_damage(10, BRUTE) //Loss Damaging! WIN KNIVE! + if(9) + new /obj/item/weapon/gun/energy/sizegun/not_advanced(capsuleowner.loc) + qdel(src) + if(777) new /obj/item/weapon/spacecash/c1000(capsuleowner.loc) //for rigging + else luckynumber7 = (rand(0,10)) + luckynumber7 = rand(0,10) + sleep(100) + playsound(src.loc, 'sound/machines/slotmachine.ogg', 25, 1) + +//items literally just made for the above item spawner + +// +//BADvanced size gun +// +/obj/item/weapon/gun/energy/sizegun/not_advanced + name = "Corrupted size gun" + desc = "A highly advanced ray gun with a knob on the side to adjust the size you desire. Or at least that's what it used to be." + projectile_type = /obj/item/projectile/beam/sizelaser/chaos + charge_cost = 60 //1/3 of the base price for a normal one. +// +//CHAOS laser +// +/obj/item/projectile/beam/sizelaser/chaos //The Defintiely not advanced sizeguns laser. + name = "chaos size beam" + light_color = "#FF0000" + light_range = 3 + light_power = 9 //should be plenty visible. + var/list/chaos_colors = list( + "#FF0000", + "#00FF00", + "#0000FF", + "#FFFF00", + "#00FFFF", + "#FF00FF", + "#000000", + "#FFFFFF", + "#F0F0F0", + "#0F0F0F", + ) + + on_hit(var/atom/target) + light_color = pick(chaos_colors) + var/chaos = rand(25,200) + var/mob/living/M = target + if(ishuman(target)) + var/mob/living/carbon/human/H = M + H.resize(chaos/100) + H.show_message(" The beam fires into your body, changing your size!") + H.updateicon() + else if (istype(target, /mob/living/)) + var/mob/living/H = M + H.resize(chaos/100) + H.updateicon() + else + return 1 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/stacks/tiles/fifty_spawner_tiles.dm b/code/game/objects/items/stacks/tiles/fifty_spawner_tiles.dm index 098926f535..4aabc88d2d 100644 --- a/code/game/objects/items/stacks/tiles/fifty_spawner_tiles.dm +++ b/code/game/objects/items/stacks/tiles/fifty_spawner_tiles.dm @@ -8,6 +8,12 @@ name = "stack of sifgrass" type_to_spawn = /obj/item/stack/tile/grass/sif +//CHOMPedit, delete if this is added upstream. +/obj/fiftyspawner/grass/sif/forest + name = "stack of sifgrass" + type_to_spawn = /obj/item/stack/tile/grass/sif/forest +//CHOMPedit end + /obj/fiftyspawner/wood name = "stack of wood" type_to_spawn = /obj/item/stack/tile/wood diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 1612725741..befe769b91 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -52,6 +52,12 @@ singular_name = "sivian grass floor tile" desc = "A patch of grass like those that decorate the plains of Sif." +//CHOMPedit: remove if this gets added upstream +/obj/item/stack/tile/grass/sif/forest + name = "sivian overgrowth tile" + singular_name = "sivian overgrowth floor tile" + desc = "A patch of dark overgrowth like those that decorate the plains of Sif." +//CHOMPedit end /* * Wood */ diff --git a/code/game/objects/items/weapons/material/material_weapons.dm b/code/game/objects/items/weapons/material/material_weapons.dm index 963f1d3683..4948adf425 100644 --- a/code/game/objects/items/weapons/material/material_weapons.dm +++ b/code/game/objects/items/weapons/material/material_weapons.dm @@ -99,6 +99,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/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm index 21bb1c9e8a..42e3792bb0 100644 --- a/code/game/turfs/flooring/flooring.dm +++ b/code/game/turfs/flooring/flooring.dm @@ -149,6 +149,17 @@ var/list/flooring_types build_type = /obj/item/stack/tile/grass/sif has_base_range = 1 +//CHOMPedit: sif/forest decl. If this ends up upstream just accept the upstream version. +/decl/flooring/grass/sif/forest + name = "thick growth" + desc = "A natural moss that has adapted to the sheer cold climate." + flags = TURF_REMOVE_SHOVEL + icon = 'icons/turf/outdoors.dmi' + icon_base = "grass_sif_dark" + build_type = /obj/item/stack/tile/grass/sif/forest + has_base_range = 1 +//CHOMPedit end + /decl/flooring/water name = "water" desc = "Water is wet, gosh, who knew!" diff --git a/code/game/turfs/simulated/outdoors/grass.dm b/code/game/turfs/simulated/outdoors/grass.dm index 57615f49b9..ac8a9c43b7 100644 --- a/code/game/turfs/simulated/outdoors/grass.dm +++ b/code/game/turfs/simulated/outdoors/grass.dm @@ -89,6 +89,7 @@ var/list/grass_types = list( /turf/simulated/floor/outdoors/grass/sif/forest name = "thick growth" icon_state = "grass_sif_dark0" + initial_flooring = /decl/flooring/grass/sif/forest //CHOMPedit: Remove if this ends up upstream edge_blending_priority = 5 tree_chance = 4 grass_chance = 1 @@ -99,3 +100,18 @@ var/list/grass_types = list( /obj/structure/flora/sif/tendrils = 30 ) +//CHOMPedit: animal spawning for sif rocks. This probably doesn't belong in grass.dm but it's where there other Sif spawns are, sue me. +/turf/simulated/floor/outdoors/rocks/sif + var/animal_chance = 0.3 //Should spawn around... 0-7 per round? Tweak as needed. + + var/animal_types = list( + /mob/living/simple_mob/vore/slug = 1 + ) + +/turf/simulated/floor/outdoors/rocks/sif/Initialize() + if(animal_chance && prob(animal_chance) && !check_density()) + var/animal_type = pickweight(animal_types) + new animal_type(src) + + . = ..() +//CHOMPedit end \ No newline at end of file diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 83542dcc08..d05b2d28b0 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -227,7 +227,6 @@ if(!void) void = new() - void.MakeGreed() screen += void if((prefs.lastchangelog != changelog_hash) && isnewplayer(src.mob)) //bolds the changelog button on the interface so we know there are updates. diff --git a/code/modules/client/preference_setup/loadout/loadout_eyes.dm b/code/modules/client/preference_setup/loadout/loadout_eyes.dm index d9eb426499..09e0fcdc47 100644 --- a/code/modules/client/preference_setup/loadout/loadout_eyes.dm +++ b/code/modules/client/preference_setup/loadout/loadout_eyes.dm @@ -27,6 +27,14 @@ ..() gear_tweaks += gear_tweak_free_color_choice +/datum/gear/eyes/thinblindfold + display_name = "blindfold, thin white (recolorable)" + path = /obj/item/clothing/glasses/sunglasses/thinblindfold + +/datum/gear/eyes/thinblindfold/New() + ..() + gear_tweaks += gear_tweak_free_color_choice + /datum/gear/eyes/glasses display_name = "Glasses, prescription" path = /obj/item/clothing/glasses/regular diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm index 4a3da55fc9..782111c161 100644 --- a/code/modules/client/preference_setup/vore/07_traits.dm +++ b/code/modules/client/preference_setup/vore/07_traits.dm @@ -58,21 +58,21 @@ if(pref.species != SPECIES_CUSTOM) pref.pos_traits.Cut() - pref.neu_traits.Cut() pref.neg_traits.Cut() - else - // Clean up positive traits - for(var/path in pref.pos_traits) - if(!(path in positive_traits)) - pref.pos_traits -= path - //Neutral traits - for(var/path in pref.neu_traits) - if(!(path in neutral_traits)) - pref.neu_traits -= path - //Negative traits - for(var/path in pref.neg_traits) - if(!(path in negative_traits)) - pref.neg_traits -= path + // Clean up positive traits + for(var/path in pref.pos_traits) + if(!(path in positive_traits)) + pref.pos_traits -= path + //Neutral traits + for(var/path in pref.neu_traits) + if(!(path in neutral_traits)) + pref.neu_traits -= path + if(!(pref.species == SPECIES_CUSTOM) && !(path in everyone_traits)) + pref.neu_traits -= path + //Negative traits + for(var/path in pref.neg_traits) + if(!(path in negative_traits)) + pref.neg_traits -= path var/datum/species/selected_species = GLOB.all_species[pref.species] if(selected_species.selects_bodytype) @@ -82,7 +82,6 @@ /datum/category_item/player_setup_item/vore/traits/copy_to_mob(var/mob/living/carbon/human/character) character.custom_species = pref.custom_species - var/datum/species/selected_species = GLOB.all_species[pref.species] if(character.isSynthetic()) //Checking if we have a synth on our hands, boys. pref.dirty_synth = 1 @@ -100,13 +99,15 @@ //Any additional non-trait settings can be applied here new_S.blood_color = pref.blood_color - //Any additional non-trait settings can be applied here - new_CS.blood_color = pref.blood_color + //Any additional non-trait settings can be applied here + new_S.blood_color = pref.blood_color + + if(pref.species == SPECIES_CUSTOM) + //Statistics for this would be nice + var/english_traits = english_list(new_S.traits, and_text = ";", comma_text = ";") + log_game("TRAITS [pref.client_ckey]/([character]) with: [english_traits]") //Terrible 'fake' key_name()... but they aren't in the same entity yet + else - if(pref.species == SPECIES_CUSTOM) - //Statistics for this would be nice - var/english_traits = english_list(new_CS.traits, and_text = ";", comma_text = ";") - log_game("TRAITS [pref.client_ckey]/([character]) with: [english_traits]") //Terrible 'fake' key_name()... but they aren't in the same entity yet /datum/category_item/player_setup_item/vore/traits/content(var/mob/user) . += "Custom Species Name: " @@ -117,15 +118,16 @@ . += "Icon Base: " . += "[pref.custom_base ? pref.custom_base : "Human"]
" + var/traits_left = pref.max_traits + . += "Traits Left: [traits_left]
" if(pref.species == SPECIES_CUSTOM) var/points_left = pref.starting_trait_points - var/traits_left = pref.max_traits + for(var/T in pref.pos_traits + pref.neg_traits) points_left -= traits_costs[T] traits_left-- . += "Points Left: [points_left]
" - . += "Traits Left: [traits_left]
" if(points_left < 0 || traits_left < 0 || !pref.custom_species) . += "^ Fix things! ^
" @@ -136,19 +138,18 @@ . += "
  • - [trait.name] ([trait.cost])
  • " . += "" - . += "Neutral Trait +
    " - . += "" - . += "Negative Trait +
    " . += "" + . += "Neutral Trait +
    " + . += "" . += "Blood Color: " //People that want to use a certain species to have that species traits (xenochimera/promethean/spider) should be able to set their own blood color. . += "Set Color" . += "R
    " @@ -224,8 +225,12 @@ picklist = positive_traits.Copy() - pref.pos_traits mylist = pref.pos_traits if(NEUTRAL_MODE) - picklist = neutral_traits.Copy() - pref.neu_traits - mylist = pref.neu_traits + if(pref.species == SPECIES_CUSTOM) + picklist = neutral_traits.Copy() - pref.neu_traits + mylist = pref.neu_traits + else + picklist = everyone_traits.Copy() - pref.neu_traits + mylist = pref.neu_traits if(NEGATIVE_MODE) picklist = negative_traits.Copy() - pref.neg_traits mylist = pref.neg_traits diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 56577053b0..c02bca7e13 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -399,6 +399,13 @@ BLIND // can't see anything desc = "A white blindfold that covers the eyes, preventing sight." icon_state = "blindfoldwhite" +/obj/item/clothing/glasses/sunglasses/thinblindfold + name = "thin white blindfold" + desc = "A thin blindfold to help protect sensitive eyes while still allowing some sight" + icon_state = "blindfoldwhite" + flash_protection = FLASH_PROTECTION_MODERATE //not as thick, only offers some protection + tint = TINT_HEAVY + /obj/item/clothing/glasses/sunglasses/blindfold/tape name = "length of tape" desc = "It's a robust DIY blindfold!" diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index 9ad92265a9..88764af536 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -6054,6 +6054,23 @@ . = ..() reagents.add_reagent("protein", 8) bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/chickennoodlesoup + name = "chicken noodle soup" + gender = PLURAL + desc = "A bright bowl of yellow broth with cuts of meat, noodles and carrots." + icon = 'icons/obj/food_custom.dmi' + icon_state = "chickennoodlesoup" + filling_color = "#ead90c" + nutriment_amt = 6 + nutriment_desc = list("warm soup" = 6) + center_of_mass = list("x"=16, "y"=5) + +/obj/item/weapon/reagent_containers/food/snacks/chickennoodlesoup/Initialize() + . = ..() + reagents.add_reagent("protein", 4) + reagents.add_reagent("water", 5) + bitesize = 6 /obj/item/weapon/reagent_containers/food/snacks/chickennoodlesoup name = "chicken noodle soup" diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index b615932f43..216eb0303c 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -940,6 +940,13 @@ I said no! /obj/item/weapon/reagent_containers/food/snacks/bun ) result = /obj/item/weapon/reagent_containers/food/snacks/chickenfillet + +/datum/recipe/chickennoodlesoup + fruit = list("carrot" = 1) + reagents = list("water" = 10) + items = list( /obj/item/weapon/reagent_containers/food/snacks/spagetti, /obj/item/weapon/reagent_containers/food/snacks/rawcutlet) + reagent_mix = RECIPE_REAGENT_REPLACE //Simplify end product + result = /obj/item/weapon/reagent_containers/food/snacks/chickennoodlesoup /datum/recipe/chickennoodlesoup fruit = list("carrot" = 1) diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm index ce13864e03..b3909968ba 100644 --- a/code/modules/games/cards.dm +++ b/code/modules/games/cards.dm @@ -343,7 +343,8 @@ H.update_icon() src.update_icon() usr.visible_message("\The [usr] plays \the [discarding].") - H.loc = get_step(usr,usr.dir) + H.loc = get_turf(usr) + H.Move(get_step(usr,usr.dir)) if(!cards.len) qdel(src) diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index c7a7c5fa39..4278436a97 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() ..() @@ -223,7 +224,7 @@ /datum/material/cloth/generate_recipes() recipes = list() - 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("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) recipes += new/datum/stack_recipe("uniform", /obj/item/clothing/under/color/white, 8, time = 15 SECONDS, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("foot wraps", /obj/item/clothing/shoes/footwraps, 2, time = 5 SECONDS, pass_stack_color = TRUE) @@ -238,6 +239,7 @@ 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("empty sandbag", /obj/item/stack/emptysandbag, 2, time = 2 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]") /datum/material/resin/generate_recipes() recipes = list() @@ -270,4 +272,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 c93c872672..2bac6e23d0 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/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 6f9242bf85..bce7209e18 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1338,6 +1338,8 @@ if(!O.up) found_welder = 1 if(!found_welder && nif && nif.flag_check(NIF_V_UVFILTER,NIF_FLAGS_VISION)) found_welder = 1 //VOREStation Add - NIF + if(istype(glasses, /obj/item/clothing/glasses/sunglasses/thinblindfold)) + found_welder = 1 if(!found_welder && istype(head, /obj/item/clothing/head/welding)) var/obj/item/clothing/head/welding/O = head if(!O.up) diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm index a94f1d80c0..c7871db8aa 100644 --- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm +++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm @@ -58,8 +58,6 @@ base_color = "#f0f0f0" color_mult = 1 - inherent_verbs = list(/mob/living/proc/shred_limb) - has_glowing_eyes = TRUE death_message = "phases to somewhere far away!" @@ -70,7 +68,7 @@ speech_bubble_appearance = "ghost" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) virus_immune = 1 diff --git a/code/modules/mob/living/carbon/human/species/species_vr.dm b/code/modules/mob/living/carbon/human/species/species_vr.dm index 353946d976..7c62d02b25 100644 --- a/code/modules/mob/living/carbon/human/species/species_vr.dm +++ b/code/modules/mob/living/carbon/human/species/species_vr.dm @@ -21,6 +21,8 @@ var/icon_height = 32 var/agility = 20 //prob() to do agile things + var/list/traits = list() + /datum/species/proc/update_attack_types() unarmed_attacks = list() for(var/u_type in unarmed_types) @@ -44,3 +46,29 @@ nif.nifsofts = nifsofts else ..() +/datum/species/proc/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) + ASSERT(to_copy) + ASSERT(istype(H)) + + if(ispath(to_copy)) + to_copy = "[initial(to_copy.name)]" + if(istext(to_copy)) + to_copy = GLOB.all_species[to_copy] + + var/datum/species/new_copy = new to_copy.type() + + new_copy.traits = traits + + //If you had traits, apply them + if(new_copy.traits) + for(var/trait in new_copy.traits) + var/datum/trait/T = all_traits[trait] + T.apply(new_copy,H) + + //Set up a mob + H.species = new_copy + + if(H.dna) + H.dna.ready_dna(H) + + return new_copy \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/alraune.dm b/code/modules/mob/living/carbon/human/species/station/alraune.dm index dc983730c1..434fd8add6 100644 --- a/code/modules/mob/living/carbon/human/species/station/alraune.dm +++ b/code/modules/mob/living/carbon/human/species/station/alraune.dm @@ -50,10 +50,6 @@ appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR inherent_verbs = list( - /mob/living/carbon/human/proc/succubus_drain, - /mob/living/carbon/human/proc/succubus_drain_finalize, - /mob/living/carbon/human/proc/succubus_drain_lethal, - /mob/living/carbon/human/proc/bloodsuck, /mob/living/carbon/human/proc/alraune_fruit_select) //Give them the voremodes related to wrapping people in vines and sapping their fluids color_mult = 1 @@ -451,7 +447,7 @@ //End of fruit gland code. -/datum/species/alraune/proc/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) +/datum/species/alraune/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) ASSERT(to_copy) ASSERT(istype(H)) @@ -477,6 +473,13 @@ new_copy.blood_mask = to_copy.blood_mask new_copy.damage_mask = to_copy.damage_mask new_copy.damage_overlays = to_copy.damage_overlays + new_copy.traits = traits + + //If you had traits, apply them + if(new_copy.traits) + for(var/trait in new_copy.traits) + var/datum/trait/T = all_traits[trait] + T.apply(new_copy,H) //Set up a mob H.species = new_copy diff --git a/code/modules/mob/living/carbon/human/species/station/blank_vr.dm b/code/modules/mob/living/carbon/human/species/station/blank_vr.dm index d640f31631..84b3a6c948 100644 --- a/code/modules/mob/living/carbon/human/species/station/blank_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/blank_vr.dm @@ -32,13 +32,11 @@ num_alternate_languages = 3 assisted_langs = list(LANGUAGE_EAL, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR - var/list/traits = list() - has_limbs = list( BP_TORSO = list("path" = /obj/item/organ/external/chest, "descriptor" = "torso"), BP_GROIN = list("path" = /obj/item/organ/external/groin, "descriptor" = "groin"), @@ -60,7 +58,7 @@ var/datum/species/real = GLOB.all_species[base_species] return real.race_key -/datum/species/custom/proc/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) +/datum/species/custom/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) ASSERT(to_copy) ASSERT(istype(H)) diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans_vr.dm b/code/modules/mob/living/carbon/human/species/station/prometheans_vr.dm index e465b2a3da..cb0b86abe8 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans_vr.dm @@ -15,7 +15,7 @@ spawn_flags = SPECIES_CAN_JOIN wikilink="https://wiki.vore-station.net/Promethean" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) color_mult = 1 mob_size = MOB_MEDIUM //As of writing, original was MOB_SMALL - Allows normal swapping @@ -34,10 +34,5 @@ /mob/living/carbon/human/proc/shapeshifter_select_tail, /mob/living/carbon/human/proc/shapeshifter_select_ears, /mob/living/proc/set_size, - /mob/living/carbon/human/proc/succubus_drain, - /mob/living/carbon/human/proc/succubus_drain_finalize, - /mob/living/carbon/human/proc/succubus_drain_lethal, - /mob/living/carbon/human/proc/slime_feed, - /mob/living/proc/eat_trash, /mob/living/carbon/human/proc/promethean_select_opaqueness, ) diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm index 53fcbc7fb9..cc5fc9cd33 100755 --- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm +++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm @@ -62,7 +62,7 @@ siemens_coefficient = 1.5 //Very bad zappy times rarity_value = 5 - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) has_organ = list( O_BRAIN = /obj/item/organ/internal/mmi_holder/posibrain/nano, @@ -101,9 +101,7 @@ /mob/living/carbon/human/proc/shapeshifter_select_gender, /mob/living/carbon/human/proc/shapeshifter_select_wings, /mob/living/carbon/human/proc/shapeshifter_select_tail, - /mob/living/carbon/human/proc/shapeshifter_select_ears, - /mob/living/proc/eat_trash, - /mob/living/carbon/human/proc/slime_feed + /mob/living/carbon/human/proc/shapeshifter_select_ears ) var/global/list/abilities = list() diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm index f3271cab3d..bed18e0924 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm @@ -25,12 +25,7 @@ inherent_verbs = list( /mob/living/carbon/human/proc/reconstitute_form, /mob/living/carbon/human/proc/sonar_ping, - /mob/living/carbon/human/proc/succubus_drain, - /mob/living/carbon/human/proc/succubus_drain_finalize, - /mob/living/carbon/human/proc/succubus_drain_lethal, - /mob/living/carbon/human/proc/bloodsuck, /mob/living/carbon/human/proc/tie_hair, - /mob/living/proc/shred_limb, /mob/living/proc/flying_toggle, /mob/living/proc/start_wings_hovering) //Xenochimera get all the special verbs since they can't select traits. @@ -60,7 +55,7 @@ spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE//Whitelisted as restricted is broken. appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) has_organ = list( //Same organ list as tajarans. O_HEART = /obj/item/organ/internal/heart, @@ -300,7 +295,7 @@ update_xenochimera_hud(H, danger, feral_state) -/datum/species/xenochimera/proc/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) +/datum/species/xenochimera/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) ASSERT(to_copy) ASSERT(istype(H)) @@ -326,6 +321,13 @@ new_copy.blood_mask = to_copy.blood_mask new_copy.damage_mask = to_copy.damage_mask new_copy.damage_overlays = to_copy.damage_overlays + new_copy.traits = traits + + //If you had traits, apply them + if(new_copy.traits) + for(var/trait in new_copy.traits) + var/datum/trait/T = all_traits[trait] + T.apply(new_copy,H) //Set up a mob H.species = new_copy @@ -411,7 +413,7 @@ spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) flesh_color = "#AFA59E" //Gray-ish. Not sure if this is really needed, but eh. base_color = "#333333" //Blackish-gray @@ -472,14 +474,11 @@ spawn_flags = SPECIES_IS_RESTRICTED //SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE CHOMPedit: disabled forever appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_EYE_COLOR - inherent_verbs = list( - /mob/living/proc/shred_limb, - /mob/living/proc/eat_trash) flesh_color = "#AFA59E" base_color = "#777777" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) heat_discomfort_strings = list( "Your fur prickles in the heat.", diff --git a/code/modules/mob/living/carbon/human/species/station/station_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_vr.dm index 6d76b5295d..44ce2dfe45 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_vr.dm @@ -40,12 +40,11 @@ spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR - inherent_verbs = list(/mob/living/proc/shred_limb) flesh_color = "#AFA59E" base_color = "#777777" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) heat_discomfort_strings = list( "Your fur prickles in the heat.", @@ -84,7 +83,6 @@ secondary_langs = list(LANGUAGE_SKRELLIAN) name_language = LANGUAGE_SKRELLIAN color_mult = 1 - inherent_verbs = list(/mob/living/proc/shred_limb) assisted_langs = list(LANGUAGE_EAL, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) min_age = 18 @@ -108,7 +106,7 @@ primitive_form = "Sobaka" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR @@ -137,7 +135,7 @@ secondary_langs = list(LANGUAGE_BIRDSONG) name_language = LANGUAGE_BIRDSONG color_mult = 1 - inherent_verbs = list(/mob/living/proc/shred_limb,/mob/living/proc/flying_toggle,/mob/living/proc/start_wings_hovering) + inherent_verbs = list(/mob/living/proc/flying_toggle,/mob/living/proc/start_wings_hovering) min_age = 18 max_age = 110 @@ -158,7 +156,7 @@ primitive_form = "Sparra" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR @@ -213,7 +211,7 @@ blood_color = "#240bc4" color_mult = 1 - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) heat_discomfort_strings = list( "Your fur prickles in the heat.", @@ -239,7 +237,7 @@ // gluttonous = 1 num_alternate_languages = 3 color_mult = 1 - inherent_verbs = list(/mob/living/proc/shred_limb, /mob/living/carbon/human/proc/lick_wounds) + inherent_verbs = list(/mob/living/carbon/human/proc/lick_wounds) male_scream_sound = null //CHOMPedit female_scream_sound = null //CHOMPedit @@ -260,7 +258,7 @@ spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) flesh_color = "#966464" base_color = "#B43214" @@ -278,7 +276,7 @@ min_age = 18 gluttonous = 0 inherent_verbs = list(/mob/living/proc/shred_limb) - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) descriptors = list() //CHOMPSedit: link to our wiki @@ -292,12 +290,12 @@ color_mult = 1 min_age = 18 gluttonous = 0 //Moving this here so I don't have to fix this conflict every time polaris glances at station.dm - inherent_verbs = list(/mob/living/proc/shred_limb, /mob/living/carbon/human/proc/lick_wounds) + inherent_verbs = list(/mob/living/carbon/human/proc/lick_wounds) heat_discomfort_level = 295 //Prevents heat discomfort spam at 20c //CHOMPSedit: links to our wiki wikilink="https://wiki.chompstation13.net/index.php?title=Tajaran" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) agility = 90 /datum/species/skrell @@ -311,13 +309,13 @@ //CHOMPedit: link to our wiki wikilink="https://wiki.chompstation13.net/index.php?title=Skrell" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) /datum/species/zaddat spawn_flags = SPECIES_CAN_JOIN min_age = 18 gluttonous = 0 - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) descriptors = list() //CHOMPedit: link to our wiki @@ -336,7 +334,7 @@ min_age = 18 //CHOMPedit: link to our wiki wikilink="https://wiki.chompstation13.net/index.php?title=Diona" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) /datum/species/teshari mob_size = MOB_SMALL //YW Edit: changed from MOB_MEDIUM to MOB_SMALL @@ -349,7 +347,7 @@ push_flags = ~HEAVY //Allows them to use micro step code. swap_flags = ~HEAVY gluttonous = 0 - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) descriptors = list() //CHOMPedit: link to our wiki @@ -359,7 +357,6 @@ inherent_verbs = list( /mob/living/carbon/human/proc/sonar_ping, /mob/living/proc/hide, - /mob/living/proc/shred_limb, /mob/living/proc/toggle_pass_table ) @@ -374,7 +371,7 @@ deform = 'icons/mob/human_races/r_def_human_vr.dmi' appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR min_age = 18 - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) base_color = "#EECEB3" //CHOMPedit: link to our wiki @@ -389,7 +386,6 @@ min_age = 18 icobase = 'icons/mob/human_races/r_vox_old.dmi' deform = 'icons/mob/human_races/r_def_vox_old.dmi' - inherent_verbs = list(/mob/living/proc/shred_limb, /mob/living/proc/eat_trash) descriptors = list( /datum/mob_descriptor/vox_markings = 0 ) @@ -409,7 +405,7 @@ datum/species/harpy secondary_langs = list(LANGUAGE_BIRDSONG) name_language = null color_mult = 1 - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) inherent_verbs = list(/mob/living/proc/flying_toggle,/mob/living/proc/start_wings_hovering) min_age = 18 @@ -503,8 +499,6 @@ datum/species/harpy base_color = "#f0f0f0" color_mult = 1 - inherent_verbs = list(/mob/living/proc/shred_limb) - has_glowing_eyes = TRUE male_cough_sounds = null @@ -514,7 +508,7 @@ datum/species/harpy speech_bubble_appearance = "ghost" - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) breath_type = null poison_type = null @@ -578,7 +572,7 @@ datum/species/harpy //primitive_form = "" //We don't have fennec-monkey sprites. spawn_flags = SPECIES_IS_RESTRICTED appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) flesh_color = "#AFA59E" base_color = "#333333" @@ -621,7 +615,7 @@ datum/species/harpy spawn_flags = SPECIES_IS_RESTRICTED appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR - genders = list(MALE, FEMALE, PLURAL, NEUTER, HERM) + genders = list(MALE, FEMALE, PLURAL, NEUTER) blood_color = "#12ff12" flesh_color = "#201730" @@ -632,4 +626,3 @@ datum/species/harpy "You feel uncomfortably warm.", "Your chitin feels hot." ) - inherent_verbs = list(/mob/living/proc/shred_limb) diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm index 5855a0ec18..709e5f53e3 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -72,7 +72,7 @@ cost = 0 var_changes = list("cold_level_1" = 200, "cold_level_2" = 150, "cold_level_3" = 90, "breath_cold_level_1" = 180, "breath_cold_level_2" = 100, "breath_cold_level_3" = 60, "cold_discomfort_level" = 210, "heat_level_1" = 305, "heat_level_2" = 360, "heat_level_3" = 700, "breath_heat_level_1" = 345, "breath_heat_level_2" = 380, "breath_heat_level_3" = 780, "heat_discomfort_level" = 295, "body_temperature" = 290) excludes = list(/datum/trait/hotadapt) - + /datum/trait/hotadapt name = "Heat-Adapted" desc = "You are able to withstand much hotter temperatures than other species, and can even be comfortable in extremely hot environments. You are also more vulnerable to cold environments, and have a higher body temperature as a consequence of these adaptations." @@ -128,6 +128,7 @@ YW change end */ name = "Minor Bloodsucker" desc = "Makes you unable to gain nutrition from anything but blood. To compensate, you get fangs that can be used to drain blood from prey." cost = 0 + custom_only = FALSE var_changes = list("gets_food_nutrition" = 0) //The verb is given in human.dm excludes = list(/datum/trait/bloodsucker_plus) @@ -139,6 +140,7 @@ YW change end */ name = "Succubus Drain" desc = "Makes you able to gain nutrition from draining prey in your grasp." cost = 0 + custom_only = FALSE /datum/trait/succubus_drain/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) @@ -150,6 +152,7 @@ YW change end */ name = "Feeder" desc = "Allows you to feed your prey using your own body." cost = 0 + custom_only = FALSE /datum/trait/feeder/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) @@ -159,6 +162,7 @@ YW change end */ name = "Hard Vore" //CHOMPedit Renamed Brutal Predation to Hard Vore, because some people don't know what this actually does desc = "Allows you to tear off limbs & tear out internal organs." cost = 0 + custom_only = FALSE /datum/trait/hard_vore/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) @@ -168,6 +172,7 @@ YW change end */ name = "Trash Can" desc = "Allows you to dispose of some garbage on the go instead of having to look for a bin or littering like an animal." cost = 0 + custom_only = FALSE var_changes = list("trashcan" = 1) /datum/trait/trashcan/apply(var/datum/species/S,var/mob/living/carbon/human/H) @@ -178,6 +183,7 @@ YW change end */ name = "Expensive Taste" desc = "You only gain nutrition from raw ore and refined minerals. There's nothing that sates the appetite better than precious gems, exotic or rare minerals and you have damn fine taste. Anything else is beneath you." cost = 0 + custom_only = FALSE var_changes = list("gets_food_nutrition" = 0, "eat_minerals" = 1) /datum/trait/gem_eater/apply(var/datum/species/S,var/mob/living/carbon/human/H) @@ -188,12 +194,14 @@ YW change end */ name = "Glowing Eyes" desc = "Your eyes show up above darkness. SPOOKY! And kinda edgey too." cost = 0 + custom_only = FALSE var_changes = list("has_glowing_eyes" = 1) /datum/trait/glowing_body name = "Glowing Body" desc = "Your body glows about as much as a PDA light! Settable color and toggle in Abilities tab ingame." cost = 0 + custom_only = FALSE /datum/trait/glowing_body/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) @@ -205,36 +213,42 @@ YW change end */ name = "Extreme Spice Intolerance" desc = "Spicy (and chilly) peppers are three times as strong. (This does not affect pepperspray.)" cost = 0 + custom_only = FALSE var_changes = list("spice_mod" = 3) // 300% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this! - + /datum/trait/spice_intolerance_basic name = "Heavy Spice Intolerance" desc = "Spicy (and chilly) peppers are twice as strong. (This does not affect pepperspray.)" cost = 0 + custom_only = FALSE var_changes = list("spice_mod" = 2) // 200% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this! /datum/trait/spice_intolerance_slight name = "Slight Spice Intolerance" desc = "You have a slight struggle with spicy foods. Spicy (and chilly) peppers are one and a half times stronger. (This does not affect pepperspray.)" cost = 0 + custom_only = FALSE var_changes = list("spice_mod" = 1.5) // 150% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this! /datum/trait/spice_tolerance_basic name = "Spice Tolerance" desc = "Spicy (and chilly) peppers are only three-quarters as strong. (This does not affect pepperspray.)" cost = 0 + custom_only = FALSE var_changes = list("spice_mod" = 0.75) // 75% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this! - + /datum/trait/spice_tolerance_advanced name = "Strong Spice Tolerance" desc = "Spicy (and chilly) peppers are only half as strong. (This does not affect pepperspray.)" cost = 0 + custom_only = FALSE var_changes = list("spice_mod" = 0.5) // 50% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this! /datum/trait/spice_immunity name = "Extreme Spice Tolerance" desc = "Spicy (and chilly) peppers are basically ineffective! (This does not affect pepperspray.)" cost = 0 + custom_only = FALSE var_changes = list("spice_mod" = 0.25) // 25% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this! /*YW CHANGE START: Commented out because we got our own variants @@ -243,36 +257,42 @@ YW change end */ name = "Liver of Air" desc = "The only way you can hold a drink is if it's in your own two hands, and even then you'd best not inhale too deeply near it. Drinks are three times as strong." cost = 0 + custom_only = FALSE var_changes = list("alcohol_mod" = 3) // 300% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! /datum/trait/alcohol_intolerance_basic name = "Liver of Lilies" desc = "You have a hard time with alcohol. Maybe you just never took to it, or maybe it doesn't agree with you... either way, drinks are twice as strong." cost = 0 + custom_only = FALSE var_changes = list("alcohol_mod" = 2) // 200% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! /datum/trait/alcohol_intolerance_slight name = "Liver of Tulips" desc = "You have a slight struggle with alcohol. Drinks are one and a half times stronger." cost = 0 + custom_only = FALSE var_changes = list("alcohol_mod" = 1.5) // 150% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! /datum/trait/alcohol_tolerance_basic name = "Liver of Iron" desc = "You can hold drinks much better than those lily-livered land-lubbers! Arr! Drinks are only three-quarters as strong." cost = 0 + custom_only = FALSE var_changes = list("alcohol_mod" = 0.75) // 75% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! - + /datum/trait/alcohol_tolerance_advanced name = "Liver of Steel" desc = "Drinks tremble before your might! You can hold your alcohol twice as well as those blue-bellied barnacle boilers! Drinks are only half as strong." cost = 0 + custom_only = FALSE var_changes = list("alcohol_mod" = 0.5) // 50% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! /datum/trait/alcohol_immunity name = "Liver of Durasteel" desc = "You've drunk so much that most booze doesn't even faze you. It takes something like a Pan-Galactic or a pint of Deathbell for you to even get slightly buzzed." cost = 0 + custom_only = FALSE var_changes = list("alcohol_mod" = 0.25) // 25% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! // Alcohol Traits End Here. YW CHANGE STOP*/ diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm index 434fc8d846..605da7e569 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm @@ -5,7 +5,8 @@ var/cost = 0 // 0 is neutral, negative cost means negative, positive cost means positive. var/list/var_changes // A list to apply to the custom species vars. var/list/excludes // Store a list of paths of traits to exclude, but done automatically if they change the same vars. - var/not_for_synths = 0 // Can freaking synths use those. + var/not_for_synths = FALSE // Can freaking synths use those. + var/custom_only = TRUE // Trait only available for custom species //Proc can be overridden lower to include special changes, make sure to call up though for the vars changes /datum/trait/proc/apply(var/datum/species/S,var/mob/living/carbon/human/H) diff --git a/code/modules/mob/living/silicon/robot/drone/zzz_unify_drone.dm b/code/modules/mob/living/silicon/robot/drone/zzz_unify_drone.dm new file mode 100644 index 0000000000..3ba5bb6ed1 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/drone/zzz_unify_drone.dm @@ -0,0 +1,64 @@ +//The chad Drone unify code rewritten to fit into this current codebase, god here we go + + +// LAWS +/******************** Drone fucking duh ********************/ +/datum/ai_laws/jani_drone + name = "Maintence Protocols" + law_header = "Maintenance Protocols" + +/datum/ai_laws/drone/New() + add_inherent_law("Do not interfere with the maintenance work of non-drones whenever possible.") + add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") + add_inherent_law("Cause no harm to the station or any crew on it.") + ..() + +/datum/ai_laws/construction_drone + name = "Construction Protocols" + law_header = "Construction Protocols" + +/datum/ai_laws/construction_drone/New() + add_inherent_law("Do not interfere with the construction work of non-drones whenever possible.") + add_inherent_law("Repair, refit and upgrade your assigned vessel.") + add_inherent_law("Prevent unplanned damage to your assigned vessel wherever possible.") + ..() + +/datum/ai_laws/mining_drone + name = "Excavation Protocols" + law_header = "Excavation Protocols" + +/datum/ai_laws/mining_drone/New() + add_inherent_law("Do not interfere with the excavation work of non-drones whenever possible.") + add_inherent_law("Provide materials for repairing, refitting, and upgrading your assigned vessel.") + add_inherent_law("Prevent unplanned damage to your assigned excavation equipment wherever possible.") + ..() + +/datum/ai_laws/security_drone + name = "Security Protocols" + law_header = "Security Protocols" + +/datum/ai_laws/security_drone/New() + add_inherent_law("Do not interfere with the security work of non-drones whenever possible.") + add_inherent_law("Provide protection to the crew and eliminate hostile lifeforms on your assigned vessel.") + add_inherent_law("Obey orders by security personnel except if they violate law 4.") + add_inherent_law("Lethal force requires a code higher than green AND orders by security to use it to authorize it.") + add_inherent_law("You must outfit yourself with a security beret.") + ..() + +//Alright lets take a look at the the scary base drone from dorne DM and mod that shit + +/mob/living/silicon/robot/drone + name = "unified drone" //Maintenance drones can be a Jani specific shell now, the normal drone will be a blank shell not really intended for use + law_type = /datum/ai_laws/drone + +/mob/living/silicon/robot/drone/jan + name = "maintenance drone" + law_type = /datum/ai_laws/jani_drone + +/mob/living/silicon/robot/drone/sec + name = "security drone" + law_type = /datum/ai_laws/security_drone + +/mob/living/silicon/robot/drone/min + name = "mining drone" + law_type = /datum/ai_laws/mining_drone \ No newline at end of file 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/mob/living/simple_mob/subtypes/vore/leopardmander_ch.dm b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander_ch.dm index a6f675a96c..d1503a7a47 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander_ch.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander_ch.dm @@ -1,7 +1,8 @@ /mob/living/simple_mob/vore/leopardmander name = "leopardmander" desc = "A huge salamander-like drake. They are best known for their rarity, their voracity, their very potent paralyzing venom, and their healing stomach. This one is white." - tt_desc = "Draconis Va'aen" + catalogue_data = list(/datum/category_item/catalogue/fauna/leopardmander) + tt_desc = "S Draconis uncia" icon = 'icons/mob/vore128x64_ch.dmi' icon_dead = "leopardmander-dead" icon_living = "leopardmander" diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/plants_ch/pitcher.dm b/code/modules/mob/living/simple_mob/subtypes/vore/plants_ch/pitcher.dm index af2a0dc214..4d1a78545a 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/plants_ch/pitcher.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/plants_ch/pitcher.dm @@ -159,7 +159,7 @@ GLOBAL_LIST_INIT(pitcher_plant_lure_messages, list( return if(fruit) if(nutrition >= PITCHER_SATED + NUTRITION_PITCHER) - var/turf/T = safepick(circleviewturfs(src, 2)) //Try this if the above doesn't work, add src.loc == T check to density check + var/turf/T = safepick(circleviewturfs(src, 2)) if(T.density) //No spawning in walls return else if(src.loc ==T) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/slug_ch.dm b/code/modules/mob/living/simple_mob/subtypes/vore/slug_ch.dm new file mode 100644 index 0000000000..1114303d96 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/slug_ch.dm @@ -0,0 +1,255 @@ +//Passive vore slug. This mob is intended to be annoying but harmless to anybody it can't eat. + +/mob/living/simple_mob/vore/slug + name = "slug" + desc = "A giant, cold-tolerant slug. It seems excessively passive." + catalogue_data = list(/datum/category_item/catalogue/fauna/slug) + tt_desc = "S Arion hortensis" + icon = 'icons/mob/vore_ch.dmi' + icon_dead = "slug-dead" + icon_living = "slug" + icon_state = "slug" + faction = "slug" //A faction other than neutral is necessary to get the slug to try eating station crew. + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + melee_damage_lower = 0 + melee_damage_upper = 1 //Not intended to pose any sort of threat outside of vore. Other code should stop it from ever attacking but this is an extra safety check. + friendly = list("blinks at") + response_help = "pokes" + response_disarm = "prods" + response_harm = "punches" + movement_cooldown = 40 //I guess you could call this a SNAIL'S PACE. + maxHealth = 500 + health = 500 + attacktext = list("headbutted") + minbodytemp = 80 + ai_holder_type = /datum/ai_holder/simple_mob/passive/slug_ch + vore_icons = SA_ICON_LIVING + armor = list( + "melee" = 98, + "bullet" = 0, + "laser" = -50, + "energy" = -50, + "bomb" = 0, + "bio" = 0, + "rad" = 100) //Relatively harmless but agonizing to kill with melee. + + glow_toggle = TRUE + glow_range = 1.3 //This seems to be the minimum range which makes glow visible. + glow_color = "#33ccff" //Same glow color as Sif trees. + glow_intensity = 1 + + + var/list/my_slime = list() + var/slime_max = 35 //With a slug which moves once every 10 seconds and a 5 minute delete timer, this should never exceed 30. + var/mob/living/vore_memory = null + +/mob/living/simple_mob/vore/slug //I guess separating the vore variables is a little more organized? + vore_bump_chance = 100 //Always attempt a bump nom if possible... + vore_bump_emote = "knocks over and begins slowly engulfing" + vore_active = 1 + vore_icons = 1 + vore_capacity = 1 + vore_pounce_chance = 100 //...while this should make bump noms always knock the target over. Passive AI meanwhile should mean this never affects combat since it doesn't fight back. + vore_ignores_undigestable = 0 + swallowTime = 100 //10 seconds. Easy to crawl away from when knocked over. + vore_default_mode = DM_DIGEST + +/mob/living/simple_mob/vore/slug/init_vore() + ..() + var/obj/belly/B = vore_selected + B.desc = "Somehow you remained still just long enough for the slug to wrap its radula around your body and gradually draw you into its pharynx. The slug moves with agonizing slowness and devours prey at a snail's pace; inch by inch you're crammed down its gullet and squishes and squeezed into the slug's gizzard. Thick walls bear down, covered with shallow, toothy ridges. The slimy moss in here suggests you're not the slug's diet but the gizzard seems intent on churning and scraping over you regardless..." + B.digest_burn = 0.1 + B.digest_brute = 0.2 + B.vore_verb = "engulf" + B.name = "gizzard" + B.mode_flags = DM_FLAG_THICKBELLY + B.escapechance = 5 + B.fancy_vore = 1 + B.vore_sound = "Squish2" + B.release_sound = "Pred Escape" + B.contamination_color = "cyan" + B.contamination_flavor = "Wet" + + + B.emote_lists[DM_DIGEST] = list( + "The toothy walls scrape and grind against your body.", + "The humid air feels thick and heavy, stinging faintly with each breath.", + "Heavy slime oozes over you, making it difficult to move." + ) //Why do so many vore mobs have endo emotes despite being digest only? + +/datum/category_item/catalogue/fauna/slug + name = "Sivian Fauna - Moss Slug" + desc = "Classification: S Arion hortensis\ +

    \ + A large herbivorous slug commonly spotted near northern waterways with abundant moss. The slug is remarkably resistant to blunt trauma despite its fleshy body due to a foul-tasting outer casing \ + of thick, mucus-filled tissue protecting the more vulnerable musculature beneath. Said mucus is a natural irritant and hardens rapidly in contact with air, sealing wounds and allowing the slug to shrug off most surface injuries. \ + Few predators exist for the Sivian slug due to the stinging slime's tendency to adhere to attacking claws and appendages.\ +

    \ + The Sivian slug is typically regarded as a pest due to the animal's large bulk and tendency to crush weak structures in its path. Most tools do little to dissuade the creature, forcing homesteads to rely on firearms or reinforced fencing \ + with a slippery coating the slug cannot stick to. While subsisting primarily on Sivian moss, the slug is an opportunistic predator known to eat small fauna which wander into its path. The slime excreted from the slug's foot is particularly sticky and capable of miring small animals. The Sivian slug glows faintly due to colonies bioluminescent bacteria present in its diet." + value = CATALOGUER_REWARD_EASY + +/mob/living/simple_mob/vore/slug/proc/spread_slime() + if(my_slime.len >= slime_max) + return + if(istype(get_turf(src), /turf/simulated/floor/water)) //Important to stop my_slime from filling with null entries in water. + return + var/obj/effect/slug_glue/G = new /obj/effect/slug_glue/(get_turf(src)) + G.my_slug = src + my_slime += G + +/mob/living/simple_mob/vore/slug/death() + ..() + for(var/obj/effect/slug_glue/G in my_slime) + G.my_slug = null + my_slime -= G //No point in keeping these loaded in the list when the slug dies if somehow the list sticks around after death. + +/mob/living/simple_mob/vore/slug/Moved() + . = ..() + spread_slime() + +/mob/living/simple_mob/vore/slug/do_attack(atom/A, turf/T) //Override of attack proc to ensure the slug can only attempt to eat people, not harm them. Inability to actually hurt anybody is intended, otherwise this mob wouldn't have 98 melee armor. + if(ckey) //If we're player controlled, use the default attack code. + return ..() + if(istype(A, /mob/living) && !will_eat(A)) + ai_holder.lose_target() //Ignore anybody we can't eat. + return + else //This is the parent do_attack() code for determining whether or not attacks can hit. + face_atom(A) + var/missed = FALSE + if(!isturf(A) && !(A in T) ) // Turfs don't contain themselves so checking contents is pointless if we're targeting a turf. + missed = TRUE + else if(!T.AdjacentQuick(src)) + missed = TRUE + + if(missed) // Most likely we have a slow attack and they dodged it or we somehow got moved. + add_attack_logs(src, A, "Animal-attacked (dodged)", admin_notify = FALSE) + playsound(src, 'sound/rakshasa/Decay1.ogg', 75, 1) + visible_message(span("warning", "\The [src] misses.")) + return FALSE + tryBumpNom(A) //Meant for bump noms but this works as intended here and has sanity checks. + +/mob/living/simple_mob/vore/slug/perform_the_nom(mob/living/user, mob/living/prey, mob/living/pred, obj/belly/belly, delay) + ..() + vore_memory = prey + +/datum/ai_holder/simple_mob/passive/slug_ch + wander = TRUE + base_wander_delay = 7 + wander_when_pulled = TRUE + vision_range = 10 + can_flee = FALSE //Otherwise it'll run as soon as it gets a target. + +/obj/effect/slug_glue + name = "liquid" + desc = "This looks wet." + icon = 'icons/effects/effects_ch.dmi' + icon_state = "wet_turf" + opacity = 0 + mouse_opacity = 0 //Unclickable + anchored = 1 + density = 0 + can_buckle = 1 + buckle_lying = TRUE + + var/persist_time = 5 MINUTES //How long until we cease existing. + var/mob/living/simple_mob/vore/slug/my_slug = null //This should be set by the slug. + var/turf/my_turf = null //The turf we spawn on. + var/base_escape_time = 1 MINUTE //How long does it take to struggle free? Affected by the victim's size_multiplier. + +/obj/effect/slug_glue/New() + ..() + dissipate() + my_turf = get_turf(src) + if(istype(my_turf, /turf/simulated/floor/water)) //Aside from not making sense in water, this prevents drowning. + qdel(src) +/* for(var/obj/effect/slug_glue/G in my_turf.contents) + if(G == src) + continue + else + qdel(G) //Prevent glue layering +*/ //Not including this due to performance concerns but keeping as comments for reference. + +/obj/effect/slug_glue/proc/dissipate() //When spawned, set a timer to despawn. + if(!persist_time) + qdel(src) + return + else + spawn(persist_time) //I used sleep() here first and it made the slug sleep for 5 minutes when spawning glue. Byond. + qdel(src) + return + +/obj/effect/slug_glue/Destroy() + . = ..() + if(my_slug) + my_slug.my_slime -= src //Remove the slime from the slug's list when destroyed. + +//This could probably be applied to spideweb code to make it work as intended again. +/obj/effect/slug_glue/Uncross(atom/movable/AM, atom/newloc) + if(istype(AM, /mob/living/simple_mob/vore/slug)) + return ..() + else if(istype(AM, /mob/living)) + if(prob(50)) + to_chat(AM, span("warning", "You stick to \the [my_turf]!")) + return FALSE + return ..() + + +/obj/effect/slug_glue/Crossed(atom/movable/AM as mob|obj) + if(AM.is_incorporeal()) + return + + if(istype(AM, /mob/living)) + var/mob/living/L = AM + if(istype(L, /mob/living/simple_mob/vore/slug)) + return + + if(L.m_intent == "run" && !L.buckled) + if(has_buckled_mobs()) + return + buckle_mob(L) + L.stop_pulling() + L.Weaken(2) + to_chat(L, "You tripped in the sticky substance, sticking to [my_turf]!") + playsound(src, 'sound/rakshasa/Decay3.ogg', 100, 1) + alert_slug(L) + +/obj/effect/slug_glue/proc/alert_slug(mob/living/victim as mob) + if(!my_slug || !has_buckled_mobs() || isbelly(my_slug.loc)) //Otherwise if you eat the slug it will infinitely attempt to eat you if you trip in glue. + return + if(my_slug.vore_memory == victim) //Getting eaten lets you get stuck once without alerting the slug. This is to prevent instantly getting eaten again if you struggle free with run intent on. + my_slug.vore_memory = null + return + my_slug.ai_holder.give_target(victim) + +/obj/effect/slug_glue/proc/unalert_slug(mob/living/victim as mob) + if(!my_slug) + return + if(my_slug.ai_holder.target == victim) + my_slug.ai_holder.remove_target() //Instant loss of target. Necessary to simulate the mob giving up if the prey escapes. + +/obj/effect/slug_glue/user_unbuckle_mob(mob/living/buckled_mob, mob/user) + user.setClickCooldown(user.get_attack_speed()) + to_chat(user, "You tug and strain against the sticky substance...") + var/escape_time + switch(buckled_mob.size_multiplier) + if(RESIZE_TINY - 1 to RESIZE_A_NORMALSMALL) //24% to 75% size scale, 1% below 25% is to account for microcillin sometimes going slightly below 25% + escape_time = 2 * base_escape_time + if(RESIZE_A_NORMALSMALL to RESIZE_A_BIGNORMAL) //75% to 125% size scale + escape_time = base_escape_time + if(RESIZE_A_BIGNORMAL to RESIZE_HUGE + 1) //125% to 201% size scale, 1% above 200% is to acount for macrocillin sometimes going slightly above 200% + escape_time = 0.5 * base_escape_time + else + escape_time = base_escape_time //Admeme size scale + if(do_after(user, escape_time, src, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY))) + if(!has_buckled_mobs()) + return + to_chat(user, "You tug free of the tacky, rubbery strands!") + unbuckle_mob(buckled_mob) + unalert_slug(buckled_mob) + +/obj/effect/slug_glue/clean_blood(var/ignore = 0) //Remove with space cleaner. + if(!ignore) + qdel(src) + return + ..() \ No newline at end of file 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/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index 20597d8b36..bf753d7cb2 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -43,7 +43,7 @@ //Actual full digest modes var/tmp/static/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_ABSORB,DM_DRAIN,DM_UNABSORB,DM_HEAL,DM_SHRINK,DM_GROW,DM_SIZE_STEAL,DM_EGG) //Digest mode addon flags - var/tmp/static/list/mode_flag_list = list("Numbing" = DM_FLAG_NUMBING, "Stripping" = DM_FLAG_STRIPPING, "Leave Remains" = DM_FLAG_LEAVEREMAINS, "Muffles" = DM_FLAG_THICKBELLY) + var/tmp/static/list/mode_flag_list = list("Numbing" = DM_FLAG_NUMBING, "Stripping" = DM_FLAG_STRIPPING, "Leave Remains" = DM_FLAG_LEAVEREMAINS, "Muffles" = DM_FLAG_THICKBELLY, "Affect Worn Items" = DM_FLAG_AFFECTWORN) //Item related modes var/tmp/static/list/item_digest_modes = list(IM_HOLD,IM_DIGEST_FOOD,IM_DIGEST) diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm index 1048903d6c..95162dfb15 100644 --- a/code/modules/vore/eating/bellymodes_vr.dm +++ b/code/modules/vore/eating/bellymodes_vr.dm @@ -138,6 +138,16 @@ if((mode_flags & DM_FLAG_THICKBELLY) && !H.muffled) H.muffled = TRUE + //Worn items flag + if(mode_flags & DM_FLAG_AFFECTWORN) + for(var/slot in slots) + var/obj/item/I = H.get_equipped_item(slot = slot) + if(I && I.canremove) + if(handle_digesting_item(I)) + digestion_noise_chance = 25 + to_update = TRUE + break + //Stripping flag if(mode_flags & DM_FLAG_STRIPPING) for(var/slot in slots) 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/effects/effects_ch.dmi b/icons/effects/effects_ch.dmi index f01cd218f3..1b7c81dc81 100644 Binary files a/icons/effects/effects_ch.dmi and b/icons/effects/effects_ch.dmi differ diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index 2071c634d1..75ba00f026 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ diff --git a/icons/mob/species/seromi/eyes.dmi b/icons/mob/species/seromi/eyes.dmi index e50b97c956..250a56d4f9 100644 Binary files a/icons/mob/species/seromi/eyes.dmi and b/icons/mob/species/seromi/eyes.dmi differ diff --git a/icons/mob/species/werebeast/back.dmi b/icons/mob/species/werebeast/back.dmi index 14cd04dbdd..f04103f7a7 100644 Binary files a/icons/mob/species/werebeast/back.dmi and b/icons/mob/species/werebeast/back.dmi differ diff --git a/icons/mob/species/werebeast/uniform.dmi b/icons/mob/species/werebeast/uniform.dmi index e441c4af6d..267847085f 100644 Binary files a/icons/mob/species/werebeast/uniform.dmi and b/icons/mob/species/werebeast/uniform.dmi differ diff --git a/icons/mob/vore_ch.dmi b/icons/mob/vore_ch.dmi index 6f12d18848..aae5553e32 100644 Binary files a/icons/mob/vore_ch.dmi and b/icons/mob/vore_ch.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index e410088a23..93d368d42c 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 473b6614e6..3c252b8d35 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/clothing/uniforms_1.dmi b/icons/obj/clothing/uniforms_1.dmi index eba7fa299f..9478ef888d 100644 Binary files a/icons/obj/clothing/uniforms_1.dmi and b/icons/obj/clothing/uniforms_1.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 97554f5c71..4a505e8dd0 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1166,6 +1166,7 @@ #include "code\game\objects\items\pizza_voucher_vr.dm" #include "code\game\objects\items\poi_items.dm" #include "code\game\objects\items\robobag.dm" +#include "code\game\objects\items\sahoc_ch.dm" #include "code\game\objects\items\shooting_range.dm" #include "code\game\objects\items\surplus_voucher_ch.dm" #include "code\game\objects\items\tailoring.dm" @@ -1249,6 +1250,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" @@ -1463,6 +1465,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" @@ -2878,6 +2881,7 @@ #include "code\modules\mob\living\silicon\robot\drone\swarm.dm" #include "code\modules\mob\living\silicon\robot\drone\swarm_abilities.dm" #include "code\modules\mob\living\silicon\robot\drone\swarm_items.dm" +#include "code\modules\mob\living\silicon\robot\drone\zzz_unify_drone.dm" #include "code\modules\mob\living\silicon\robot\robot_modules\event.dm" #include "code\modules\mob\living\silicon\robot\robot_modules\event_vr.dm" #include "code\modules\mob\living\silicon\robot\robot_modules\station.dm" @@ -3080,6 +3084,7 @@ #include "code\modules\mob\living\simple_mob\subtypes\vore\rat_ch.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\redpanda.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\sect_queen.dm" +#include "code\modules\mob\living\simple_mob\subtypes\vore\slug_ch.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\snake.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\softdog.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\solargrub.dm" @@ -3410,6 +3415,7 @@ #include "code\modules\power\antimatter\shielding.dm" #include "code\modules\power\cells\device_cells.dm" #include "code\modules\power\cells\device_cells_vr.dm" +#include "code\modules\power\cells\esoteric_cells.dm" #include "code\modules\power\cells\power_cells.dm" #include "code\modules\power\fusion\_setup.dm" #include "code\modules\power\fusion\fusion_circuits.dm"