diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 4af93d6ff876..18fd079608b4 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -84361,6 +84361,11 @@ }, /turf/open/floor/iron, /area/station/commons/dorms) +"uCq" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/loafer, +/turf/open/floor/plating, +/area/station/maintenance/department/security) "uCt" = ( /obj/effect/spawner/random/structure/chair_maintenance{ dir = 1 @@ -151776,7 +151781,7 @@ adM uHP dth fws -vHY +uCq rYA vHY hie diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 8e2776eef326..1b58e0ec08bb 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -30106,6 +30106,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/mine/production) +"jLk" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/spawner/random/loafer, +/turf/open/floor/plating, +/area/station/security/prison/safe) "jLl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden, /obj/effect/turf_decal/siding/yellow{ @@ -170915,7 +170922,7 @@ wRa vVH nRO ulz -ulz +jLk ulz pNm eOz diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 5d3a454518ed..fa27b7dffd28 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -39676,6 +39676,10 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"omE" = ( +/obj/effect/spawner/random/loafer, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "omF" = ( /obj/machinery/teleport/station, /obj/machinery/status_display/evac/directional/north, @@ -90451,7 +90455,7 @@ aaa bxr jXu rOz -sHu +omE siY jXu aaa diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index acd6f5664038..8571488858ee 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -61887,6 +61887,7 @@ /turf/open/floor/iron/white, /area/station/medical/storage) "sQY" = ( +/obj/effect/spawner/random/loafer, /turf/open/floor/iron/smooth, /area/station/maintenance/department/eva) "sQZ" = ( diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index dd653a8d7900..70ba23836678 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -70,6 +70,9 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 /// Yes I know this is a stupid flag, no you can't take him from me #define DECAL_INIT_UPDATE_EXPERIENCED_1 (1<<20) +/// Used for items that cannot be used directly to harm people with, ex. loafs +#define CANNOT_ATTACK_WITH (1<<21) + // Update flags for [/atom/proc/update_appearance] /// Update the atom's name #define UPDATE_NAME (1<<0) diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index d99019e61a57..83cc88c4063c 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -219,7 +219,7 @@ SUBSYSTEM_DEF(throwing) if (callback) callback.Invoke() - if(!thrownthing.currently_z_moving) // I don't think you can zfall while thrown but hey, just in case. + if(!thrownthing?.currently_z_moving) // I don't think you can zfall while thrown but hey, just in case. var/turf/T = get_turf(thrownthing) T?.zFall(thrownthing) diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index 221d4945c0e2..ae6bc7f5a599 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -310,7 +310,12 @@ Behavior that's still missing from this component that original food items had t var/atom/owner = parent - if((feeder.istate & ISTATE_HARM)) + var/obj/item/food/foodstuff + + if(istype(owner, /obj/item/food)) + foodstuff = owner + + if((feeder.istate & ISTATE_HARM) && !(foodstuff?.force_feed_on_aggression)) //monkestation edit - add loafing return . = COMPONENT_CANCEL_ATTACK_CHAIN //Point of no return I suppose diff --git a/code/game/objects/items/food/_food.dm b/code/game/objects/items/food/_food.dm index a790cb65f4c4..b18f0b09f9fc 100644 --- a/code/game/objects/items/food/_food.dm +++ b/code/game/objects/items/food/_food.dm @@ -46,7 +46,8 @@ var/decomp_req_handle = FALSE ///Used to set custom decomposition times for food. Set to 0 to have it automatically set via the food's flags. var/decomposition_time = 0 - + ///If we want to still force feed food even on combat mode or harm intent - monkestation edit + var/force_feed_on_aggression = FALSE ///The food buffs the food has var/food_buffs = STATUS_EFFECT_FOOD_STAM_MEDIUM diff --git a/monkestation/code/modules/loafing/README.txt b/monkestation/code/modules/loafing/README.txt new file mode 100644 index 000000000000..cd5b1e842aae --- /dev/null +++ b/monkestation/code/modules/loafing/README.txt @@ -0,0 +1,41 @@ +## Title: + + +MODULE ID: LOAFING + +### Description: + +This module adds a loafing mechanic. + + + +### TG Proc/File Changes: + +changed /datum/component/edible/proc/TryToEat(mob/living/eater, mob/living/feeder) in edible.dm +changed _food.dm + + + + +### Defines: + + + + +### Master file additions + +- N/A + + +### Included files that are not contained in this module: + +- N/A + + +### Credits: + + + +Code and sprites done by Lmenvs. Concept from Goon. + + diff --git a/monkestation/code/modules/loafing/code/loaf.dm b/monkestation/code/modules/loafing/code/loaf.dm new file mode 100644 index 000000000000..fa6526876aaa --- /dev/null +++ b/monkestation/code/modules/loafing/code/loaf.dm @@ -0,0 +1,266 @@ +/obj/item/food/prison_loaf + name = "prison loaf" + desc = "A barely edible brick of nutrients, designed as a low-cost solution to malnourishment." + icon = 'monkestation/code/modules/loafing/icons/obj.dmi' + icon_state = "loaf" + food_reagents = list(/datum/reagent/consumable/nutraslop = 10) + var/loaf_density = 1 //base loaf density + var/can_condense = TRUE //for special loaves, make false + force_feed_on_aggression = TRUE + //vars for high level loafs + + var/critical = FALSE + var/atom/movable/warp_effect/warp + + + var/lifespan = ANOMALY_COUNTDOWN_TIMER //works similar to grav anomaly when hits critical + var/death_time + var/countdown_colour = COLOR_ASSEMBLY_LBLUE + var/obj/effect/countdown/loaf/countdown + var/boing = 0 + var/obj/singularity/singuloaf + +/obj/item/food/prison_loaf/process(seconds_per_tick) + anomalyEffect(seconds_per_tick) + if(death_time < world.time) + if(loc) + detonate() + qdel(src) + +/obj/item/food/prison_loaf/Destroy() + STOP_PROCESSING(SSobj, src) + QDEL_NULL(countdown) + vis_contents -= warp + warp = null + return ..() + +/obj/item/food/prison_loaf/proc/anomalyEffect(seconds_per_tick) + if(SPT_PROB(ANOMALY_MOVECHANCE, seconds_per_tick)) + step(src,pick(GLOB.alldirs)) + boing = 1 + for(var/obj/object in orange(4, src)) + if(!object.anchored) + step_towards(object,src) + for(var/mob/living/M in range(0, src)) + gravShock(M) + for(var/mob/living/M in orange(4, src)) + if(!M.mob_negates_gravity()) + step_towards(M,src) + for(var/obj/object in range(0,src)) + if(!object.anchored) + if(isturf(object.loc)) + var/turf/T = object.loc + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(object, TRAIT_T_RAY_VISIBLE)) + continue + var/mob/living/target = locate() in view(4,src) + if(target && !target.stat) + object.throw_at(target, 5, 10) + animate(warp, time = seconds_per_tick*3, transform = matrix().Scale(0.5,0.5)) + animate(time = seconds_per_tick*7, transform = matrix()) + +/obj/item/food/prison_loaf/proc/detonate() + var/turf/T = get_turf(src) + log_game("\A [src] critical loaf has ended its lifespan, turning into a singularity at [AREACOORD(T)].") + message_admins("A [src.name] critical loaf has ended its lifespan, turning into a singularity at [ADMIN_VERBOSEJMP(T)].") + + singuloaf = new /obj/singularity/(src) + singuloaf.loc = src.loc + return + +/obj/item/food/prison_loaf/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) + . = ..() + if(same_z_layer) + return + if(warp) + SET_PLANE(warp, PLANE_TO_TRUE(warp.plane), new_turf) + +/obj/item/food/prison_loaf/proc/on_entered(datum/source, atom/movable/AM) + SIGNAL_HANDLER + gravShock(AM) + +/obj/item/food/prison_loaf/Bump(atom/A) + if(critical) + gravShock(A) + else + return ..() + +/obj/item/food/prison_loaf/Bumped(atom/movable/AM) + if(critical) + gravShock(AM) + else + return ..() + +/obj/item/food/prison_loaf/proc/gravShock(mob/living/A) + if(boing && isliving(A) && !A.stat) + A.Paralyze(40) + var/atom/target = get_edge_target_turf(A, get_dir(src, get_step_away(A, src))) + A.throw_at(target, 5, 1) + boing = 0 + +/obj/item/food/prison_loaf/proc/critical() + src.critical = TRUE + var/turf/T = get_turf(src) + notify_ghosts("A [src] has been condensed to the point of criticality!", source=src, action=NOTIFY_ORBIT, header="Loaf Criticality!!") + log_game("\A [src] has been condensed to the point of criticality at [AREACOORD(T)].") + message_admins("A [src.name] has been condensed to the point of criticality at [ADMIN_VERBOSEJMP(T)].") + death_time = world.time + lifespan + warp = new(src) + vis_contents += warp + countdown = new(src) + if(countdown_colour) + countdown.color = countdown_colour + countdown.start() + can_condense = FALSE + START_PROCESSING(SSobj, src) + +/obj/effect/countdown/loaf + name = "singuloaf countdown" + +/obj/effect/countdown/loaf/get_value() + var/obj/item/food/prison_loaf/loaf = attached_to + if(!istype(loaf)) + return + else + var/time_left = max(0, (loaf.death_time - world.time) / 10) + return round(time_left) + +/obj/item/food/prison_loaf/rod + name = "rod loaf" + desc = "If you loaf something, set it free. If it comes back, it's yours." + icon_state = "rod_loaf" + can_condense = FALSE + +/obj/item/food/prison_loaf/rod/after_throw(datum/callback/callback) + . = ..() + var/startside = pick(GLOB.cardinals) + var/turf/end_turf = get_edge_target_turf(get_random_station_turf(), turn(startside, 180)) + var/turf/start_turf = get_turf(usr) + var/atom/rod = new /obj/effect/immovablerod/loaf(start_turf, end_turf) + notify_ghosts("[usr.name] has an object of interest: [rod]!", source=rod, action=NOTIFY_ORBIT, header="Something's Interesting!") + qdel(src) + +/obj/effect/immovablerod/loaf + name = "immovable loaf" + desc = "Oh no, the flavor is coming right for us!" + icon = 'monkestation/code/modules/loafing/icons/obj.dmi' + icon_state = "rod_loaf" + +/obj/machinery/power/supermatter_crystal/loaf + name = "suppermatter loaf" //you can't kill me for my bad puns. they make me immortal. + desc = "A prison loaf that has condensed and crystalized to the point where it can be used as a standard power source." + icon = 'monkestation/code/modules/loafing/icons/obj.dmi' + icon_state = "sm" + + + +/obj/item/food/prison_loaf/proc/condense() + if(!src.can_condense) + return + switch(src.loaf_density) + if(0 to 10) + src.name = initial(src.name) + src.desc = "A barely edible brick of nutrients, designed as a low-cost solution to malnourishment." + src.icon_state = initial(src.icon_state) + "0" + src.force = 0 + src.throwforce = 0 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 1) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 1) + if(11 to 100) + src.name = "dense " + initial(src.name) + src.desc = initial(src.desc) + "\n This loaf is noticeably heavier than usual." + src.icon_state = initial(src.icon_state) + "0" + src.force = 2 + src.throwforce = 2 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 3) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 3) + if(101 to 250) + src.name = "compacted " + initial(src.name) + src.desc = initial(src.desc) + "\n Hooh, this thing packs a punch. What are they putting into these?" + src.icon_state = initial(src.icon_state) + "0" + src.force = 4 + src.throwforce = 4 + src.throw_range = 6 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 5) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 5) + if(251 to 500) + src.name = "super-compressed " + initial(src.name) + src.desc = initial(src.desc) + "\n Hard enough to scratch a diamond, yet still somehow edible,\n this loaf seems to be emitting decay heat. Dear god." + src.icon_state = initial(src.icon_state) + "1" + src.force = 5 + src.throwforce = 5 + src.throw_range = 6 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 8) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 8) + if(501 to 2500) + src.name = "molecular " + initial(src.name) + src.desc = initial(src.desc) + "\n The loaf has become so dense that no food particulates are visible to the naked eye." + src.icon_state = initial(src.icon_state) + "2" + src.force = 10 + src.throwforce = 10 + src.throw_range = 5 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 10) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 10) + src.reagents.add_reagent(/datum/reagent/consumable/corn_syrup, 5) + if(2501 to 10000) + src.name = "atomic " + initial(src.name) + src.desc = initial(src.desc) + "\n Forget food particulates, the loaf is now comprised of flavor atoms." + src.icon_state = initial(src.icon_state) + "3" + src.force = 20 + src.throwforce = 20 + src.throw_range = 4 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 10) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 10) + src.reagents.add_reagent(/datum/reagent/growthserum, 5) + if(10001 to 25000) + src.name = "sub atomic " + initial(src.name) + src.desc = initial(src.desc) + "\n Oh good, the flavor atoms in this prison loaf have collapsed down to a a solid lump of neutrons. Eating this could prove dangerous." + src.icon_state = initial(src.icon_state) + "4" + src.force = 30 + src.throwforce = 30 + src.throw_range = 3 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 10) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 10) + src.reagents.add_reagent(/datum/reagent/consumable/vitfro, 25) + if(25001 to 50000) + src.name = "quark " + initial(src.name) + src.desc = initial(src.desc) + "\n This nutritional loaf is collapsing into subatomic flavor particles. Consuption could convert your DNA into synthetic sludge." + src.icon_state = initial(src.icon_state) + "5" + src.force = 50 + src.throwforce = 50 + src.throw_range = 2 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 10) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 10) + src.reagents.add_reagent(/datum/reagent/mulligan, 25) + if(50001 to 100000) + src.name = "strangelet " + initial(src.name) + src.desc = initial(src.desc) + "\n At this point you may be considering: has man gone too far? Are we meant to have food this powerful?" + src.icon_state = initial(src.icon_state) + "6" + src.force = 75 + src.throwforce = 75 + src.throw_range = 1 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 10) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 10) + src.reagents.add_reagent(/datum/reagent/cyborg_mutation_nanomachines, 50) + if(100001 to 1000000) + src.name = "quantum " + initial(src.name) + src.desc = initial(src.desc) + "\n The mere existence of this nutritional masterpiece is causing reality to distort!" + src.icon_state = initial(src.icon_state) + "7" + src.force = 100 + src.throwforce = 100 + src.throw_range = 0 + src.reagents.add_reagent(/datum/reagent/consumable/salt, 10) + src.reagents.add_reagent(/datum/reagent/consumable/nutraslop, 10) + src.reagents.add_reagent(/datum/reagent/gravitum, 100) + critical() + + +/datum/export/food/loaf + cost = 10 + unit_name = "loaf" + message = "of Nutraloaf" + export_types = list(/obj/item/food/prison_loaf) + +/datum/export/food/loaf/get_cost(obj/O) + var/obj/item/food/prison_loaf/loaf = O + cost = max(10, loaf.loaf_density / 5) + return ..() diff --git a/monkestation/code/modules/loafing/code/loafer.dm b/monkestation/code/modules/loafing/code/loafer.dm new file mode 100644 index 000000000000..b74221e3dc5e --- /dev/null +++ b/monkestation/code/modules/loafing/code/loafer.dm @@ -0,0 +1,114 @@ +/obj/structure/disposalpipe/loafer + name = "loafing device" + desc = "A prisoner feeding device that condenses matter into an Ultra Delicious(tm) nutrition bar!" + icon = 'monkestation/code/modules/loafing/icons/obj.dmi' + icon_state = "loafer" + var/is_loafing = FALSE + var/list/loaf_blacklist = list(/obj/item/organ/internal/brain, /obj/item/bodypart/head) + +/obj/structure/disposalpipe/loafer/transfer(obj/structure/disposalholder/holder) + if(is_loafing) + return src + //check if there's anything in there + if (holder.contents.len) + //start playing sound + is_loafing = TRUE + src.icon_state = "loafer-on" + src.update_appearance() + playsound(src, 'monkestation/code/modules/loafing/sound/loafer.ogg', 100, 1, mixer_channel = CHANNEL_MACHINERY) + + //create new loaf + var/obj/item/food/prison_loaf/loaf = new /obj/item/food/prison_loaf(src) + + //add all the garbage to the loaf's contents + for (var/atom/movable/debris in holder) + if(debris.resistance_flags & INDESTRUCTIBLE || (debris.type in loaf_blacklist)) + if(holder.contents.len > 1) + continue + else + loaf = null + src.icon_state = "loafer" + is_loafing = FALSE + return transfer_to_dir(holder, nextdir(holder)) + if(debris.reagents)//the object has reagents + debris.reagents.trans_to(loaf, 1000) + if(istype(debris, /obj/item/food/prison_loaf))//the object is a loaf, compress somehow + var/obj/item/food/prison_loaf/loaf_to_grind = debris + loaf.loaf_density += loaf_to_grind.loaf_density * 1.05 + loaf_to_grind = null + else if(isliving(debris)) + var/mob/living/victim = debris + //different mobs add different reagents + if(issilicon(victim)) + loaf.reagents.add_reagent(/datum/reagent/fuel, 10) + loaf.reagents.add_reagent(/datum/reagent/iron, 10) + else + loaf.reagents.add_reagent(/datum/reagent/bone_dust, 3) + loaf.reagents.add_reagent(/datum/reagent/ammonia/urine, 2) + loaf.reagents.add_reagent(/datum/reagent/consumable/liquidgibs, 2) + loaf.reagents.add_reagent(/datum/reagent/consumable/nutriment/organ_tissue, 2) + //then we give the loaf more power + if(ishuman(victim)) + loaf.loaf_density += 25 + else + loaf.loaf_density += 10 + if(!isdead(victim)) + victim.emote("scream") + victim.gib() + if(victim.mind || victim.client) + victim.ghostize(FALSE) + else if (istype(debris, /obj/item))//everything else + var/obj/item/kitchen_sink = debris + var/weight = kitchen_sink.w_class + loaf.loaf_density += weight * 3 + holder.contents -= debris + qdel(debris) + + sleep(3 SECONDS) + + //condense the loaf + loaf.condense() + //place the loaf + loaf.forceMove(holder) + holder.contents += loaf + is_loafing = FALSE + src.icon_state = "loafer" + return transfer_to_dir(holder, nextdir(holder)) + +/obj/structure/disposalpipe/loafer/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + if(disassembled) + if(stored) + stored.forceMove(loc) + transfer_fingerprints_to(stored) + stored.setDir(dir) + stored = null + else + var/turf/T = get_turf(src) + for(var/D in GLOB.cardinals) + if(D & dpdir) + var/obj/structure/disposalpipe/broken/P = new(T) + P.setDir(D) + spew_forth() + qdel(src) + +/obj/structure/disposalconstruct/loafer + name = "loafing device" + desc = "A prisoner feeding device that condenses matter into an Ultra Delicious(tm) nutrition bar!" + icon = 'monkestation/code/modules/loafing/icons/obj.dmi' + icon_state = "conloafer" + pipe_type = /obj/structure/disposalpipe/loafer + + +//spawning + +/obj/effect/spawner/random/loafer + name = "loafer spawner" + spawn_scatter_radius = 5 + spawn_loot_chance = 20 + layer = DISPOSAL_PIPE_LAYER + +/obj/effect/spawner/random/loafer/Initialize(mapload) + loot = list( + /obj/structure/disposalpipe/loafer/) + return ..() diff --git a/monkestation/code/modules/loafing/icons/obj.dmi b/monkestation/code/modules/loafing/icons/obj.dmi new file mode 100644 index 000000000000..8fedcae132d5 Binary files /dev/null and b/monkestation/code/modules/loafing/icons/obj.dmi differ diff --git a/monkestation/code/modules/loafing/sound/loafer.ogg b/monkestation/code/modules/loafing/sound/loafer.ogg new file mode 100644 index 000000000000..4ce15e80e60b Binary files /dev/null and b/monkestation/code/modules/loafing/sound/loafer.ogg differ diff --git a/monkestation/code/modules/mech_comp/vending_machine.dm b/monkestation/code/modules/mech_comp/vending_machine.dm index 82fdecef5f66..35293de5ff7b 100644 --- a/monkestation/code/modules/mech_comp/vending_machine.dm +++ b/monkestation/code/modules/mech_comp/vending_machine.dm @@ -40,6 +40,7 @@ /obj/item/mcobject/messaging/storage = STANDARD_COMPONENT_SUPPLY, /obj/item/mcobject/messaging/type_sensor = STANDARD_COMPONENT_SUPPLY, /obj/item/mcobject/messaging/clock = STANDARD_COMPONENT_SUPPLY, + /obj/item/mcobject/messaging/repeater = LOW_COMPONENT_SUPPLY ) diff --git a/tgstation.dme b/tgstation.dme index 238b739b1010..e20c511ce225 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5916,6 +5916,8 @@ #include "monkestation\code\modules\loadouts\items\toys.dm" #include "monkestation\code\modules\loadouts\items\under\donator.dm" #include "monkestation\code\modules\loadouts\items\under\under.dm" +#include "monkestation\code\modules\loafing\code\loaf.dm" +#include "monkestation\code\modules\loafing\code\loafer.dm" #include "monkestation\code\modules\maptext\maptext_image_helper.dm" #include "monkestation\code\modules\mech_comp\_interface.dm" #include "monkestation\code\modules\mech_comp\_message.dm"