From e040d243866c60a83528e161fb1e5d532666da0d Mon Sep 17 00:00:00 2001 From: Noelle Lavenza Date: Sun, 16 Nov 2025 13:17:39 -0500 Subject: [PATCH 001/149] Add 'in wallet' abstract inventory slot --- code/__defines/items_clothing.dm | 1 + code/_global_vars/lists/clothing.dm | 5 +++-- code/_global_vars/lists/names.dm | 3 ++- code/game/objects/items/__item.dm | 3 +++ code/modules/mob/inventory.dm | 16 +++++++++++++++- code/modules/species/species_hud.dm | 2 ++ maps/~mapsystem/maps.dm | 2 +- 7 files changed, 27 insertions(+), 5 deletions(-) diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm index ffd20f690f9..eaa502407f5 100644 --- a/code/__defines/items_clothing.dm +++ b/code/__defines/items_clothing.dm @@ -82,6 +82,7 @@ #define slot_r_store_str "slot_r_store" #define slot_s_store_str "slot_s_store" #define slot_in_backpack_str "slot_in_backpack" +#define slot_in_wallet_str "slot_in_wallet" // Defined here for consistency, not actually used for slots, just for species clothing offsets. #define slot_undershirt_str "slot_undershirt" diff --git a/code/_global_vars/lists/clothing.dm b/code/_global_vars/lists/clothing.dm index a819fa7c527..c77cb035a88 100644 --- a/code/_global_vars/lists/clothing.dm +++ b/code/_global_vars/lists/clothing.dm @@ -30,6 +30,7 @@ var/global/list/airtight_slots = list( var/global/list/abstract_inventory_slots = list( slot_in_backpack_str, + slot_in_wallet_str, slot_undershirt_str, slot_underpants_str, slot_socks_str @@ -40,7 +41,7 @@ var/global/list/vitals_sensor_equip_slots = list( ) var/global/list/headphone_slots = list( - slot_l_ear_str, - slot_r_ear_str, + slot_l_ear_str, + slot_r_ear_str, slot_head_str ) diff --git a/code/_global_vars/lists/names.dm b/code/_global_vars/lists/names.dm index 78cd73fe25b..741c433285d 100644 --- a/code/_global_vars/lists/names.dm +++ b/code/_global_vars/lists/names.dm @@ -6,5 +6,6 @@ var/global/list/verbs = file2list("config/names/verbs.txt") var/global/list/adjectives = file2list("config/names/adjectives.txt") var/global/list/abstract_slot_names = list( - slot_in_backpack_str = "In Backpack" + slot_in_backpack_str = "In Backpack", + slot_in_wallet_str = "In Wallet" ) diff --git a/code/game/objects/items/__item.dm b/code/game/objects/items/__item.dm index f548bcbfada..d9164b23c5e 100644 --- a/code/game/objects/items/__item.dm +++ b/code/game/objects/items/__item.dm @@ -726,6 +726,9 @@ if(slot == slot_in_backpack_str) var/obj/item/back = user.get_equipped_item(slot_back_str) return back?.storage?.can_be_inserted(src, user, TRUE) + if(slot == slot_in_wallet_str) + var/obj/item/wallet = user.get_equipped_item(slot_wear_id_str) + return wallet?.storage?.can_be_inserted(src, user, TRUE) var/datum/inventory_slot/inv_slot = user.get_inventory_slot_datum(slot) if(!inv_slot) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index b306780544b..a565d1e1aae 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -61,6 +61,14 @@ else prop.dropInto(loc) return TRUE + if(slot == slot_in_wallet_str) + remove_from_mob(prop) + var/obj/item/wallet = get_equipped_item(slot_wear_id_str) + if(wallet) + prop.forceMove(wallet) + else + prop.dropInto(loc) + return TRUE // Attempt to equip accessories if the slot is already blocked. if(!delete_old_item && get_equipped_item(slot)) @@ -126,10 +134,16 @@ /mob/proc/equip_to_storage(obj/item/newitem) // Try put it in their backpack var/obj/item/back = get_equipped_item(slot_back_str) - if(back?.storage?.can_be_inserted(newitem, null, 1)) + if(back?.storage?.can_be_inserted(newitem, null, TRUE)) back.storage.handle_item_insertion(src, newitem) return back + // Or in their wallet + var/obj/item/wallet = get_equipped_item(slot_wear_id_str) + if(wallet?.storage?.can_be_inserted(newitem, null, TRUE)) + wallet.storage.handle_item_insertion(src, newitem) + return wallet + // Try to place it in any item that can store stuff, on the mob. for(var/obj/item/thing in contents) if(thing?.storage?.can_be_inserted(newitem, null, 1)) diff --git a/code/modules/species/species_hud.dm b/code/modules/species/species_hud.dm index 6c67caea5d2..17ab4381d16 100644 --- a/code/modules/species/species_hud.dm +++ b/code/modules/species/species_hud.dm @@ -41,6 +41,8 @@ equip_slots |= slot_handcuffed_str if(slot_back_str in equip_slots) equip_slots |= slot_in_backpack_str + if(slot_wear_id_str in equip_slots) + equip_slots |= slot_in_wallet_str /datum/hud_data/monkey inventory_slots = list( diff --git a/maps/~mapsystem/maps.dm b/maps/~mapsystem/maps.dm index c09d5bc2488..7adfcd3d86b 100644 --- a/maps/~mapsystem/maps.dm +++ b/maps/~mapsystem/maps.dm @@ -548,7 +548,7 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also toggleable var/obj/item/passport/pass = new passport_type(get_turf(H)) if(istype(pass)) pass.set_info(H) - if(!H.equip_to_slot(pass, slot_in_backpack_str)) + if(!H.equip_to_slot(pass, slot_in_wallet_str) && !H.equip_to_slot(pass, slot_in_backpack_str)) H.put_in_hands(pass) /datum/map/proc/populate_overmap_events() From 1989ef824aea9a607278d1c62892caef7b459099 Mon Sep 17 00:00:00 2001 From: Noelle Lavenza Date: Mon, 17 Nov 2025 19:01:58 -0500 Subject: [PATCH 002/149] Allow quick-equip to place items in backpacks/wallets --- code/datums/inventory_slots/_inventory_slot.dm | 2 ++ code/datums/inventory_slots/slots/slot_back.dm | 1 + code/datums/inventory_slots/slots/slot_id.dm | 1 + code/modules/mob/living/inventory.dm | 6 ++++++ 4 files changed, 10 insertions(+) diff --git a/code/datums/inventory_slots/_inventory_slot.dm b/code/datums/inventory_slots/_inventory_slot.dm index 6f23b1b51a1..b27b2a93090 100644 --- a/code/datums/inventory_slots/_inventory_slot.dm +++ b/code/datums/inventory_slots/_inventory_slot.dm @@ -19,6 +19,8 @@ var/requires_slot_flags var/requires_organ_tag var/quick_equip_priority = 0 // Higher priority means it will be checked first. If null, will not be considered for quick equip. + /// Additional slot ID(s) to add in quick equip. Will always be added at the lowest priority. + var/list/additional_quick_equip_slots /// What depth of fluid is necessary for an item in this slot to be considered submerged? var/fluid_height = FLUID_SHALLOW // we're treating FLUID_SHALLOW as waist level, basically diff --git a/code/datums/inventory_slots/slots/slot_back.dm b/code/datums/inventory_slots/slots/slot_back.dm index 7c2496867ed..25b320f578a 100644 --- a/code/datums/inventory_slots/slots/slot_back.dm +++ b/code/datums/inventory_slots/slots/slot_back.dm @@ -8,6 +8,7 @@ mob_overlay_layer = HO_BACK_LAYER quick_equip_priority = 14 fluid_height = (FLUID_SHALLOW + FLUID_OVER_MOB_HEAD) / 2 // halfway between waist and top of head, so roughly chest level + additional_quick_equip_slots = list(slot_in_backpack_str) /datum/inventory_slot/back/simple requires_organ_tag = null diff --git a/code/datums/inventory_slots/slots/slot_id.dm b/code/datums/inventory_slots/slots/slot_id.dm index 67b759c682c..ecde7fc83db 100644 --- a/code/datums/inventory_slots/slots/slot_id.dm +++ b/code/datums/inventory_slots/slots/slot_id.dm @@ -7,6 +7,7 @@ mob_overlay_layer = HO_ID_LAYER quick_equip_priority = 13 fluid_height = (FLUID_SHALLOW + FLUID_OVER_MOB_HEAD) / 2 // halfway between waist and top of head, so roughly chest level + additional_quick_equip_slots = list(slot_in_wallet_str) // try to go as late as possible /datum/inventory_slot/id/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) var/obj/item/clothing/clothes = user.get_equipped_item(slot_w_uniform_str) diff --git a/code/modules/mob/living/inventory.dm b/code/modules/mob/living/inventory.dm index 4d3d35090dc..a7d0bb0ca26 100644 --- a/code/modules/mob/living/inventory.dm +++ b/code/modules/mob/living/inventory.dm @@ -14,10 +14,16 @@ var/list/all_slots = list() for(var/slot in get_inventory_slots()) all_slots += get_inventory_slot_datum(slot) + var/list/low_priority_slots // Slots that will always be added at the end, in the order of their parent slots' priority. + // This is sort of due to technical limitations but mostly due to laziness. for(var/datum/inventory_slot/inv_slot as anything in sortTim(all_slots, /proc/cmp_inventory_slot_desc)) + if(LAZYLEN(inv_slot.additional_quick_equip_slots)) + for(var/extra_slot in inv_slot.additional_quick_equip_slots) + LAZYADD(low_priority_slots, extra_slot) if(isnull(inv_slot.quick_equip_priority)) // Never quick-equip into some slots. continue _inventory_slot_priority += inv_slot.slot_id + _inventory_slot_priority += low_priority_slots return _inventory_slot_priority /mob/living/get_inventory_slot_datum(var/slot) From c1c4c4f5b6ce79898d4a6100aab09848cf551e32 Mon Sep 17 00:00:00 2001 From: mistakenot4892 Date: Fri, 26 Dec 2025 19:28:02 +1100 Subject: [PATCH 003/149] Porting quadbikes from Polaris. --- .../datums/composite_sounds/vehicle_engine.dm | 7 + code/datums/supplypacks/operations.dm | 4 +- code/game/turfs/flooring/_flooring.dm | 3 + code/game/turfs/flooring/flooring_grass.dm | 6 + code/game/turfs/flooring/flooring_mud.dm | 9 + code/game/turfs/flooring/flooring_natural.dm | 3 + code/game/turfs/flooring/flooring_rock.dm | 3 + code/game/turfs/flooring/flooring_snow.dm | 11 + code/game/turfs/floors/_floor.dm | 6 + code/modules/mob/mob.dm | 2 +- code/modules/vehicles/bike.dm | 15 +- code/modules/vehicles/cargo_train.dm | 300 +++++++----------- code/modules/vehicles/cargo_trolley.dm | 103 ++++++ code/modules/vehicles/quad_bike.dm | 198 ++++++++++++ code/modules/vehicles/quad_trailer.dm | 108 +++++++ code/modules/vehicles/train.dm | 21 +- code/modules/vehicles/vehicle.dm | 46 ++- icons/obj/custom_items_vehicle.dmi | Bin 0 -> 218 bytes icons/obj/vehicles_64x64.dmi | Bin 0 -> 19406 bytes maps/away/errant_pisces/errant_pisces.dmm | 8 +- maps/exodus/exodus-2.dmm | 4 +- maps/ministation/ministation-0.dmm | 4 +- .../government/away_sites/icarus/icarus-1.dmm | 6 +- nebula.dme | 4 + sound/machines/vehicle/engine_end.ogg | Bin 0 -> 49838 bytes sound/machines/vehicle/engine_mid.ogg | Bin 0 -> 40211 bytes sound/machines/vehicle/engine_start.ogg | Bin 0 -> 39943 bytes sound/machines/vehicle/ignition.ogg | Bin 0 -> 10613 bytes 28 files changed, 642 insertions(+), 229 deletions(-) create mode 100644 code/datums/composite_sounds/vehicle_engine.dm create mode 100644 code/modules/vehicles/cargo_trolley.dm create mode 100644 code/modules/vehicles/quad_bike.dm create mode 100644 code/modules/vehicles/quad_trailer.dm create mode 100644 icons/obj/custom_items_vehicle.dmi create mode 100644 icons/obj/vehicles_64x64.dmi create mode 100644 sound/machines/vehicle/engine_end.ogg create mode 100644 sound/machines/vehicle/engine_mid.ogg create mode 100644 sound/machines/vehicle/engine_start.ogg create mode 100644 sound/machines/vehicle/ignition.ogg diff --git a/code/datums/composite_sounds/vehicle_engine.dm b/code/datums/composite_sounds/vehicle_engine.dm new file mode 100644 index 00000000000..824d0044134 --- /dev/null +++ b/code/datums/composite_sounds/vehicle_engine.dm @@ -0,0 +1,7 @@ +/datum/composite_sound/vehicle_engine + start_sound = 'sound/machines/vehicle/engine_start.ogg' + start_length = 2 + mid_sounds = list('sound/machines/vehicle/engine_mid.ogg'=1) + mid_length = 6 + end_sound = 'sound/machines/vehicle/engine_end.ogg' + play_volume = 20 diff --git a/code/datums/supplypacks/operations.dm b/code/datums/supplypacks/operations.dm index 09c51789dc3..0ec89477c5e 100644 --- a/code/datums/supplypacks/operations.dm +++ b/code/datums/supplypacks/operations.dm @@ -3,13 +3,13 @@ /decl/hierarchy/supply_pack/operations/cargotrain name = "Equipment - Cargo Train Tug" - contains = list(/obj/vehicle/train/cargo/engine) + contains = list(/obj/vehicle/train/engine) containertype = /obj/structure/largecrate containername = "cargo train tug crate" /decl/hierarchy/supply_pack/operations/cargotrailer name = "Equipment - Cargo Train Trolley" - contains = list(/obj/vehicle/train/cargo/trolley) + contains = list(/obj/vehicle/train/trolley) containertype = /obj/structure/largecrate containername = "cargo train trolley crate" diff --git a/code/game/turfs/flooring/_flooring.dm b/code/game/turfs/flooring/_flooring.dm index f5f8083873f..bca8e7bbea6 100644 --- a/code/game/turfs/flooring/_flooring.dm +++ b/code/game/turfs/flooring/_flooring.dm @@ -391,3 +391,6 @@ var/global/list/flooring_cache = list() /// contaminant is, optionally, the material of the coating that wants to be added. /decl/flooring/proc/can_show_coating_footprints(turf/target, decl/material/contaminant) return TRUE + +/decl/flooring/proc/get_vehicle_transit_delay(obj/vehicle/vehicle) + return vehicle::base_speed diff --git a/code/game/turfs/flooring/flooring_grass.dm b/code/game/turfs/flooring/flooring_grass.dm index dc53aaf4680..7d8a10d2948 100644 --- a/code/game/turfs/flooring/flooring_grass.dm +++ b/code/game/turfs/flooring/flooring_grass.dm @@ -48,6 +48,9 @@ return TRUE return ..() +/decl/flooring/grass/get_vehicle_transit_delay(obj/vehicle/vehicle) + return 1 + /decl/flooring/grass/fake desc = "Do they smoke grass out in space, Bowie? Or do they smoke AstroTurf?" icon = 'icons/turf/flooring/fakegrass.dmi' @@ -56,3 +59,6 @@ build_type = /obj/item/stack/tile/grass force_material = /decl/material/solid/organic/plastic uid = "floor_grass_fake" + +/decl/flooring/grass/fake/get_vehicle_transit_delay(obj/vehicle/vehicle) + return vehicle::base_speed diff --git a/code/game/turfs/flooring/flooring_mud.dm b/code/game/turfs/flooring/flooring_mud.dm index bdce5b2859e..41591c57457 100644 --- a/code/game/turfs/flooring/flooring_mud.dm +++ b/code/game/turfs/flooring/flooring_mud.dm @@ -33,6 +33,9 @@ return FALSE return ..() +/decl/flooring/mud/get_vehicle_transit_delay(obj/vehicle/vehicle) + return vehicle.vehicle_transit_type == vehicle::VEHICLE_SNOWMOBILE ? 1.4 : 1.5 + /decl/flooring/dry_mud name = "dry mud" desc = "This was once mud, but forgot to keep hydrated." @@ -46,6 +49,9 @@ force_material = /decl/material/solid/soil uid = "floor_dry_mud" +/decl/flooring/dry_mud/get_vehicle_transit_delay(obj/vehicle/vehicle) + return 1 + /decl/flooring/dry_mud/fluid_act(turf/floor/target, datum/reagents/fluids) if(target.get_topmost_flooring() == src) target.set_flooring(/decl/flooring/mud) @@ -76,3 +82,6 @@ target.set_base_flooring(/decl/flooring/mud) . = TRUE return . || ..() + +/decl/flooring/dirt/get_vehicle_transit_delay(obj/vehicle/vehicle) + return 1 diff --git a/code/game/turfs/flooring/flooring_natural.dm b/code/game/turfs/flooring/flooring_natural.dm index 128bdc34cbc..ea8adec4397 100644 --- a/code/game/turfs/flooring/flooring_natural.dm +++ b/code/game/turfs/flooring/flooring_natural.dm @@ -70,6 +70,9 @@ force_material = /decl/material/solid/ice uid = "floor_ice" +/decl/flooring/ice/get_vehicle_transit_delay(obj/vehicle/vehicle) + return vehicle.vehicle_transit_type == vehicle::VEHICLE_SNOWMOBILE ? 0.8 : ..() + /decl/flooring/ice/update_turf_icon(turf/floor/target) . = ..() if(istype(target)) diff --git a/code/game/turfs/flooring/flooring_rock.dm b/code/game/turfs/flooring/flooring_rock.dm index 13836a0a7da..3bf779b61da 100644 --- a/code/game/turfs/flooring/flooring_rock.dm +++ b/code/game/turfs/flooring/flooring_rock.dm @@ -14,3 +14,6 @@ ASSERT(turf_material?.adjective_name) target.SetName("[turf_material.adjective_name] [name]") target.desc = "An expanse of bare [turf_material.solid_name]." + +/decl/flooring/rock/get_vehicle_transit_delay(obj/vehicle/vehicle) + return vehicle.vehicle_transit_type == vehicle::VEHICLE_SNOWMOBILE ? 1.5 : ..() diff --git a/code/game/turfs/flooring/flooring_snow.dm b/code/game/turfs/flooring/flooring_snow.dm index 881da81bdcc..cccda657fad 100644 --- a/code/game/turfs/flooring/flooring_snow.dm +++ b/code/game/turfs/flooring/flooring_snow.dm @@ -46,6 +46,9 @@ return FALSE return ..() +/decl/flooring/snow/get_vehicle_transit_delay(obj/vehicle/vehicle) + return vehicle.vehicle_transit_type == vehicle::VEHICLE_SNOWMOBILE ? 0.8 : 1.7 + /decl/flooring/permafrost name = "permafrost" desc = "A stretch of frozen soil that hasn't seen a thaw for many seasons." @@ -54,8 +57,16 @@ force_material = /decl/material/solid/ice uid = "floor_permafrost" +/decl/flooring/permafrost/get_vehicle_transit_delay(obj/vehicle/vehicle) + if(holographic) + return vehicle::base_speed + if(vehicle.vehicle_transit_type == vehicle::VEHICLE_SNOWMOBILE) + return 0.8 + return ..() + /decl/flooring/snow/fake name = "holosnow" desc = "Not quite the same as snow on an entertainment terminal, but close." holographic = TRUE uid = "floor_snow_fake" + diff --git a/code/game/turfs/floors/_floor.dm b/code/game/turfs/floors/_floor.dm index 3982c3dab82..0f5109932c2 100644 --- a/code/game/turfs/floors/_floor.dm +++ b/code/game/turfs/floors/_floor.dm @@ -189,3 +189,9 @@ /turf/floor/can_show_coating_footprints(decl/material/contaminant = null) return ..() && get_topmost_flooring()?.can_show_coating_footprints(src, contaminant) + +/turf/floor/proc/get_vehicle_transit_delay(obj/vehicle/vehicle) + var/decl/flooring/terrain = get_topmost_flooring() + if(!istype(vehicle) || QDELETED(vehicle) || !istype(terrain) || vehicle.vehicle_transit_type == vehicle::VEHICLE_GENERIC) + return vehicle::base_speed + return terrain.get_vehicle_transit_delay(vehicle) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index dadb2de1b99..e0952f1222c 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -713,7 +713,7 @@ var/global/const/ACTION_DANGER_ALL = 2 return TRUE if(!anchored && istype(over, /obj/vehicle/train)) var/obj/vehicle/train/beep = over - if(!beep.load(src)) + if(!beep.load_onto_vehicle(src)) to_chat(user, SPAN_WARNING("You were unable to load \the [src] onto \the [over].")) return TRUE . = ..() diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm index 7522827dc86..49e6274920d 100644 --- a/code/modules/vehicles/bike.dm +++ b/code/modules/vehicles/bike.dm @@ -32,7 +32,7 @@ update_icon() /obj/vehicle/bike/user_buckle_mob(mob/living/M, mob/user) - return load(M) + return load_onto_vehicle(M) /obj/vehicle/bike/verb/toggle() set name = "Toggle Engine" @@ -89,11 +89,12 @@ qdel(trail) trail = null -/obj/vehicle/bike/load(var/atom/movable/loading) +/obj/vehicle/bike/load_onto_vehicle(var/atom/movable/loading) + if(!isliving(loading)) + return FALSE var/mob/living/M = loading - if(!istype(M)) return 0 if(M.buckled || M.anchored || M.restrained() || !Adjacent(M) || !M.Adjacent(src)) - return 0 + return FALSE return ..(M) /obj/vehicle/bike/emp_act(var/severity) @@ -124,14 +125,14 @@ /obj/vehicle/bike/receive_mouse_drop(atom/dropping, mob/user, params) . = ..() if(!. && istype(dropping, /atom/movable)) - if(!load(dropping)) + if(!load_onto_vehicle(dropping)) to_chat(user, SPAN_WARNING("You were unable to load \the [dropping] onto \the [src].")) return TRUE /obj/vehicle/bike/attack_hand(var/mob/user) if(user != load) return ..() - unload(load) + unload_from_vehicle(load) to_chat(user, "You unbuckle yourself from \the [src].") return TRUE @@ -139,7 +140,7 @@ if(user != load || !on) return if(user.incapacitated()) - unload(user) + unload_from_vehicle(user) visible_message("\The [user] falls off \the [src]!") return return Move(get_step(src, direction)) diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index f828d2f4e1c..4fcb9ee46ce 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -1,18 +1,21 @@ -/obj/vehicle/train/cargo/engine +/obj/vehicle/train/engine name = "cargo train tug" - desc = "A rideable electric car designed for pulling cargo trolleys." + desc = "A ridable electric car designed for pulling cargo trolleys." icon = 'icons/obj/vehicles.dmi' icon_state = "cargo_engine" on = 0 powered = 1 locked = 0 + load_item_visible = 1 load_offset_x = 0 buckle_pixel_shift = list("x" = 0, "y" = 0, "z" = 7) charge_use = 1 KILOWATTS active_engines = 1 + var/car_limit = 3 //how many cars an engine can pull before performance degrades - var/obj/item/key/cargo_train/key + var/obj/item/key/key + var/key_type = /obj/item/key/cargo_train /obj/item/key/cargo_train desc = "A small key on a yellow fob reading \"Choo Choo!\"." @@ -24,34 +27,24 @@ icon_state = "train_keys" w_class = ITEM_SIZE_TINY -/obj/vehicle/train/cargo/trolley - name = "cargo train trolley" - icon = 'icons/obj/vehicles.dmi' - icon_state = "cargo_trailer" - anchored = FALSE - passenger_allowed = 0 - locked = 0 - buckle_pixel_shift = list("x" = 0, "y" = 0, "z" = 8) - - load_item_visible = 1 - load_offset_x = 0 - load_offset_y = 4 - - //------------------------------------------- // Standard procs //------------------------------------------- -/obj/vehicle/train/cargo/engine/Initialize() +/obj/vehicle/train/engine/Initialize() . = ..() cell = new /obj/item/cell/high(src) - key = new(src) - var/image/I = new(icon = icon, icon_state = "cargo_engine_overlay") + key = new key_type(src) + update_icon() + turn_off() //so engine verbs are correctly set + +/obj/vehicle/train/engine/on_update_icon() + . = ..() + var/image/I = image(icon, "cargo_engine_overlay") I.plane = plane I.layer = layer - overlays += I - turn_off() //so engine verbs are correctly set + set_overlays(I) -/obj/vehicle/train/cargo/engine/Move(var/turf/destination) +/obj/vehicle/train/engine/Move(var/turf/destination) if(on && cell.charge < (charge_use * CELLRATE)) turn_off() update_stats() @@ -67,46 +60,23 @@ return ..() -/obj/vehicle/train/cargo/trolley/attackby(obj/item/used_item, mob/user) - if(open && IS_WIRECUTTER(used_item)) - passenger_allowed = !passenger_allowed - user.visible_message("[user] [passenger_allowed ? "cuts" : "mends"] a cable in [src].","You [passenger_allowed ? "cut" : "mend"] the load limiter cable.") - return TRUE - return ..() - -/obj/vehicle/train/cargo/engine/attackby(obj/item/used_item, mob/user) - if(istype(used_item, /obj/item/key/cargo_train)) +/obj/vehicle/train/engine/attackby(obj/item/used_item, mob/user) + if(istype(used_item, key_type)) if(!key && user.try_unequip(used_item, src)) key = used_item - verbs += /obj/vehicle/train/cargo/engine/verb/remove_key + verbs |= /obj/vehicle/train/engine/verb/remove_key return TRUE return ..() -//cargo trains are open topped, so there is a chance the projectile will hit the mob ridding the train instead -/obj/vehicle/train/cargo/bullet_act(var/obj/item/projectile/Proj) - if(buckled_mob && prob(70)) - buckled_mob.bullet_act(Proj) - return - ..() - -/obj/vehicle/train/cargo/on_update_icon() - if(open) - icon_state = initial(icon_state) + "_open" - else - icon_state = initial(icon_state) - -/obj/vehicle/train/cargo/trolley/insert_cell(var/obj/item/cell/cell, var/mob/living/human/H) - return - -/obj/vehicle/train/cargo/engine/insert_cell(var/obj/item/cell/cell, var/mob/living/human/H) +/obj/vehicle/train/engine/insert_cell(var/obj/item/cell/cell, var/mob/living/human/H) ..() update_stats() -/obj/vehicle/train/cargo/engine/remove_cell(var/mob/living/human/H) +/obj/vehicle/train/engine/remove_cell(var/mob/living/human/H) ..() update_stats() -/obj/vehicle/train/cargo/engine/Bump(atom/Obstacle) +/obj/vehicle/train/engine/Bump(atom/Obstacle) var/obj/machinery/door/D = Obstacle var/mob/living/human/H = load if(istype(D) && istype(H)) @@ -114,52 +84,47 @@ ..() -/obj/vehicle/train/cargo/trolley/Bump(atom/Obstacle) - if(!lead) - return //so people can't knock others over by pushing a trolley around - ..() - //------------------------------------------- // Train procs //------------------------------------------- -/obj/vehicle/train/cargo/engine/turn_on() +/obj/vehicle/train/engine/turn_on() if(!key) return + if(!cell) + return + ..() + update_stats() + if(on) + verbs |= /obj/vehicle/train/engine/verb/stop_engine + verbs -= /obj/vehicle/train/engine/verb/start_engine else - ..() - update_stats() - - verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine - verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine - - if(on) - verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine - else - verbs += /obj/vehicle/train/cargo/engine/verb/start_engine + verbs |= /obj/vehicle/train/engine/verb/start_engine + verbs -= /obj/vehicle/train/engine/verb/stop_engine -/obj/vehicle/train/cargo/engine/turn_off() +/obj/vehicle/train/engine/turn_off() ..() + if(!on) + verbs |= /obj/vehicle/train/engine/verb/start_engine + verbs -= /obj/vehicle/train/engine/verb/stop_engine + else + verbs |= /obj/vehicle/train/engine/verb/stop_engine + verbs -= /obj/vehicle/train/engine/verb/start_engine - verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine - verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine - if(!on) - verbs += /obj/vehicle/train/cargo/engine/verb/start_engine +/obj/vehicle/train/engine/on_update_icon() + if(open) + icon_state = initial(icon_state) + "_open" else - verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine + icon_state = initial(icon_state) -/obj/vehicle/train/cargo/crossed_mob(var/mob/living/victim) +/obj/vehicle/train/engine/crossed_mob(var/mob/living/victim) victim.apply_effects(5, 5) for(var/i = 1 to rand(1,5)) var/obj/item/organ/external/E = pick(victim.get_external_organs()) if(E) victim.apply_damage(rand(5,10), BRUTE, E.organ_tag) -/obj/vehicle/train/cargo/trolley/crossed_mob(var/mob/living/victim) - ..() - attack_log += text("\[[time_stamp()]\] ran over [victim.name] ([victim.ckey])") - -/obj/vehicle/train/cargo/engine/crossed_mob(var/mob/living/victim) +/obj/vehicle/train/engine/crossed_mob(var/mob/living/victim) ..() if(is_train_head() && ishuman(load)) var/mob/living/human/D = load @@ -170,161 +135,96 @@ else attack_log += text("\[[time_stamp()]\] ran over [victim.name] ([victim.ckey])") - //------------------------------------------- // Interaction procs //------------------------------------------- -/obj/vehicle/train/cargo/engine/relaymove(mob/user, direction) +/obj/vehicle/train/engine/relaymove(mob/user, direction) if(user != load || user.incapacitated()) - return 0 - + return FALSE if(is_train_head()) if(direction == global.reverse_dir[dir] && tow) - return 0 + return FALSE if(Move(get_step(src, direction))) - return 1 - return 0 - else - return ..() + return TRUE + return FALSE + return ..() -/obj/vehicle/train/cargo/engine/get_examine_strings(mob/user, distance, infix, suffix) +/obj/vehicle/train/engine/get_examine_strings(mob/user, distance, infix, suffix) . = ..() if(distance <= 1) . += "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition." . += "The charge meter reads [cell? round(cell.percent(), 0.01) : 0]%" -/obj/vehicle/train/cargo/engine/verb/start_engine() +/obj/vehicle/train/engine/verb/start_engine() set name = "Start engine" - set category = "Object" + set category = "Vehicle" set src in view(0) if(!ishuman(usr)) return if(on) - to_chat(usr, "The engine is already running.") + to_chat(usr, SPAN_WARNING("The engine is already running.")) return turn_on() if (on) - to_chat(usr, "You start [src]'s engine.") + to_chat(usr, SPAN_NOTICE("You start \the [src]'s engine.")) else - if(cell.charge < charge_use) - to_chat(usr, "[src] is out of power.") + if(!cell) + to_chat(usr, SPAN_NOTICE("\The [src] doesn't appear to have a power cell!")) + else if(cell.charge < charge_use) + to_chat(usr, SPAN_NOTICE("\The [src] is out of power.")) else - to_chat(usr, "[src]'s engine won't start.") + to_chat(usr, SPAN_NOTICE("\The [src]'s engine won't start.")) -/obj/vehicle/train/cargo/engine/verb/stop_engine() +/obj/vehicle/train/engine/verb/stop_engine() set name = "Stop engine" - set category = "Object" + set category = "Vehicle" set src in view(0) if(!ishuman(usr)) return if(!on) - to_chat(usr, "The engine is already stopped.") + to_chat(usr, SPAN_WARNING("The engine is already stopped.")) return turn_off() if (!on) - to_chat(usr, "You stop [src]'s engine.") + to_chat(usr, SPAN_NOTICE("You stop [src]'s engine.")) -/obj/vehicle/train/cargo/engine/verb/remove_key() +/obj/vehicle/train/engine/verb/remove_key() set name = "Remove key" - set category = "Object" + set category = "Vehicle" set src in view(0) - if(!ishuman(usr)) - return - - if(!key || (load && load != usr)) + if(!isliving(usr) || !key || (load && load != usr)) return if(on) turn_off() + var/mob/living/user = usr + key.dropInto(get_turf(user)) usr.put_in_hands(key) key = null + verbs -= /obj/vehicle/train/engine/verb/remove_key - verbs -= /obj/vehicle/train/cargo/engine/verb/remove_key - -//------------------------------------------- -// Loading/unloading procs -//------------------------------------------- -/obj/vehicle/train/cargo/trolley/load(var/atom/movable/loading) - if(ismob(loading) && !passenger_allowed) - return 0 - if(!istype(loading,/obj/machinery) && !istype(loading,/obj/structure/closet) && !istype(loading,/obj/structure/largecrate) && !istype(loading,/obj/structure/reagent_dispensers) && !istype(loading,/obj/structure/ore_box) && !ishuman(loading)) - return 0 - - //if there are any items you don't want to be able to interact with, add them to this check - // ~no more shielded, emitter armed death trains - if(istype(loading, /obj/machinery)) - load_object(loading) - else - ..() - - if(load) - return 1 - -/obj/vehicle/train/cargo/engine/load(var/atom/movable/loading) - if(!ishuman(loading)) - return 0 - - return ..() - -//Load the object "inside" the trolley and add an overlay of it. -//This prevents the object from being interacted with until it has -// been unloaded. A dummy object is loaded instead so the loading -// code knows to handle it correctly. -/obj/vehicle/train/cargo/trolley/proc/load_object(var/atom/movable/loading) - if(!isturf(loading.loc)) //To prevent loading things from someone's inventory, which wouldn't get handled properly. - return 0 - if(load || loading.anchored) - return 0 - - var/datum/vehicle_dummy_load/dummy_load = new() - load = dummy_load - - if(!load) - return - dummy_load.actual_load = loading - loading.forceMove(src) - - if(load_item_visible) - loading.pixel_x += load_offset_x - loading.pixel_y += load_offset_y - loading.plane = plane - loading.layer = VEHICLE_LOAD_LAYER - - overlays += loading - - //we can set these back now since we have already cloned the icon into the overlay - loading.pixel_x = initial(loading.pixel_x) - loading.pixel_y = initial(loading.pixel_y) - loading.reset_plane_and_layer() - -/obj/vehicle/train/cargo/trolley/unload(var/mob/user, var/direction) - if(istype(load, /datum/vehicle_dummy_load)) - var/datum/vehicle_dummy_load/dummy_load = load - load = dummy_load.actual_load - dummy_load.actual_load = null - qdel(dummy_load) - overlays.Cut() - ..() +/obj/vehicle/train/engine/load_onto_vehicle(var/atom/movable/loading, var/mob/user) + return istype(loading, /mob/living/human) && ..() //------------------------------------------- // Latching/unlatching procs //------------------------------------------- -/obj/vehicle/train/cargo/engine/latch(obj/vehicle/train/T, mob/user) +/obj/vehicle/train/engine/latch(obj/vehicle/train/T, mob/user) if(!istype(T) || !Adjacent(T)) return 0 //if we are attaching a trolley to an engine we don't care what direction // it is in and it should probably be attached with the engine in the lead - if(istype(T, /obj/vehicle/train/cargo/trolley)) + if(istype(T, /obj/vehicle/train/trolley)) T.attach_to(src, user) else var/T_dir = get_dir(src, T) //figure out where T is wrt src @@ -345,24 +245,40 @@ // more engines increases this limit by car_limit per // engine. //------------------------------------------------------- -/obj/vehicle/train/cargo/engine/update_car(var/train_length, var/active_engines) - src.train_length = train_length - src.active_engines = active_engines +/obj/vehicle/train/engine/update_vehicle_move_delay(atom/prev_loc) + ..() + if(is_train_head() && on) + move_delay = max(move_delay, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you can't overspeed trains + move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines) - //Update move delay - if(!is_train_head() || !on) - move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind - else - move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) // limits base overweight so you cant overspeed trains - move_delay *= (1 / max(1, active_engines)) * 2 // overweight penalty (scaled by the number of engines) - move_delay += get_config_value(/decl/config/num/movement_run) // base reference speed - move_delay *= 1.1 // makes cargo trains 10% slower than running when not overweight +/obj/vehicle/train/engine/get_alt_interactions(mob/user) + . = ..() + LAZYADD(., /decl/interaction_handler/train/toggle_ignition) + if(key) + LAZYADD(., /decl/interaction_handler/train/remove_key) -/obj/vehicle/train/cargo/trolley/update_car(var/train_length, var/active_engines) - src.train_length = train_length - src.active_engines = active_engines +/decl/interaction_handler/train + abstract_type = /decl/interaction_handler/train + expected_target_type = /obj/vehicle/train/engine - if(!lead && !tow) - anchored = FALSE +/decl/interaction_handler/train/toggle_ignition + name = "Toggle Ignition" + +/decl/interaction_handler/train/toggle_ignition/invoked(atom/target, mob/user, obj/item/prop) + var/obj/vehicle/train/engine/train = target + if(train.on) + train.stop_engine() else - anchored = TRUE + train.start_engine() + +/decl/interaction_handler/train/remove_key + name = "Remove Key" + +/decl/interaction_handler/train/remove_key/is_possible(atom/target, mob/user, obj/item/prop) + if((. = ..())) + var/obj/vehicle/train/engine/train = target + return train.key + +/decl/interaction_handler/train/remove_key/invoked(atom/target, mob/user, obj/item/prop) + var/obj/vehicle/train/engine/train = target + train.remove_key() diff --git a/code/modules/vehicles/cargo_trolley.dm b/code/modules/vehicles/cargo_trolley.dm new file mode 100644 index 00000000000..f41875d4cd9 --- /dev/null +++ b/code/modules/vehicles/cargo_trolley.dm @@ -0,0 +1,103 @@ +/obj/vehicle/train/trolley + name = "cargo train trolley" + desc = "A large, flat platform made for putting things on." + icon = 'icons/obj/vehicles.dmi' + icon_state = "cargo_trailer" + anchored = FALSE + passenger_allowed = 0 + locked = 0 + buckle_pixel_shift = list("x" = 0, "y" = 0, "z" = 8) + + load_item_visible = 1 + load_offset_x = 0 + load_offset_y = 4 + + var/static/list/can_load_types = list( + /obj/machinery, + /obj/structure/closet, + /obj/structure/largecrate, + /obj/structure/reagent_dispensers, + /obj/structure/ore_box, + /mob/living/human + ) + +/obj/vehicle/train/trolley/insert_cell(var/obj/item/cell/cell, var/mob/living/human/H) + return + +//------------------------------------------- +// Loading/unloading procs +//------------------------------------------- +/obj/vehicle/train/trolley/load_onto_vehicle(var/atom/movable/loading, var/mob/user) + if(ismob(loading) && !passenger_allowed) + return 0 + if(!is_type_in_list(loading, can_load_types)) + return 0 + //if there are any items you don't want to be able to interact with, add them to this check + // ~no more shielded, emitter armed death trains + if(istype(loading, /obj/machinery)) + load_object(loading) + else + ..(loading, user) + return !!load + +//Load the object "inside" the trolley and add an overlay of it. +//This prevents the object from being interacted with until it has +// been unloaded. A dummy object is loaded instead so the loading +// code knows to handle it correctly. +/obj/vehicle/train/trolley/proc/load_object(var/atom/movable/loading) + //To prevent loading things from someone's inventory, which wouldn't get handled properly. + if(!isturf(loading.loc) || load || loading.anchored) + return 0 + var/datum/vehicle_dummy_load/dummy_load = new + dummy_load.actual_load = loading + load = dummy_load + loading.forceMove(src) + update_icon() + +/obj/vehicle/train/trolley/unload_from_vehicle(var/mob/user, var/direction) + if(istype(load, /datum/vehicle_dummy_load)) + var/datum/vehicle_dummy_load/dummy_load = load + load = dummy_load.actual_load + dummy_load.actual_load = null + qdel(dummy_load) + update_icon() + ..() + +/obj/vehicle/train/trolley/on_update_icon() + cut_overlays() + var/datum/vehicle_dummy_load/dummy_load = load + if(istype(dummy_load) && dummy_load.actual_load && load_item_visible) + var/atom/movable/loading = dummy_load.actual_load + loading.pixel_x += load_offset_x + loading.pixel_y += load_offset_y + loading.plane = plane + loading.layer = VEHICLE_LOAD_LAYER + add_overlay(loading) + compile_overlays() // We want to reset the pixel values on our load after this. + //we can set these back now since we have already cloned the icon into the overlay + loading.pixel_x = initial(loading.pixel_x) + loading.pixel_y = initial(loading.pixel_y) + loading.layer = initial(loading.layer) + +/obj/vehicle/train/trolley/update_car(var/train_length, var/active_engines) + ..() + anchored = lead || tow + +/obj/vehicle/train/trolley/Bump(atom/Obstacle) + if(!lead) + return //so people can't knock others over by pushing a trolley around + ..() + +/obj/vehicle/train/trolley/attackby(obj/item/used_item, mob/user) + if(open && IS_WIRECUTTER(used_item)) + passenger_allowed = !passenger_allowed + user.visible_message( + SPAN_NOTICE("\The [user] [passenger_allowed ? "cuts" : "mends"] a cable in [src]."), + SPAN_NOTICE("You [passenger_allowed ? "cut" : "mend"] the load limiter cable.") + ) + return TRUE + return ..() + +/obj/vehicle/train/trolley/crossed_mob(var/mob/living/victim) + ..() + attack_log += text("\[[time_stamp()]\] ran over [victim.name] ([victim.ckey])") diff --git a/code/modules/vehicles/quad_bike.dm b/code/modules/vehicles/quad_bike.dm new file mode 100644 index 00000000000..3d01876bc16 --- /dev/null +++ b/code/modules/vehicles/quad_bike.dm @@ -0,0 +1,198 @@ +/obj/vehicle/train/engine/quadbike //It's a train engine, so it can tow trailers. + name = "electric all terrain vehicle" + desc = "A ridable electric ATV designed for all terrain. Except space." + icon = 'icons/obj/vehicles_64x64.dmi' + icon_state = "quad" + on = 0 + powered = 1 + locked = 0 + load_item_visible = 1 + load_offset_x = 0 + buckle_pixel_shift = list("x" = 0, "y" = 0, "z" = 5) + pixel_x = -16 + base_speed = 0.45 + car_limit = 1 //It gets a trailer. That's about it. + active_engines = 1 + key_type = /obj/item/key/quadbike + paint_color = "#ffffff" + layer = OBJ_LAYER + vehicle_transit_type = VEHICLE_QUADBIKE + + var/frame_state = "quad" //Custom-item proofing! + var/paint_base = 'icons/obj/vehicles_64x64.dmi' + var/custom_frame = FALSE + var/datum/composite_sound/vehicle_engine/soundloop + +/obj/vehicle/train/engine/quadbike/Initialize() + cell = new /obj/item/cell/high(src) + key = new key_type(src) + soundloop = new(list(src), FALSE) + . = ..() + turn_off() + update_icon() + +/obj/vehicle/train/engine/quadbike/built/Initialize() + key = new key_type(src) + . = ..() + turn_off() + +/obj/vehicle/train/engine/quadbike/random/Initialize() + paint_color = rgb(rand(1,255),rand(1,255),rand(1,255)) + . = ..() + +/obj/vehicle/train/engine/quadbike/Destroy() + QDEL_NULL(soundloop) + return ..() + +/obj/item/key/quadbike + name = "key" + desc = "A keyring with a small steel key, and a blue fob reading \"ZOOM!\"." + icon = 'icons/obj/vehicles.dmi' + icon_state = "quad_keys" + w_class = ITEM_SIZE_TINY + +/obj/vehicle/train/engine/quadbike/forceMove(turf/destination) + var/atom/old_loc = loc + if((. = ..())) + update_vehicle_move_delay(old_loc) + handle_vehicle_icon() + +/obj/vehicle/train/engine/quadbike/Move(turf/destination) + var/atom/old_loc = loc + if((. = ..())) + update_vehicle_move_delay(old_loc) + handle_vehicle_icon() + +/obj/vehicle/train/engine/quadbike/update_vehicle_move_delay(atom/prev_loc) + ..() + update_car(train_length, active_engines) + +/obj/vehicle/train/engine/quadbike/proc/handle_vehicle_icon() + switch(dir) //Due to being a Big Boy sprite, it has to have special pixel shifting to look 'normal' when being driven. + if(1) + pixel_y = -6 + if(2) + pixel_y = -6 + if(4) + pixel_y = 0 + if(8) + pixel_y = 0 + +/obj/vehicle/train/engine/quadbike/attackby(obj/item/used_item, mob/user) + if(istype(used_item, /obj/item/multitool) && open) + var/new_paint = input("Please select a paint color.", "Trailer Color", paint_color) as color|null + if(new_paint && !QDELETED(src) && !QDELETED(used_item) && !QDELETED(user) && !user.incapacitated() && user.get_active_held_item() == used_item) + paint_color = new_paint + update_icon() + return TRUE + return ..() + +/obj/vehicle/train/engine/quadbike/on_update_icon() + ..() + cut_overlays() + + if(custom_frame) + var/image/Bodypaint = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_a") + Bodypaint.layer = layer + Bodypaint.color = paint_color + add_overlay(Bodypaint) + + var/image/Overmob = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_overlay") //over mobs + var/image/Overmob_color = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_overlay_a") //over the over mobs, gives the color. + Overmob.layer = layer + 0.2 + Overmob_color.layer = layer + 0.2 + Overmob_color.color = paint_color + add_overlay(Overmob) + add_overlay(Overmob_color) + return + + var/image/Bodypaint = new(icon = paint_base, icon_state = "[frame_state]_a", layer = src.layer) + Bodypaint.color = paint_color + add_overlay(Bodypaint) + + var/image/Overmob = new(icon = paint_base, icon_state = "[frame_state]_overlay", layer = src.layer + 0.2) //over mobs + var/image/Overmob_color = new(icon = paint_base, icon_state = "[frame_state]_overlay_a", layer = src.layer + 0.2) //over the over mobs, gives the color. + Overmob.layer = ABOVE_HUMAN_LAYER + Overmob_color.layer = ABOVE_HUMAN_LAYER + Overmob_color.color = paint_color + + add_overlay(Overmob) + add_overlay(Overmob_color) + +/obj/vehicle/train/engine/quadbike/Bump(atom/Obstacle) + if(!istype(Obstacle, /atom/movable)) + return + var/atom/movable/A = Obstacle + + if(!A.anchored) + var/turf/T = get_step(A, dir) + if(isturf(T)) + A.Move(T) //bump things away when hit + + if(istype(A, /mob/living)) + var/mob/living/M = A + visible_message(SPAN_DANGER("\The [src] knocks over \the [M]!")) + M.apply_effects(2, 2) // Knock people down for a short moment + M.apply_damages(8 / move_delay) // Smaller amount of damage than a tug, since this will always be possible because Quads don't have safeties. + var/list/throw_dirs = all_throw_dirs.Copy() + if(!emagged) // By the power of Bumpers TM, it won't throw them ahead of the quad's path unless it's emagged or the person turns. + take_damage(round(M.mob_size / 2)) + throw_dirs -= dir + throw_dirs -= get_dir(M, src) //Don't throw it AT the quad either. + else + take_damage(round(M.mob_size / 4)) // Less damage if they actually put the point in to emag it. + var/turf/T2 = get_step(A, pick(throw_dirs)) + M.throw_at(T2, 1, 1, src) + if(isliving(load)) + var/mob/living/D = load + to_chat(D, SPAN_DANGER("You hit \the [M]!")) + admin_attack_log(D, M, "Ran over with [src.name]") + +/obj/vehicle/train/engine/quadbike/crossed_mob(mob/living/victim) + . = ..() + var/list/throw_dirs = all_throw_dirs.Copy() + if(!emagged) + throw_dirs -= dir + if(tow) + throw_dirs -= get_dir(victim, tow) //Don't throw it at the trailer either. + var/turf/T = get_step(victim, pick(throw_dirs)) + victim.throw_at(T, 1, 1, src) + +/obj/vehicle/train/engine/quadbike/turn_on() + ..() + if(on) + visible_message(SPAN_NOTICE("\The [src] rumbles to life."), "You hear something rumble deeply.") + soundloop.start() + +/obj/vehicle/train/engine/quadbike/turn_off() + if(on) + visible_message(SPAN_NOTICE("\The [src] putters before turning off."), "You hear something putter slowly.") + soundloop.stop() + ..() + +/obj/vehicle/train/engine/quadbike/snowmobile + name = "snowmobile" + desc = "An electric snowmobile for traversing snow and ice with ease! Other terrain, not so much." + icon = 'icons/obj/vehicles.dmi' + icon_state = "snowmobile" + load_item_visible = 1 + base_speed = 0.6 + car_limit = 0 + key_type = /obj/item/key/snowmobile + frame_state = "snowmobile" + paint_base = 'icons/obj/vehicles.dmi' + pixel_x = 0 + water_delay = 6 + +/obj/item/key/snowmobile + name = "key" + desc = "A keyring with an ice-blue fob reading \"CHILL\"." + icon = 'icons/obj/vehicles.dmi' + icon_state = "sno_keys" + +/obj/vehicle/train/engine/quadbike/snowmobile/random/Initialize() + paint_color = rgb(rand(1,255),rand(1,255),rand(1,255)) + . = ..() + +/obj/vehicle/train/engine/quadbike/snowmobile/handle_vehicle_icon() + return diff --git a/code/modules/vehicles/quad_trailer.dm b/code/modules/vehicles/quad_trailer.dm new file mode 100644 index 00000000000..a730ab54b65 --- /dev/null +++ b/code/modules/vehicles/quad_trailer.dm @@ -0,0 +1,108 @@ +/* + * Trailer bits and bobs. + */ +/obj/vehicle/train/trolley/trailer + name = "all terrain trailer" + icon = 'icons/obj/vehicles_64x64.dmi' + icon_state = "quadtrailer" + anchored = FALSE + passenger_allowed = 1 + buckle_lying = 1 + locked = 0 + load_item_visible = 1 + load_offset_x = 0 + load_offset_y = 13 + buckle_pixel_shift = list("x" = 0, "y" = 0, "z" = 16) + pixel_x = -16 + paint_color = "#ffffff" + var/mob_offset_y = 16 + +/obj/vehicle/train/trolley/trailer/random/Initialize() + paint_color = rgb(rand(1,255),rand(1,255),rand(1,255)) + . = ..() + +/obj/vehicle/train/trolley/trailer/proc/update_load() + if(load) + var/y_offset = load_offset_y + if(istype(load, /mob/living)) + y_offset = mob_offset_y + load.pixel_x = (initial(load.pixel_x) + 16 + load_offset_x + pixel_x) //Base location for the sprite, plus 16 to center it on the 'base' sprite of the trailer, plus the x shift of the trailer, then shift it by the same pixel_x as the trailer to track it. + load.pixel_y = (initial(load.pixel_y) + y_offset + pixel_y) //Same as the above. + return 1 + return 0 +/obj/vehicle/train/trolley/trailer/Initialize() + . = ..() + update_icon() + +/obj/vehicle/train/trolley/trailer/Move() + var/atom/old_loc = loc + if((. = ..())) + update_trolley_offset(old_loc) + +/obj/vehicle/train/trolley/trailer/forceMove() + var/atom/old_loc = loc + if((. = ..())) + update_trolley_offset(old_loc) + +/obj/vehicle/train/trolley/trailer/proc/update_trolley_offset(var/atom/old_loc) + if(lead) + switch(dir) //Due to being a Big Boy sprite, it has to have special pixel shifting to look 'normal'. + if(1) + default_pixel_y = -10 + default_pixel_x = -16 + if(2) + default_pixel_y = 0 + default_pixel_x = -16 + if(4) + default_pixel_y = 0 + default_pixel_x = -25 + if(8) + default_pixel_y = 0 + default_pixel_x = -5 + else + default_pixel_x = initial(default_pixel_x) + default_pixel_y = initial(default_pixel_y) + reset_offsets(0) + update_load() + +/obj/vehicle/train/trolley/trailer/Bump(atom/Obstacle) + if(!istype(Obstacle, /atom/movable)) + return + + var/atom/movable/A = Obstacle + if(!A.anchored) + var/turf/T = get_step(A, dir) + if(isturf(T)) + A.Move(T) //bump things away when hit + + if(istype(A, /mob/living)) + var/mob/living/M = A + visible_message(SPAN_DANGER("\The [src] knocks over \the [M]!")) + M.apply_effects(1, 1) + M.apply_damages(8 / move_delay) + if(load) + M.apply_damages(4/move_delay) + var/list/throw_dirs = all_throw_dirs.Copy() + if(!emagged) + throw_dirs -= dir + var/turf/T2 = get_step(A, pick(throw_dirs)) + M.throw_at(T2, 1, 1, src) + if(isliving(load)) + var/mob/living/D = load + to_chat(D, SPAN_DANGER("You hit \the [M]!")) + admin_attack_log(D, M, "Ran over with \the [src]") + +/obj/vehicle/train/trolley/trailer/on_update_icon() + ..() + var/image/Bodypaint = new(icon = icon, icon_state = "[initial(icon_state)]_a", layer = src.layer) + Bodypaint.color = paint_color + set_overlays(Bodypaint) + +/obj/vehicle/train/trolley/trailer/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/multitool) && open) + var/new_paint = input("Please select paint color.", "Paint Color", paint_color) as color|null + if(new_paint) + paint_color = new_paint + update_icon() + return + ..() diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm index 0cb43501e1e..59665c6b326 100644 --- a/code/modules/vehicles/train.dm +++ b/code/modules/vehicles/train.dm @@ -5,17 +5,18 @@ max_health = 100 fire_dam_coeff = 0.7 brute_dam_coeff = 0.5 + layer = ABOVE_HUMAN_LAYER var/passenger_allowed = 1 - var/active_engines = 0 var/train_length = 0 - var/obj/vehicle/train/lead var/obj/vehicle/train/tow + var/static/list/all_throw_dirs = list(NORTH, SOUTH, EAST, WEST, NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST) + /obj/vehicle/train/user_buckle_mob(mob/living/M, mob/user) - return load(M) + return load_onto_vehicle(M) //------------------------------------------- // Standard procs @@ -95,7 +96,7 @@ return 1 return 0 - unload(user, direction) + unload_from_vehicle(user, direction) to_chat(user, "You climb down from [src].") return 1 @@ -110,7 +111,7 @@ /obj/vehicle/train/receive_mouse_drop(atom/dropping, mob/user, params) . = ..() if(!. && istype(dropping, /atom/movable)) - if(!load(dropping)) + if(!load_onto_vehicle(dropping)) to_chat(user, SPAN_WARNING("You were unable to load \the [dropping] onto \the [src].")) return TRUE @@ -121,9 +122,9 @@ if(user != load && (user in src)) user.forceMove(loc) else if(load) - unload(user) + unload_from_vehicle(user) else if(!load && !user.buckled) - load(user) + load_onto_vehicle(user) return TRUE /obj/vehicle/train/verb/unlatch_v() @@ -235,5 +236,7 @@ T.update_car(train_length, active_engines) T = T.lead -/obj/vehicle/train/proc/update_car(var/train_length, var/active_engines) - return +/obj/vehicle/train/proc/update_car(var/_train_length, var/_active_engines) + SHOULD_CALL_PARENT(TRUE) + train_length = _train_length + active_engines = _active_engines diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index 111eb94818e..6086aa1fab2 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -6,7 +6,7 @@ /obj/vehicle name = "vehicle" icon = 'icons/obj/vehicles.dmi' - layer = ABOVE_HUMAN_LAYER + layer = OBJ_LAYER density = TRUE anchored = TRUE animate_movement=1 @@ -17,6 +17,11 @@ buckle_movable = 1 buckle_lying = 0 + var/const/VEHICLE_GENERIC = 1 + var/const/VEHICLE_QUADBIKE = 2 + var/const/VEHICLE_SNOWMOBILE = 3 + + var/vehicle_transit_type = VEHICLE_GENERIC var/attack_log = null var/on = 0 var/fire_dam_coeff = 1.0 @@ -26,7 +31,13 @@ var/stat = 0 var/emagged = 0 var/powered = 0 //set if vehicle is powered and should use fuel when moving - var/move_delay = 1 //set this to limit the speed of the vehicle + + /// How long a single move takes with this vehicle. + var/move_delay = 1 + /// The base delay of a move with this vehicle, assuming no terrain modifiers. If null, uses default running + var/base_speed + /// Speed when a location is flooded. + var/water_delay = 4 var/obj/item/cell/cell var/charge_use = 200 // W @@ -35,10 +46,31 @@ var/load_item_visible = 1 //set if the loaded item should be overlayed on the vehicle sprite var/load_offset_x = 0 //pixel_x offset for item overlay var/load_offset_y = 0 //pixel_y offset for item overlay - //------------------------------------------- // Standard procs //------------------------------------------- +/obj/vehicle/Initialize(mapload) + update_vehicle_move_delay(null) + base_speed ||= get_config_value(/decl/config/num/movement_run) + . = ..() + +/obj/vehicle/proc/update_vehicle_move_delay(atom/prev_loc) + + var/turf/floor/prev_turf = prev_loc + var/turf/floor/this_turf = loc + if(istype(prev_turf) && istype(this_turf) && this_turf.get_topmost_flooring() == prev_turf.get_topmost_flooring() && this_turf.check_fluid_depth(FLUID_SHALLOW) == prev_turf.check_fluid_depth(FLUID_SHALLOW)) + return // Same speed if terrain type doesn't change + + var/terrain_mod + if(loc?.check_fluid_depth(FLUID_SHALLOW)) + terrain_mod = water_delay + else if(istype(this_turf)) + terrain_mod = this_turf.get_vehicle_transit_delay(src) + + if(isnull(terrain_mod)) + move_delay = base_speed + else + move_delay = base_speed * terrain_mod /obj/vehicle/Move() if(world.time > l_move_time + move_delay) @@ -162,7 +194,7 @@ /obj/vehicle/unbuckle_mob(mob/user) . = ..(user) if(load == .) - unload(.) + unload_from_vehicle(.) //------------------------------------------- // Vehicle procs @@ -207,7 +239,7 @@ var/mob/living/M = load M.apply_effects(5, 5) - unload() + unload_from_vehicle() new /obj/effect/gibspawner/robot(my_turf) new /obj/effect/decal/cleanable/blood/oil(src.loc) @@ -261,7 +293,7 @@ // the vehicle load() definition before // calling this parent proc. //------------------------------------------- -/obj/vehicle/proc/load(var/atom/movable/loading) +/obj/vehicle/proc/load_onto_vehicle(var/atom/movable/loading) //This loads objects onto the vehicle so they can still be interacted with. //Define allowed items for loading in specific vehicle definitions. if(!isturf(loading.loc)) //To prevent loading things from someone's inventory, which wouldn't get handled properly. @@ -293,7 +325,7 @@ return 1 -/obj/vehicle/proc/unload(var/mob/user, var/direction) +/obj/vehicle/proc/unload_from_vehicle(var/mob/user, var/direction) if(!load) return diff --git a/icons/obj/custom_items_vehicle.dmi b/icons/obj/custom_items_vehicle.dmi new file mode 100644 index 0000000000000000000000000000000000000000..a6afb68bab511eff886dc4cefd510a46b62b596b GIT binary patch literal 218 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF$egBxE?rgAkBMU3XscK666=m z;PC858jzD!6%tY6l3JWxlvz-cnV-kNP%$Sste~j$`e1P4th#xHghs-Nqcg*% z%$UuUsI9%@*UpBstPD|Cq$YD3UVZ_zmEY6FF+^ixa)Jcw;)WUq1||mv#)MGQET9yF Mr>mdKI;Vst0PaOgjQ{`u literal 0 HcmV?d00001 diff --git a/icons/obj/vehicles_64x64.dmi b/icons/obj/vehicles_64x64.dmi new file mode 100644 index 0000000000000000000000000000000000000000..50cc6457594ae921f7c60c804cfae12eb109b3a4 GIT binary patch literal 19406 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 literal 0 HcmV?d00001 diff --git a/maps/away/errant_pisces/errant_pisces.dmm b/maps/away/errant_pisces/errant_pisces.dmm index 77c6de05aef..6241f27598e 100644 --- a/maps/away/errant_pisces/errant_pisces.dmm +++ b/maps/away/errant_pisces/errant_pisces.dmm @@ -451,7 +451,7 @@ /obj/effect/floor_decal/industrial/warning{ dir = 4 }, -/obj/vehicle/train/cargo/trolley, +/obj/vehicle/train/trolley, /turf/floor/plating, /area/errant_pisces/enginering) "bp" = ( @@ -569,7 +569,7 @@ /turf/floor/plating, /area/errant_pisces/enginering) "bK" = ( -/obj/vehicle/train/cargo/trolley, +/obj/vehicle/train/trolley, /turf/floor/plating, /area/errant_pisces/enginering) "bL" = ( @@ -4380,11 +4380,11 @@ /turf/floor/tiled/white, /area/errant_pisces/science_wing) "lU" = ( -/obj/vehicle/train/cargo/engine, +/obj/vehicle/train/engine, /turf/floor/plating, /area/errant_pisces/general_storage) "lV" = ( -/obj/vehicle/train/cargo/trolley, +/obj/vehicle/train/trolley, /turf/floor/plating, /area/errant_pisces/general_storage) "lW" = ( diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm index c9e92ad6347..1c4098ff2ea 100644 --- a/maps/exodus/exodus-2.dmm +++ b/maps/exodus/exodus-2.dmm @@ -34922,7 +34922,7 @@ /turf/floor/tiled/steel_grid, /area/exodus/quartermaster/storage) "bwe" = ( -/obj/vehicle/train/cargo/trolley, +/obj/vehicle/train/trolley, /obj/effect/floor_decal/industrial/outline/yellow, /turf/floor/tiled/steel_grid, /area/exodus/quartermaster/storage) @@ -34933,7 +34933,7 @@ /turf/floor/tiled/steel_grid, /area/exodus/quartermaster/storage) "bwg" = ( -/obj/vehicle/train/cargo/engine, +/obj/vehicle/train/engine, /obj/effect/floor_decal/industrial/outline/yellow, /obj/structure/cable/green{ icon_state = "1-2" diff --git a/maps/ministation/ministation-0.dmm b/maps/ministation/ministation-0.dmm index ac11d915541..e932f12856f 100644 --- a/maps/ministation/ministation-0.dmm +++ b/maps/ministation/ministation-0.dmm @@ -3645,7 +3645,7 @@ /area/ministation/atmospherics) "pS" = ( /obj/effect/floor_decal/industrial/outline/yellow, -/obj/vehicle/train/cargo/trolley, +/obj/vehicle/train/trolley, /turf/floor/tiled, /area/ministation/cargo) "pT" = ( @@ -13140,7 +13140,7 @@ /area/ministation/engine) "Ws" = ( /obj/effect/floor_decal/industrial/outline/yellow, -/obj/vehicle/train/cargo/engine, +/obj/vehicle/train/engine, /turf/floor/tiled, /area/ministation/cargo) "Wt" = ( diff --git a/mods/content/government/away_sites/icarus/icarus-1.dmm b/mods/content/government/away_sites/icarus/icarus-1.dmm index 64d4c6491db..18c6c2ab63d 100644 --- a/mods/content/government/away_sites/icarus/icarus-1.dmm +++ b/mods/content/government/away_sites/icarus/icarus-1.dmm @@ -1801,7 +1801,7 @@ /turf/floor/plating, /area/icarus/vessel) "fS" = ( -/obj/vehicle/train/cargo/engine, +/obj/vehicle/train/engine, /turf/floor/plating, /area/icarus/vessel) "fT" = ( @@ -1926,7 +1926,7 @@ /turf/floor/plating, /area/icarus/vessel) "gp" = ( -/obj/vehicle/train/cargo/trolley, +/obj/vehicle/train/trolley, /turf/floor/plating, /area/icarus/vessel) "gq" = ( @@ -2545,7 +2545,7 @@ /obj/effect/decal/cleanable/dirt/visible, /obj/effect/decal/cleanable/dirt/visible, /obj/effect/decal/cleanable/dirt/visible, -/obj/vehicle/train/cargo/trolley, +/obj/vehicle/train/trolley, /turf/unsimulated/floor/sand, /area/icarus/open) "ii" = ( diff --git a/nebula.dme b/nebula.dme index 5cffd8b3216..52d262392e0 100644 --- a/nebula.dme +++ b/nebula.dme @@ -397,6 +397,7 @@ #include "code\datums\composite_sounds\fire_sounds.dm" #include "code\datums\composite_sounds\loom.dm" #include "code\datums\composite_sounds\machinery_sounds.dm" +#include "code\datums\composite_sounds\vehicle_engine.dm" #include "code\datums\config\_config.dm" #include "code\datums\config\_config_categories.dm" #include "code\datums\config\config_enum.dm" @@ -3904,7 +3905,10 @@ #include "code\modules\turbolift\turbolift_turfs.dm" #include "code\modules\vehicles\bike.dm" #include "code\modules\vehicles\cargo_train.dm" +#include "code\modules\vehicles\cargo_trolley.dm" #include "code\modules\vehicles\engine.dm" +#include "code\modules\vehicles\quad_bike.dm" +#include "code\modules\vehicles\quad_trailer.dm" #include "code\modules\vehicles\train.dm" #include "code\modules\vehicles\vehicle.dm" #include "code\modules\weather\_weather.dm" diff --git a/sound/machines/vehicle/engine_end.ogg b/sound/machines/vehicle/engine_end.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7f3c179ad802ed085ad74cf5cdfd7dd919822364 GIT binary patch literal 49838 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 literal 0 HcmV?d00001 diff --git a/sound/machines/vehicle/engine_start.ogg b/sound/machines/vehicle/engine_start.ogg new file mode 100644 index 0000000000000000000000000000000000000000..e4b5ac744b9dcca2e69a2303eaf37da8c918886b GIT binary patch literal 39943 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

" if(screen == 1) - dat += "Select an event to trigger:
" + var/list/options = get_event_options(user) + dat += "Select an event to trigger:
  • [options.Join("
  • ")]
" show_browser(user, dat, "window=keycard_auth;size=500x250") if(screen == 2) - dat += "Please swipe your card to authorize the following event: [event]" + var/decl/keycard_auth_event/real_event = global.decls_repository.get_decl_by_id(event) + dat += "Please swipe your card to authorize the following event: [real_event.get_link_text()]" dat += "

Back" show_browser(user, dat, "window=keycard_auth;size=500x250") return @@ -144,8 +136,10 @@ /obj/machinery/keycard_auth/proc/broadcast_check() if(confirmed) confirmed = 0 + var/decl/keycard_auth_event/real_event = global.decls_repository.get_decl_by_id(event) + var/cached_name = real_event.get_link_text() // because triggering the event can change the name trigger_event(event) - log_and_message_admins("triggered and [key_name(event_confirmed_by)] confirmed event [event]", event_triggered_by || usr) + log_and_message_admins("triggered and [key_name(event_confirmed_by)] confirmed event [cached_name]", event_triggered_by || usr) reset() /obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source, obj/item/card/id/ID) @@ -166,45 +160,11 @@ busy = 0 /obj/machinery/keycard_auth/proc/trigger_event() - switch(event) - if("Red alert") - var/decl/security_state/security_state = GET_DECL(global.using_map.security_state) - security_state.stored_security_level = security_state.current_security_level - security_state.set_security_level(security_state.high_security_level) - SSstatistics.add_field("alert_keycard_auth_red",1) - if("Revert alert") - var/decl/security_state/security_state = GET_DECL(global.using_map.security_state) - security_state.set_security_level(security_state.stored_security_level) - SSstatistics.add_field("alert_keycard_revert_red",1) - if("Grant Emergency Maintenance Access") - global.using_map.make_maint_all_access() - SSstatistics.add_field("alert_keycard_auth_maintGrant",1) - if("Revoke Emergency Maintenance Access") - global.using_map.revoke_maint_all_access() - SSstatistics.add_field("alert_keycard_auth_maintRevoke",1) - if("Emergency Response Team") - if(is_ert_blocked()) - visible_message(SPAN_WARNING("\The [src] blinks and displays a message: All emergency response teams are dispatched and can not be called at this time."), range=2) - return - - trigger_armed_response_team(1) - SSstatistics.add_field("alert_keycard_auth_ert",1) - if("Grant Nuclear Authorization Code") - var/obj/machinery/nuclearbomb/nuke = locate(/obj/machinery/nuclearbomb/station) in SSmachines.machinery - if(nuke) - visible_message(SPAN_WARNING("\The [src] blinks and displays a message: The nuclear authorization code is [nuke.r_code]"), range=2) - else - visible_message(SPAN_WARNING("\The [src] blinks and displays a message: No self-destruct terminal found."), range=2) - SSstatistics.add_field("alert_keycard_auth_nukecode",1) - -/obj/machinery/keycard_auth/proc/is_ert_blocked() - if(get_config_value(/decl/config/toggle/ert_admin_call_only)) - return TRUE - return SSticker.mode?.ert_disabled + var/decl/keycard_auth_event/the_event = decls_repository.get_decl_by_id(event) + if(the_event) + the_event.on_event(src) /obj/machinery/keycard_auth/update_directional_offset(force = FALSE) if(!force && (!length(directional_offset) || !is_wall_mounted())) //Check if the thing is actually mapped onto a table or something return - . = ..() - -var/global/maint_all_access = 0 \ No newline at end of file + . = ..() \ No newline at end of file diff --git a/code/modules/security_levels/keycard_authentication_events.dm b/code/modules/security_levels/keycard_authentication_events.dm new file mode 100644 index 00000000000..76b36018a0b --- /dev/null +++ b/code/modules/security_levels/keycard_authentication_events.dm @@ -0,0 +1,96 @@ +/decl/keycard_auth_event + abstract_type = /decl/keycard_auth_event + decl_flags = DECL_FLAG_MANDATORY_UID + var/name = "Abstract Keycard Authentication Event" + +/decl/keycard_auth_event/proc/get_link_text(obj/machinery/keycard_auth/auth, mob/user) + return name + +/decl/keycard_auth_event/proc/is_available(obj/machinery/keycard_auth/auth, mob/user) + return TRUE + +/decl/keycard_auth_event/proc/get_option(obj/machinery/keycard_auth/auth, mob/user) + SHOULD_NOT_OVERRIDE(TRUE) + var/fail_reason = get_failure_reason(user) + if(fail_reason) + return fail_reason + return "[get_link_text(auth, user)]" + +/decl/keycard_auth_event/proc/get_failure_reason(obj/machinery/keycard_auth/auth, mob/user) + return + +/decl/keycard_auth_event/proc/on_event(obj/machinery/keycard_auth/auth) + return + +/decl/keycard_auth_event/high_security + name = "Toggle High Security Level" + uid = "keycard_event_toggle_high_security" + +/decl/keycard_auth_event/high_security/get_failure_reason(obj/machinery/keycard_auth/auth, mob/user) + var/decl/security_state/security_state = GET_DECL(global.using_map.security_state) + if(security_state.current_security_level == security_state.severe_security_level) + return "Cannot modify the alert level at this time: [security_state.severe_security_level.name] engaged." + +/decl/keycard_auth_event/high_security/get_link_text(obj/machinery/keycard_auth/auth, mob/user) + var/decl/security_state/security_state = GET_DECL(global.using_map.security_state) + if(security_state.current_security_level == security_state.high_security_level) // toggle! + return "Disengage [security_state.high_security_level.name]" + else + return "Engage [security_state.high_security_level.name]" + +/decl/keycard_auth_event/high_security/on_event(obj/machinery/keycard_auth/auth, mob/user) + var/decl/security_state/security_state = GET_DECL(global.using_map.security_state) + if(security_state.current_security_level == security_state.high_security_level) + security_state.set_security_level(security_state.stored_security_level) + SSstatistics.add_field("alert_keycard_revert_red",1) + else + security_state.stored_security_level = security_state.current_security_level + security_state.set_security_level(security_state.high_security_level) + SSstatistics.add_field("alert_keycard_auth_red",1) + +/decl/keycard_auth_event/call_ert + name = "Emergency Response Team" + uid = "keycard_event_call_ert" + +/decl/keycard_auth_event/call_ert/is_available(obj/machinery/keycard_auth/auth, mob/user) + if(get_config_value(/decl/config/toggle/ert_admin_call_only)) + return FALSE + return TRUE + +/decl/keycard_auth_event/call_ert/on_event(obj/machinery/keycard_auth/auth) + if(!SSticker.mode || SSticker.mode.ert_disabled) // disabled by mode + auth.visible_message(SPAN_WARNING("\The [src] blinks and displays a message: All emergency response teams are dispatched and can not be called at this time."), range=2) + return + + trigger_armed_response_team(1) + SSstatistics.add_field("alert_keycard_auth_ert",1) + +/decl/keycard_auth_event/maintenance_access + name = "Toggle Emergency Maintenance Access" + uid = "keycard_event_maintenance_access" + +/decl/keycard_auth_event/maintenance_access/get_link_text(obj/machinery/keycard_auth/auth, mob/user) + if(global.using_map.maint_all_access) + return "Revoke Emergency Maintenance Access" + else + return "Grant Emergency Maintenance Access" + +/decl/keycard_auth_event/maintenance_access/on_event(obj/machinery/keycard_auth/auth) + if(global.using_map.maint_all_access) + global.using_map.revoke_maint_all_access() + SSstatistics.add_field("alert_keycard_auth_maintRevoke",1) + else + global.using_map.make_maint_all_access() + SSstatistics.add_field("alert_keycard_auth_maintGrant",1) + +/decl/keycard_auth_event/nuke_code + name = "Grant Nuclear Authorization Code" + uid = "keycard_event_nuke_code" + +/decl/keycard_auth_event/nuke_code/on_event(obj/machinery/keycard_auth/auth) + var/obj/machinery/nuclearbomb/nuke = locate(/obj/machinery/nuclearbomb/station) in SSmachines.machinery + if(nuke) + auth.visible_message(SPAN_WARNING("\The [src] blinks and displays a message: The nuclear authorization code is [nuke.r_code]"), range=2) + else + auth.visible_message(SPAN_WARNING("\The [src] blinks and displays a message: No self-destruct terminal found."), range=2) + SSstatistics.add_field("alert_keycard_auth_nukecode",1) \ No newline at end of file diff --git a/nebula.dme b/nebula.dme index 97f30cde7b2..6740b330292 100644 --- a/nebula.dme +++ b/nebula.dme @@ -3748,6 +3748,7 @@ #include "code\modules\security_levels\_security_level.dm" #include "code\modules\security_levels\alarm_appearance.dm" #include "code\modules\security_levels\keycard_authentication.dm" +#include "code\modules\security_levels\keycard_authentication_events.dm" #include "code\modules\security_levels\security_levels.dm" #include "code\modules\security_levels\security_state.dm" #include "code\modules\shield_generators\floor_diffuser.dm" From 886719904720748b6aaf8692602c0ba8d8db82b9 Mon Sep 17 00:00:00 2001 From: mistakenot4892 Date: Wed, 31 Dec 2025 11:22:48 +1100 Subject: [PATCH 018/149] Removes now-unneeded drake marking override. --- mods/~compatibility/patches/drakes/fantasy_drakes.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/mods/~compatibility/patches/drakes/fantasy_drakes.dm b/mods/~compatibility/patches/drakes/fantasy_drakes.dm index f2f20a7a00f..7c9279184ba 100644 --- a/mods/~compatibility/patches/drakes/fantasy_drakes.dm +++ b/mods/~compatibility/patches/drakes/fantasy_drakes.dm @@ -6,9 +6,6 @@ They are commonly found living in caves or burrows bordering grassland or forest, and while they prefer to hunt deer or rabbits, they will sometimes attack travellers if pickings are slim enough. \ While they are not domesticated, they can be habituated and trained as working animals if captured young enough." -/decl/sprite_accessory/marking/grafadreka - species_allowed = list("Meredrake") - /decl/language/grafadreka desc = "Hiss hiss, feed me rabbits." From b4f6be058b0ca5a5882fa1a42cfa8d527d66f1fe Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Tue, 30 Dec 2025 14:32:03 -0500 Subject: [PATCH 019/149] Add map migration --- tools/map_migrations/5320_power_debug.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tools/map_migrations/5320_power_debug.txt diff --git a/tools/map_migrations/5320_power_debug.txt b/tools/map_migrations/5320_power_debug.txt new file mode 100644 index 00000000000..b5a1d738e49 --- /dev/null +++ b/tools/map_migrations/5320_power_debug.txt @@ -0,0 +1,2 @@ +/obj/machinery/power/debug_items/@SUBTYPES : /obj/machinery/debug_items/@SUBTYPES{@OLD} +/obj/machinery/power/ascent_reactor/@SUBTYPES : /obj/machinery/ascent_reactor/@SUBTYPES{@OLD} \ No newline at end of file From 092d7c1ec11e914c4a2ebfcf9ede3454ca95c490 Mon Sep 17 00:00:00 2001 From: mistakenot4892 Date: Wed, 31 Dec 2025 11:39:15 +1100 Subject: [PATCH 020/149] Prevents tile removal sound on non-tile floor removal. --- code/game/turfs/flooring/_flooring.dm | 4 +++- code/game/turfs/flooring/flooring_reinforced.dm | 1 + code/game/turfs/flooring/flooring_tiled.dm | 3 +++ code/game/turfs/floors/subtypes/floor_reinforced.dm | 8 ++++---- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/code/game/turfs/flooring/_flooring.dm b/code/game/turfs/flooring/_flooring.dm index f5f8083873f..a93566d69e3 100644 --- a/code/game/turfs/flooring/_flooring.dm +++ b/code/game/turfs/flooring/_flooring.dm @@ -19,6 +19,7 @@ var/global/list/flooring_cache = list() var/color = COLOR_WHITE var/footstep_type = /decl/footsteps/plating var/growth_value = 0 + var/deconstruct_sound var/neighbour_type @@ -295,7 +296,8 @@ var/global/list/flooring_cache = list() return TRUE to_chat(user, SPAN_NOTICE("You remove the [get_surface_descriptor()] with \the [item].")) floor.remove_flooring(floor.get_topmost_flooring(), place_product = TRUE) - playsound(floor, 'sound/items/Deconstruct.ogg', 80, 1) + if(deconstruct_sound) + playsound(floor, deconstruct_sound, 80, 1) return TRUE if(constructed) diff --git a/code/game/turfs/flooring/flooring_reinforced.dm b/code/game/turfs/flooring/flooring_reinforced.dm index 38234d29ce8..a48566d0861 100644 --- a/code/game/turfs/flooring/flooring_reinforced.dm +++ b/code/game/turfs/flooring/flooring_reinforced.dm @@ -24,6 +24,7 @@ "broken4" ) uid = "floor_reinf" + deconstruct_sound = 'sound/items/Deconstruct.ogg' /decl/flooring/reinforced/circuit name = "processing strata" diff --git a/code/game/turfs/flooring/flooring_tiled.dm b/code/game/turfs/flooring/flooring_tiled.dm index e2b4af68c87..4b762fffeef 100644 --- a/code/game/turfs/flooring/flooring_tiled.dm +++ b/code/game/turfs/flooring/flooring_tiled.dm @@ -15,6 +15,8 @@ space_smooth = SMOOTH_ALL constructed = TRUE gender = NEUTER + deconstruct_sound = 'sound/items/Deconstruct.ogg' + burned_states = list( "burned0", "burned1" @@ -87,6 +89,7 @@ color = null build_type = null uid = "floor_tiled_new" + deconstruct_sound = 'sound/items/Deconstruct.ogg' /decl/flooring/tiling/new_tile/cargo_one icon_base = "cargo_one_full" diff --git a/code/game/turfs/floors/subtypes/floor_reinforced.dm b/code/game/turfs/floors/subtypes/floor_reinforced.dm index 5ea377aa396..551786ed357 100644 --- a/code/game/turfs/floors/subtypes/floor_reinforced.dm +++ b/code/game/turfs/floors/subtypes/floor_reinforced.dm @@ -1,8 +1,8 @@ /turf/floor/reinforced - name = "reinforced floor" - icon = 'icons/turf/flooring/tiles.dmi' - icon_state = "reinforced" - _flooring = /decl/flooring/reinforced + name = "reinforced floor" + icon = 'icons/turf/flooring/tiles.dmi' + icon_state = "reinforced" + _flooring = /decl/flooring/reinforced /turf/floor/reinforced/airless initial_gas = null From afcafb9523450011dc17673f5b1f058ffab040be Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Wed, 31 Dec 2025 01:03:19 +0000 Subject: [PATCH 021/149] Automatic changelog generation [ci skip] --- html/changelog.html | 6 ++++++ html/changelogs/.all_changelog.yml | 4 ++++ html/changelogs/AutoChangeLog-pr-5223.yml | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-5223.yml diff --git a/html/changelog.html b/html/changelog.html index 6e4661c6884..2a129d1019d 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -52,6 +52,12 @@ -->

+

31 December 2025

+

Penelope Haze updated:

+
    +
  • Kharmaan nymph jobbans now use the "Mantid Nymph" role in the jobban menu, rather than the Semi-Antagonist role.
  • +
+

30 December 2025

Penelope Haze updated:

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 b%xqOodx6}??PAp&D!$ZZL=BD3eSrKQ-_dRd literal 0 HcmV?d00001 From 88d07f3abebea398092aa09a77e6fca94f7ec582 Mon Sep 17 00:00:00 2001 From: mistakenot4892 Date: Sun, 28 Dec 2025 13:34:10 +1100 Subject: [PATCH 004/149] Porting cliffs and mines from Polaris. --- code/game/atoms.dm | 23 +- code/game/atoms_movable.dm | 4 + code/game/objects/__objs.dm | 1 - code/game/objects/effects/mines.dm | 98 ------ code/game/objects/effects/mines/_mine.dm | 202 ++++++++++++ .../objects/effects/mines/_mine_payload.dm | 22 ++ .../objects/effects/mines/mine_assembly.dm | 67 ++++ code/game/objects/effects/mines/mine_emp.dm | 12 + code/game/objects/effects/mines/mine_frag.dm | 23 ++ .../objects/effects/mines/mine_incendiary.dm | 16 + code/game/objects/effects/mines/mine_kick.dm | 17 + .../game/objects/effects/mines/mine_napalm.dm | 15 + .../objects/effects/mines/mine_radiation.dm | 14 + .../objects/effects/mines/mine_sleeping.dm | 14 + code/game/objects/effects/mines/mine_stun.dm | 14 + .../objects/effects/mines/mine_training.dm | 15 + code/game/objects/structures/catwalk.dm | 1 - code/game/objects/structures/cliffs.dm | 300 ++++++++++++++++++ code/game/objects/structures/fishtanks.dm | 20 +- code/game/objects/structures/railing.dm | 10 +- code/game/turfs/flooring/_flooring.dm | 1 + code/game/turfs/flooring/flooring_concrete.dm | 1 + code/game/turfs/flooring/flooring_grass.dm | 2 + code/game/turfs/flooring/flooring_mud.dm | 1 + code/game/turfs/flooring/flooring_snow.dm | 1 + code/game/turfs/turf.dm | 24 ++ code/game/turfs/turf_changing.dm | 2 + code/modules/clothing/shoes/_shoes.dm | 1 + .../designs/general/designs_arms_ammo.dm | 6 +- code/modules/mob/living/living.dm | 9 + code/modules/mob/mob_movement.dm | 10 + code/modules/multiz/movement.dm | 42 ++- .../modules/reagents/chems/chems_compounds.dm | 7 +- icons/obj/mine.dmi | Bin 0 -> 403 bytes icons/obj/structures/cliffs.dmi | Bin 0 -> 73393 bytes nebula.dme | 14 +- sound/effects/break_stone.ogg | Bin 0 -> 35871 bytes 37 files changed, 861 insertions(+), 148 deletions(-) delete mode 100644 code/game/objects/effects/mines.dm create mode 100644 code/game/objects/effects/mines/_mine.dm create mode 100644 code/game/objects/effects/mines/_mine_payload.dm create mode 100644 code/game/objects/effects/mines/mine_assembly.dm create mode 100644 code/game/objects/effects/mines/mine_emp.dm create mode 100644 code/game/objects/effects/mines/mine_frag.dm create mode 100644 code/game/objects/effects/mines/mine_incendiary.dm create mode 100644 code/game/objects/effects/mines/mine_kick.dm create mode 100644 code/game/objects/effects/mines/mine_napalm.dm create mode 100644 code/game/objects/effects/mines/mine_radiation.dm create mode 100644 code/game/objects/effects/mines/mine_sleeping.dm create mode 100644 code/game/objects/effects/mines/mine_stun.dm create mode 100644 code/game/objects/effects/mines/mine_training.dm create mode 100644 code/game/objects/structures/cliffs.dm create mode 100644 icons/obj/mine.dmi create mode 100644 icons/obj/structures/cliffs.dmi create mode 100644 sound/effects/break_stone.ogg diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c197b8580b9..fc5d6249d26 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -742,17 +742,19 @@ - `post_climb_check?`: If we should check if the user can continue climbing - Return: `TRUE` if they can climb, otherwise `FALSE` */ -/atom/proc/can_climb(var/mob/living/user, post_climb_check=0) +/atom/proc/can_climb(mob/living/user, post_climb_check = FALSE, silent = FALSE) if (!(atom_flags & ATOM_FLAG_CLIMBABLE) || !user.can_touch(src) || (!post_climb_check && climbers && (user in climbers))) return FALSE if (!user.Adjacent(src)) - to_chat(user, "You can't climb there, the way is blocked.") + if(!silent) + to_chat(user, SPAN_WARNING("You can't climb there, the way is blocked.")) return FALSE var/obj/occupied = turf_is_crowded(user) if(occupied) - to_chat(user, "There's \a [occupied] in the way.") + if(!silent) + to_chat(user, SPAN_WARNING("There's \a [occupied] in the way.")) return FALSE return TRUE @@ -1062,3 +1064,18 @@ if(blood_color) return FONT_COLORED(blood_color, "stained") return null + +// Used to mark a turf as containing objects that are dangerous to step onto. +/atom/proc/register_dangerous_to_step() + var/turf/T = get_turf(src) + if(T) + T.register_dangerous_object(src) + +/atom/proc/unregister_dangerous_to_step() + var/turf/T = get_turf(src) + if(T) + T.unregister_dangerous_object(src) + +// Test for if stepping on a tile containing this obj is safe to do, used for things like landmines and cliffs. +/atom/proc/is_safe_to_step(mob/living/stepper) + return TRUE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 94c8602eefe..628b5880042 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -628,3 +628,7 @@ /atom/movable/proc/is_valid_merchant_pad_target() return simulated + +// TODO reimplement this properly. +/atom/movable/proc/is_incorporeal() + return !simulated diff --git a/code/game/objects/__objs.dm b/code/game/objects/__objs.dm index 01cc88b50e3..123678e0cee 100644 --- a/code/game/objects/__objs.dm +++ b/code/game/objects/__objs.dm @@ -493,4 +493,3 @@ if(anchored) return FALSE return ..() - diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm deleted file mode 100644 index ac59e8322d4..00000000000 --- a/code/game/objects/effects/mines.dm +++ /dev/null @@ -1,98 +0,0 @@ -/obj/effect/mine - name = "Mine" - desc = "I Better stay away from that thing." - density = TRUE - anchored = TRUE - layer = OBJ_LAYER - icon = 'icons/obj/items/weapon/landmine.dmi' - icon_state = "uglymine" - var/triggerproc = PROC_REF(explode) // the proc that's called when the mine is triggered - var/triggered = 0 - -/obj/effect/mine/Initialize() - . = ..() - icon_state = "uglyminearmed" - -/obj/effect/mine/Crossed(atom/movable/AM) - if(!isobserver(AM)) - Bumped(AM) - -/obj/effect/mine/Bumped(mob/M) - - if(triggered) return - - if(ishuman(M)) - visible_message(SPAN_DANGER("\The [M] triggered \the [src]!")) - triggered = 1 - call(src,triggerproc)(M) - -/obj/effect/mine/proc/triggerrad(obj) - spark_at(src, cardinal_only = TRUE) - if(ismob(obj)) - var/mob/victim = obj - victim.radiation += 50 - if(ismob(obj)) - var/mob/mob = obj - mob.add_genetic_condition(pick(decls_repository.get_decls_of_type(/decl/genetic_condition/disability))) - qdel(src) - -/obj/effect/mine/proc/triggerstun(obj) - if(ismob(obj)) - var/mob/M = obj - SET_STATUS_MAX(M, STAT_STUN, 30) - spark_at(src, cardinal_only = TRUE) - qdel(src) - -/obj/effect/mine/proc/triggern2o(obj) - //example: n2o triggerproc - //note: im lazy - - for (var/turf/target in range(1,src)) - if(target.simulated && !target.blocks_air) - target.assume_gas(/decl/material/gas/nitrous_oxide, 30) - - qdel(src) - -/obj/effect/mine/proc/triggerflame(obj) - for (var/turf/target in range(1,src)) - if(target.simulated && !target.blocks_air) - target.assume_gas(/decl/material/gas/hydrogen, 30) - target.hotspot_expose(1000, CELL_VOLUME) - - qdel(src) - -/obj/effect/mine/proc/triggerkick(obj) - spark_at(src, cardinal_only = TRUE) - if(ismob(obj)) - var/mob/victim = obj - qdel(victim.client) - qdel(src) - -/obj/effect/mine/proc/explode(obj) - explosion(loc, 0, 1, 2, 3) - qdel(src) - -/obj/effect/mine/dnascramble - name = "Radiation Mine" - icon_state = "uglymine" - triggerproc = PROC_REF(triggerrad) - -/obj/effect/mine/flame - name = "Incendiary Mine" - icon_state = "uglymine" - triggerproc = PROC_REF(triggerflame) - -/obj/effect/mine/kick - name = "Kick Mine" - icon_state = "uglymine" - triggerproc = PROC_REF(triggerkick) - -/obj/effect/mine/n2o - name = "N2O Mine" - icon_state = "uglymine" - triggerproc = PROC_REF(triggern2o) - -/obj/effect/mine/stun - name = "Stun Mine" - icon_state = "uglymine" - triggerproc = PROC_REF(triggerstun) diff --git a/code/game/objects/effects/mines/_mine.dm b/code/game/objects/effects/mines/_mine.dm new file mode 100644 index 00000000000..a377a9d8286 --- /dev/null +++ b/code/game/objects/effects/mines/_mine.dm @@ -0,0 +1,202 @@ +/obj/item/mine + name = "mine" + desc = "A small landmine." + density = FALSE + anchored = FALSE + icon = 'icons/obj/mine.dmi' + icon_state = "mine" + + var/actual_name + var/actual_desc + var/actual_icon_state + var/hidden_alpha = 255 + + var/panel_open = FALSE + var/armed = FALSE + var/triggering = FALSE + var/datum/mine_payload/payload = /datum/mine_payload/explosive + +/obj/item/mine/Initialize() + . = ..() + if(ispath(payload)) + payload = new payload + register_dangerous_to_step() + + // We store and hide our appearance if we're armed, to avoid people gaming mines via desc. + actual_name = name + actual_desc = desc + actual_icon_state = icon_state + update_icon() + +/obj/item/mine/Destroy() + if(istype(payload)) + QDEL_NULL(payload) + unregister_dangerous_to_step() + return ..() + +/obj/item/mine/on_update_icon() + . = ..() + alpha = initial(alpha) + cut_overlays() + if(panel_open) + add_overlay("[icon_state]_open") + else if(armed) + add_overlay("[icon_state]_armed") + alpha = hidden_alpha + else + add_overlay("[icon_state]_safe") + +/obj/item/mine/attack_self(mob/user) // You do not want to move or throw a land mine while priming it... Explosives + Sudden Movement = Bad Times + if(armed) + to_chat(user, SPAN_WARNING("\The [src] is already armed!")) + return TRUE + add_fingerprint(user) + msg_admin_attack("[key_name_admin(user)] armed \the [src]") + user.visible_message( + SPAN_DANGER("\The [user] starts arming \the [src]."), + SPAN_DANGER("You start arming \the [src]. Hold still!") + ) + + if(user.do_skilled(10 SECONDS, SKILL_DEVICES, src)) + playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3) + prime(user) + else if(prob(user.skill_fail_chance(SKILL_DEVICES, 50, SKILL_ADEPT))) + visible_message( + SPAN_DANGER("\The [user] accidentally triggers \the [src]!"), + SPAN_DANGER("You accidentally trigger \the [src]!") + ) + prime(user) + trigger_payload(user) + else + to_chat(user, SPAN_WARNING("You fumble with \the [src], but thankfully manage not to set it off prematurely.")) + return TRUE + +// debug proc, replace with proper disarm minigame +/obj/item/mine/proc/disarm() + armed = FALSE + triggering = FALSE + anchored = FALSE + name = actual_name + desc = actual_desc + icon_state = actual_icon_state + hidden_alpha = 255 + update_icon() + +/obj/item/mine/attack_hand(mob/living/user) + if(armed) + trigger_payload() + return TRUE + return ..() + +/obj/item/mine/attackby(obj/item/W, mob/living/user) + + if(IS_SCREWDRIVER(W)) + if(W.do_tool_interaction(TOOL_SCREWDRIVER, user, src, 15 SECONDS, start_message = "carefully adjusting \the [src]'s casing", check_skill = SKILL_DEVICES)) + panel_open = !panel_open + visible_message(SPAN_NOTICE("\The [user] carefully [(panel_open ? "opens" : "closes")] the casing of \the [src].")) + update_icon() + else if(armed) + if(prob(user.skill_fail_chance(SKILL_DEVICES, 75, SKILL_PROF))) + to_chat(user, SPAN_DANGER("You set off \the [src]!")) + trigger_payload(user) + else + to_chat(user, SPAN_WARNING("You fumble with \the [src], but thankfully manage not to set it off prematurely.")) + return TRUE + + if(armed) + if(panel_open && IS_WIRECUTTER(W)) + if(W.do_tool_interaction(TOOL_WIRECUTTERS, user, src, 30 SECONDS, start_message = "painstakingly disarming \the [src]", check_skill = SKILL_DEVICES)) + visible_message(SPAN_NOTICE("\The [user] disarms \the [src]!")) + disarm() + return TRUE + if(armed) // checking again in case the do_after() stacks + if(prob(user.skill_fail_chance(SKILL_DEVICES, 75, SKILL_PROF))) + to_chat(user, SPAN_DANGER("You set off \the [src]!")) + trigger_payload(user) + else + to_chat(user, SPAN_WARNING("You fumble with \the [src], but thankfully manage not to set it off prematurely.")) + return TRUE + + return ..() + +/obj/item/mine/proc/prime(mob/user) + + if(armed) + return + + if(user) + visible_message(SPAN_NOTICE("\The [src] beeps as the priming sequence completes.")) + user.drop_from_inventory(src, get_turf(user)) + add_fingerprint(user) + + anchored = TRUE + armed = TRUE + + if(istype(loc, /turf/floor) && prob(65)) + var/turf/floor/floor = loc + var/decl/flooring/flooring = floor.get_topmost_flooring() + if(flooring.can_conceal_hazards) + hidden_alpha = pick(50, 90, 120) + + name = "mine" + desc = "A small landmine." + icon_state = "mine" + update_icon() + +/obj/item/mine/forceMove() + var/turf/old_turf = get_turf(loc) + . = ..() + if(.) + var/turf/new_turf = get_turf(src) + if(old_turf != new_turf) + old_turf?.unregister_dangerous_object(src) + new_turf?.register_dangerous_object(src) + +/obj/item/mine/Move() + var/turf/old_turf = get_turf(loc) + . = ..() + if(.) + var/turf/new_turf = get_turf(src) + if(old_turf != new_turf) + old_turf?.unregister_dangerous_object(src) + new_turf?.register_dangerous_object(src) + +/obj/item/mine/proc/trigger_payload(var/mob/living/M) + if(!triggering && payload && armed) + triggering = TRUE + if(ismob(loc)) + var/mob/holder = loc + holder.drop_from_inventory(src) + visible_message("\The [src] goes off!") + payload.trigger_payload(src, M) + disarm() // the mine can be reused if the payload doesn't destroy it. + return TRUE + return FALSE + +/obj/item/mine/bullet_act() + if(prob(50)) + trigger_payload() + if(!QDELETED(src)) + ..() + +/obj/item/mine/explosion_act(severity) + if(severity <= 2 || prob(50)) + trigger_payload() + if(!QDELETED(src)) + . = ..() + +/obj/item/mine/Crossed(atom/movable/AM) + . = ..() + if(istype(AM) && !AM.is_incorporeal()) + Bumped(AM) + +/obj/item/mine/Bumped(atom/movable/AM) + . = ..() + if(armed && !QDELETED(src) && !is_safe_to_step(AM)) + trigger_payload(AM) + +// This tells AI mobs to not be dumb and step on mines willingly. +/obj/item/mine/is_safe_to_step(mob/living/stepper) + if(!armed) + return TRUE + return !armed || stepper.can_overcome_gravity() diff --git a/code/game/objects/effects/mines/_mine_payload.dm b/code/game/objects/effects/mines/_mine_payload.dm new file mode 100644 index 00000000000..99139be493d --- /dev/null +++ b/code/game/objects/effects/mines/_mine_payload.dm @@ -0,0 +1,22 @@ +/datum/mine_payload + var/do_sparks = TRUE + var/destroy_self_on_trigger = TRUE + +/datum/mine_payload/proc/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + if(do_sparks) + var/datum/effect/effect/system/spark_spread/s = new + s.set_up(3, 1, owner) + s.start() + if(destroy_self_on_trigger) + if(!QDELETED(owner)) + QDEL_IN(owner, 1) + else + owner.disarm() // some mines can be reused + +/datum/mine_payload/proc/remove_from_mine() + return + +/datum/mine_payload/explosive/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + owner.visible_message("\The [owner] detonates!") + explosion(owner.loc, 0, 2, 3, 4) //land mines are dangerous, folks. diff --git a/code/game/objects/effects/mines/mine_assembly.dm b/code/game/objects/effects/mines/mine_assembly.dm new file mode 100644 index 00000000000..6a40fa0ae30 --- /dev/null +++ b/code/game/objects/effects/mines/mine_assembly.dm @@ -0,0 +1,67 @@ +/obj/item/mine/assembly + name = "mine assembly" + desc = "A small pressure-triggered device. Accepts grenades and tank transfer valves." + payload = null + + var/static/list/accepts_items = list( + /obj/item/transfer_valve = /datum/mine_payload/assembly/tank_transfer_valve, + /obj/item/grenade = /datum/mine_payload/assembly/grenade + ) + +/obj/item/mine/assembly/mapped + armed = TRUE + +/obj/item/mine/assembly/attackby(obj/item/W, mob/living/user) + if(!armed && !triggering) + var/datum/mine_payload/assembly/attached_payload = payload + if(attached_payload?.attached) + if(IS_SCREWDRIVER(W)) + to_chat(user, "You disconnect \the [src]'s [attached_payload.attached.name] and remove it.") + attached_payload.attached.forceMove(get_turf(user)) + payload.remove_from_mine() + QDEL_NULL(payload) + else + for(var/loadtype in accepts_items) + if(istype(W, loadtype)) + user.drop_from_inventory(W) + W.forceMove(src) + var/payload_type = accepts_items[loadtype] + attached_payload = new payload_type + attached_payload.attached = W + payload = attached_payload + return TRUE + return ..() + +/datum/mine_payload/assembly + var/obj/item/attached + +/datum/mine_payload/assembly/New(var/obj/item/_attaching) + ..() + attached = _attaching + +/datum/mine_payload/assembly/Destroy() + QDEL_NULL(attached) + . = ..() + +/datum/mine_payload/assembly/remove_from_mine() + attached = null + +/datum/mine_payload/assembly/tank_transfer_valve/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + if(istype(attached, /obj/item/transfer_valve)) + var/obj/item/transfer_valve/ttv = attached + ttv.forceMove(get_turf(owner)) + ttv.toggle_valve() + remove_from_mine() + +/datum/mine_payload/assembly/grenade/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + if(istype(attached, /obj/item/grenade)) + var/obj/item/grenade/grenade = attached + grenade.forceMove(get_turf(owner)) + if(ismob(trigger)) + var/mob/victim = trigger + if(victim.ckey) + msg_admin_attack("[key_name_admin(victim)] stepped on \a [owner], triggering [grenade]") + grenade.activate() + remove_from_mine() diff --git a/code/game/objects/effects/mines/mine_emp.dm b/code/game/objects/effects/mines/mine_emp.dm new file mode 100644 index 00000000000..5f8a54ad12f --- /dev/null +++ b/code/game/objects/effects/mines/mine_emp.dm @@ -0,0 +1,12 @@ +/obj/item/mine/emp + name = "\improper EMP mine" + desc = "A small explosive mine with a lightning bolt symbol on the side." + payload = /datum/mine_payload/emp + +/obj/item/mine/emp/mapped + armed = TRUE + +/datum/mine_payload/emp/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + owner.visible_message("\The [owner] flashes violently before disintegrating!") + empulse(owner.loc, 2, 4, 7, 10, 1) // As strong as an EMP grenade diff --git a/code/game/objects/effects/mines/mine_frag.dm b/code/game/objects/effects/mines/mine_frag.dm new file mode 100644 index 00000000000..de11402ca5a --- /dev/null +++ b/code/game/objects/effects/mines/mine_frag.dm @@ -0,0 +1,23 @@ +/obj/item/mine/frag + name = "fragmentation mine" + desc = "A small explosive mine with 'FRAG' and a grenade symbol on the side." + payload = /datum/mine_payload/frag + +/obj/item/mine/frag/mapped + armed = TRUE + +/datum/mine_payload/frag + var/fragment_types = list(/obj/item/projectile/bullet/pellet/fragment) + var/num_fragments = 20 //total number of fragments produced by the grenade + //The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern + var/spread_range = 7 + var/explosion_size = 3 + +/datum/mine_payload/frag/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + owner.visible_message("\The [owner] detonates!") + var/turf/O = get_turf(owner) + if(O) + owner.fragmentate(O, num_fragments, spread_range, fragment_types) + if(explosion_size) + explosion(O, -1, -1, round(explosion_size/2), explosion_size, FALSE) diff --git a/code/game/objects/effects/mines/mine_incendiary.dm b/code/game/objects/effects/mines/mine_incendiary.dm new file mode 100644 index 00000000000..f8b8a49ab2d --- /dev/null +++ b/code/game/objects/effects/mines/mine_incendiary.dm @@ -0,0 +1,16 @@ +/obj/item/mine/incendiary + name = "incendiary mine" + desc = "A small explosive mine with a fire symbol on the side." + payload = /datum/mine_payload/incendiary + +/obj/item/mine/incendiary/mapped + armed = TRUE + +/datum/mine_payload/incendiary/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + for(var/turf/floor/target in range(1, owner)) + if(!target.blocks_air) + target.assume_gas(/decl/material/gas/hydrogen, 10) + target.assume_gas(/decl/material/gas/oxygen, 5) + target.hotspot_expose(1000, CELL_VOLUME) + owner.visible_message("\The [owner] spews a cloud of flaming gas!") diff --git a/code/game/objects/effects/mines/mine_kick.dm b/code/game/objects/effects/mines/mine_kick.dm new file mode 100644 index 00000000000..ab38a2a2fb3 --- /dev/null +++ b/code/game/objects/effects/mines/mine_kick.dm @@ -0,0 +1,17 @@ +/obj/item/mine/kick + name = "kick mine" + desc = "Concentrated war crimes. Handle with care." + payload = /datum/mine_payload/kick + +/obj/item/mine/kick/mapped + armed = TRUE + +/datum/mine_payload/kick/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + if(isexosuit(trigger)) + var/mob/living/exosuit/mech = trigger + for(var/mob/pilot in mech.pilots) + qdel(pilot.client) + if(ismob(trigger)) + var/mob/M = trigger + qdel(M.client) diff --git a/code/game/objects/effects/mines/mine_napalm.dm b/code/game/objects/effects/mines/mine_napalm.dm new file mode 100644 index 00000000000..6bceace3f0e --- /dev/null +++ b/code/game/objects/effects/mines/mine_napalm.dm @@ -0,0 +1,15 @@ +/obj/item/mine/napalm + name = "napalm mine" + desc = "A small explosive mine with a fire symbol on the side." + payload = /datum/mine_payload/napalm + +/obj/item/mine/napalm/mapped + armed = TRUE + +/datum/mine_payload/napalm/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + if(isliving(trigger)) + var/mob/living/M = trigger + M.adjust_fire_intensity(5) + M.fire_act() + owner.visible_message(SPAN_DANGER("\The [owner] bursts into flames!")) diff --git a/code/game/objects/effects/mines/mine_radiation.dm b/code/game/objects/effects/mines/mine_radiation.dm new file mode 100644 index 00000000000..08b00d2a659 --- /dev/null +++ b/code/game/objects/effects/mines/mine_radiation.dm @@ -0,0 +1,14 @@ +/obj/item/mine/radiation + name = "radiation mine" + desc = "A small explosive mine with a radiation symbol on the side." + payload = /datum/mine_payload/radiation + +/obj/item/mine/radiation/mapped + armed = TRUE + +/datum/mine_payload/radiation/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + if(isliving(trigger)) + var/mob/living/victim = trigger + victim.apply_random_mutation(50) + owner.visible_message(SPAN_DANGER("\The [owner] flashes violently before disintegrating!")) diff --git a/code/game/objects/effects/mines/mine_sleeping.dm b/code/game/objects/effects/mines/mine_sleeping.dm new file mode 100644 index 00000000000..b6d5ad9a0de --- /dev/null +++ b/code/game/objects/effects/mines/mine_sleeping.dm @@ -0,0 +1,14 @@ +/obj/item/mine/sleeping + name = "nitrous oxide mine" + desc = "A small explosive mine with three Z's on the side." + payload = /datum/mine_payload/sleeping + +/obj/item/mine/sleeping/mapped + armed = TRUE + +/datum/mine_payload/sleeping/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + for (var/turf/floor/target in range(1, owner)) + if(!target.blocks_air) + target.assume_gas(/decl/material/gas/nitrous_oxide, 30) + owner.visible_message("\The [owner] sprays a cloud of gas!") diff --git a/code/game/objects/effects/mines/mine_stun.dm b/code/game/objects/effects/mines/mine_stun.dm new file mode 100644 index 00000000000..26b5704b304 --- /dev/null +++ b/code/game/objects/effects/mines/mine_stun.dm @@ -0,0 +1,14 @@ +/obj/item/mine/stun + name = "stun mine" + desc = "A small explosive mine with a lightning bolt symbol on the side." + payload = /datum/mine_payload/stun + +/obj/item/mine/stun/mapped + armed = TRUE + +/datum/mine_payload/stun/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + if(ismob(trigger)) + var/mob/M = trigger + SET_STATUS_MAX(M, STAT_STUN, 30) + owner.visible_message("\The [owner] flashes violently before disintegrating!") diff --git a/code/game/objects/effects/mines/mine_training.dm b/code/game/objects/effects/mines/mine_training.dm new file mode 100644 index 00000000000..13b23f31945 --- /dev/null +++ b/code/game/objects/effects/mines/mine_training.dm @@ -0,0 +1,15 @@ +/obj/item/mine/training + name = "training mine" + desc = "A mine with its payload removed, for EOD training and demonstrations." + payload = /datum/mine_payload/training + +/obj/item/mine/training/mapped + armed = TRUE + +/datum/mine_payload/training + do_sparks = FALSE + destroy_self_on_trigger = FALSE + +/datum/mine_payload/training/trigger_payload(var/obj/item/mine/owner, var/atom/trigger) + ..() + owner.visible_message("\The [owner]'s light flashes rapidly as it 'explodes'.") diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index 3f5b94ea071..8598d9db8d5 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -60,7 +60,6 @@ /obj/structure/catwalk/can_climb_from_below(var/mob/climber) return TRUE - /obj/structure/catwalk/proc/redraw_nearby_catwalks() for(var/direction in global.alldirs) var/obj/structure/catwalk/L = locate() in get_step(src, direction) diff --git a/code/game/objects/structures/cliffs.dm b/code/game/objects/structures/cliffs.dm new file mode 100644 index 00000000000..5745913052a --- /dev/null +++ b/code/game/objects/structures/cliffs.dm @@ -0,0 +1,300 @@ +/* +Cliffs give a visual illusion of depth by separating two places while presenting a 'top' and 'bottom' side. + +Ported from Polaris. + +Mobs moving into a cliff from the bottom side will simply bump into it and be denied moving into the tile, +where as mobs moving into a cliff from the top side will 'fall' off the cliff, forcing them to the bottom, causing significant damage and stunning them. + +Mobs can climb this while wearing climbing equipment by clickdragging themselves onto a cliff, as if it were a table. + +Flying mobs can pass over all cliffs with no risk of falling. + +Projectiles and thrown objects can pass, however if moving upwards, there is a chance for it to be stopped by the cliff. +This makes fighting something that is on top of a cliff more challenging. + +As a note, dir points upwards, e.g. pointing WEST means the left side is 'up', and the right side is 'down'. + +When mapping these in, be sure to give at least a one tile clearance, as NORTH facing cliffs expand to +two tiles on initialization, and which way a cliff is facing may change during maploading. +*/ + +/obj/structure/cliff + name = "cliff" + desc = "A steep rock ledge. You might be able to climb it if you feel bold enough." + icon = 'icons/obj/structures/cliffs.dmi' + anchored = TRUE + density = TRUE + opacity = FALSE + atom_flags = ATOM_FLAG_CLIMBABLE + appearance_flags = KEEP_TOGETHER + climb_speed_mult = 2 + + var/icon_variant = null // Used to make cliffs less repetitive by having a selection of sprites to display. + var/corner = FALSE // Used for icon things. + var/ramp = FALSE // Ditto. + var/bottom = FALSE // Used for 'bottom' typed cliffs, to avoid infinite cliffs, and for icons. + + var/is_double_cliff = FALSE // Set to true when making the two-tile cliffs, used for projectile checks. + var/uphill_penalty = 30 // Odds of a projectile not making it up the cliff. + +/obj/structure/cliff/Initialize() + . = ..() + register_dangerous_to_step() + +/obj/structure/cliff/Destroy() + unregister_dangerous_to_step() + if(is_double_cliff && !bottom) + var/turf/other = get_step(src, SOUTH) + if(istype(other)) + for(var/obj/structure/cliff/bottom/bottom in other) + qdel(bottom) + . = ..() + +/obj/structure/cliff/get_examine_hints(mob/user, distance, infix, suffix) + . = ..() + var/static/desc_string = "Walking off the edge of a cliff while on top will cause you to fall off, causing severe injury.
\ + You can climb this cliff if wearing special climbing equipment, by click-dragging yourself onto the cliff.
\ + Projectiles traveling up a cliff may hit the cliff instead, making it more difficult to fight something \ + on top." + LAZYADD(., desc_string) + +/obj/structure/cliff/Move() + var/turf/old_turf = get_turf(src) + . = ..() + if(.) + var/turf/new_turf = get_turf(src) + if(old_turf != new_turf) + old_turf.unregister_dangerous_object(src) + new_turf.register_dangerous_object(src) + +// These arrange their sprites at runtime, as opposed to being statically placed in the map file. +/obj/structure/cliff/automatic + icon_state = "cliffbuilder" + dir = NORTH + +/obj/structure/cliff/automatic/corner + icon_state = "cliffbuilder-corner" + dir = NORTHEAST + corner = TRUE + +// Tiny part that doesn't block, used for making 'ramps'. +/obj/structure/cliff/automatic/ramp + icon_state = "cliffbuilder-ramp" + dir = NORTHEAST + density = FALSE + ramp = TRUE + +// Made automatically as needed by automatic cliffs. +/obj/structure/cliff/bottom + bottom = TRUE + is_spawnable_type = FALSE + +/obj/structure/cliff/automatic/Initialize() + ..() + return INITIALIZE_HINT_LATELOAD + +// Paranoid about the maploader, direction is very important to cliffs, since they may get bigger if initialized while facing NORTH. +/obj/structure/cliff/automatic/LateInitialize() + if(dir in global.cardinal) + icon_variant = pick("a", "b", "c") + + if(dir & NORTH && !bottom) // North-facing cliffs require more cliffs to be made. + make_bottom() + + update_icon() + +/obj/structure/cliff/proc/make_bottom() + // First, make sure there's room to put the bottom side. + var/turf/turf = locate(x, y - 1, z) + if(!istype(turf)) + return FALSE + + // Now make the bottom cliff have mostly the same variables. + var/obj/structure/cliff/bottom/bottom_cliff = new(turf) + is_double_cliff = TRUE + climb_speed_mult /= 2 // Since there are two cliffs to climb when going north, both take half the time. + + bottom_cliff.dir = dir + bottom_cliff.is_double_cliff = TRUE + bottom_cliff.climb_speed_mult = climb_speed_mult + bottom_cliff.icon_variant = icon_variant + bottom_cliff.corner = corner + bottom_cliff.ramp = ramp + bottom_cliff.layer = layer - 0.1 + bottom_cliff.density = density + bottom_cliff.update_icon() + +/obj/structure/cliff/set_dir(new_dir) + ..() + update_icon() + +/obj/structure/cliff/on_update_icon() + icon_state = "cliff-[dir][icon_variant][bottom ? "-bottom" : ""][corner ? "-corner" : ""][ramp ? "-ramp" : ""]" + + // Now for making the top-side look like a different turf. + var/turf/turf = get_step(src, dir) + if(!istype(turf)) + return + + underlays.Cut() + var/subtraction_icon_state = "[icon_state]-subtract" + if(turf && (check_state_in_icon(subtraction_icon_state, icon))) + var/image/subtract = image(icon, subtraction_icon_state) + subtract.blend_mode = BLEND_SUBTRACT + underlays += subtract + +// Movement-related code. +/obj/structure/cliff/CanPass(atom/movable/mover, turf/target) + if(isliving(mover)) + var/mob/living/faller = mover + if(faller.can_overcome_gravity()) // Flying mobs can always pass. + return TRUE + return ..() + + else if(!istype(mover, /obj/item/projectile) && !mover.throwing) // 'sliding' objects can fall / bump into cliffs. + return ..() + + // Projectiles and objects flying 'upward' have a chance to hit the cliff instead, wasting the shot. + else if(istype(mover, /obj)) + var/obj/O = mover + if(check_shield_arc(src, dir, O)) // This is actually for mobs but it will work for our purposes as well. + if(prob(uphill_penalty / (1 + is_double_cliff) )) // Firing upwards facing NORTH means it will likely have to pass through two cliffs, so the chance is halved. + return FALSE + return TRUE + +/obj/structure/cliff/Bumped(atom/movable/mover) + if(!istype(mover, /obj/item/projectile) && !mover.throwing && should_fall(mover)) + fall_off_cliff(mover) + return + ..() + +/obj/structure/cliff/proc/should_fall(atom/movable/mover) + if(isliving(mover)) + var/mob/living/faller = mover + if(faller.can_overcome_gravity()) + return FALSE + var/turf/turf = get_turf(mover) + if(turf && get_dir(turf, loc) & global.reverse_dir[dir]) // dir points 'up' the cliff, e.g. cliff pointing NORTH will cause someone to fall if moving SOUTH into it. + return TRUE + return FALSE + +/obj/structure/cliff/proc/fall_off_cliff(atom/movable/mover) + . = FALSE + + var/mob/living/faller + if(isliving(mover)) + faller = mover + var/turf/turf = get_step(src, global.reverse_dir[dir]) + var/displaced = FALSE + + if(dir in list(EAST, WEST)) // Apply an offset if flying sideways, to help maintain the illusion of depth. + for(var/i = 1 to 2) + var/turf/new_T = locate(turf.x, turf.y - i, turf.z) + if(!new_T || locate(/obj/structure/cliff) in new_T) + break + turf = new_T + displaced = TRUE + + if(!istype(turf)) + return + + var/safe_fall = FALSE + if(istype(faller)) + safe_fall = faller.can_overcome_gravity() + else if(istype(mover, /obj/vehicle/bike)) + var/obj/vehicle/bike/Bi = mover + if(Bi.on) + safe_fall = TRUE + + // Buckled people can't react to save themselves, if they're not on a vehicle. + if(!istype(mover, /obj/vehicle) && !isexosuit(mover) && !faller && mover.buckled_mob) + faller = mover.buckled_mob + + if(safe_fall) + visible_message(SPAN_NOTICE("\The [mover] glides down from \the [src].")) + else + visible_message(SPAN_DANGER("\The [mover] falls off \the [src]!")) + + mover.forceMove(turf) + + var/harm = !is_double_cliff ? 1 : 0.5 + if(!safe_fall) + // Do the actual hurting. Double cliffs do halved damage due to them most likely hitting twice. + if(faller) + SET_STATUS_MAX(faller, STAT_WEAK, (5 * harm)) + + if(istype(mover, /obj/vehicle)) + var/obj/vehicle/vehicle = mover + vehicle.take_damage(40 * harm) + vehicle.visible_message(SPAN_WARNING("\The [vehicle] absorbs some of the impact, damaging it.")) + harm = round(harm * 0.5) + if(vehicle.buckled_mob) + var/damage = clamp(vehicle.buckled_mob.get_max_health() * 0.4, 20, 100) + vehicle.buckled_mob.take_damage(damage * harm, BRUTE, inflicter = src) + shake_camera(vehicle.buckled_mob, 1, 1) + else if(isexosuit(mover)) + var/mob/living/exosuit/Mech = mover + harm = round(harm * 0.5) + var/list/passengers = list() + for(var/mob/living/passenger in Mech.pilots) + passengers |= passenger + passenger.take_damage(clamp(faller.get_max_health() * 0.4, 10, 50) * harm, BRUTE, inflicter = src) + shake_camera(passenger, 1, 1) + to_chat(passenger, SPAN_DANGER("\The [Mech] shakes, bouncing you violently!")) + Mech.take_damage(clamp(Mech.get_max_health() * 0.4 * harm, 50, 300)) + if(QDELETED(Mech) && length(passengers)) // Damage caused the mech to explode, or otherwise vanish. + for(var/mob/living/victim in passengers) + to_chat(victim, SPAN_DANGER("The exosuit shears apart around you, throwing you from the debris!")) + victim.throw_at_random(FALSE,2,1, 32) + + playsound(mover, 'sound/effects/break_stone.ogg', 70, 1) + + var/fall_time = 3 + if(displaced) // Make the fall look more natural when falling sideways. + mover.pixel_z = 32 * 2 + animate(mover, pixel_z = 0, time = fall_time) + + sleep(fall_time) // A brief delay inbetween the two sounds helps sell the 'ouch' effect. + + if(QDELETED(src) || QDELETED(mover) || QDELETED(turf)) + return + + if(safe_fall) + visible_message(SPAN_NOTICE("\The [mover] lands on \the [turf].")) + playsound(mover, "rustle", 25, 1) + return + + playsound(mover, "punch", 70, 1) + + visible_message(SPAN_DANGER("\The [mover] hits \the [turf]!")) + + if(faller) + // The bigger they are, the harder they fall. + // They will take at least 20 damage at the minimum, and tries to scale up to 40% of their max health. + // This scaling is capped at 100 total damage, which occurs if the thing that fell has more than 250 health. + faller.take_damage(clamp(faller.get_max_health() * 0.4, 20, 100) * harm, BRUTE, ran_zone(), inflicter = src) + shake_camera(faller, 1, 1) + + // Now fall off more cliffs below this one if they exist. + var/obj/structure/cliff/bottom_cliff = locate() in turf + if(bottom_cliff && !QDELETED(mover)) // Exosuits are deleted when destroyed. This is to prevent phantom exosuits. + visible_message(SPAN_DANGER("\The [mover] rolls down towards \the [bottom_cliff]!")) + addtimer(CALLBACK(bottom_cliff, TYPE_PROC_REF(/obj/structure/cliff, fall_off_cliff), mover), 5) + +/obj/structure/cliff/can_climb(mob/living/user, post_climb_check = FALSE, silent = FALSE) + // Cliff climbing requires climbing gear. + if(ishuman(user)) + var/mob/living/human/H = user + var/obj/item/clothing/shoes/shoes = H.get_equipped_item(slot_shoes_str) + if(shoes?.rock_climbing) + return ..() // Do the other checks too. + if(!silent) + to_chat(user, SPAN_WARNING("\The [src] is too steep to climb unassisted.")) + return FALSE + +// This tells AI mobs to not be dumb and step off cliffs willingly. +/obj/structure/cliff/is_safe_to_step(mob/living/stepper) + if(should_fall(stepper)) + return FALSE + return ..() diff --git a/code/game/objects/structures/fishtanks.dm b/code/game/objects/structures/fishtanks.dm index c9ab4bc5f72..2e828ed6e80 100644 --- a/code/game/objects/structures/fishtanks.dm +++ b/code/game/objects/structures/fishtanks.dm @@ -138,25 +138,25 @@ var/global/list/global/aquarium_states_and_layers = list( for(var/atom/movable/AM in get_contained_external_atoms()) add_overlay(AM) -/obj/structure/glass_tank/can_climb(var/mob/living/user, post_climb_check=0) +/obj/structure/glass_tank/can_climb(mob/living/user, post_climb_check = FALSE, silent = FALSE) if (!user.can_touch(src) || !(atom_flags & ATOM_FLAG_CLIMBABLE) || (!post_climb_check && (user in climbers))) - return 0 - + return FALSE if (!Adjacent(user)) - to_chat(user, SPAN_DANGER("You can't climb there, the way is blocked.")) - return 0 - + if(!silent) + to_chat(user, SPAN_WARNING("You can't climb there, the way is blocked.")) + return FALSE var/obj/occupied = turf_is_crowded() if(occupied) - to_chat(user, SPAN_DANGER("There's \a [occupied] in the way.")) - return 0 - return 1 + if(!silent) + to_chat(user, SPAN_WARNING("There's \a [occupied] in the way.")) + return FALSE + return TRUE /obj/structure/glass_tank/do_climb(var/mob/living/user) if(!istype(user) || !can_climb(user)) return user.visible_message(SPAN_WARNING("\The [user] starts climbing into \the [src]!")) - if(!do_after(user,50)) + if(!do_after(user, 5 SECONDS)) return if (!can_climb(user)) return diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index b04f59f9a15..003d51d5b13 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -314,13 +314,13 @@ WOOD_RAILING_SUBTYPE(yew) if(!QDELETED(src)) qdel(src) -/obj/structure/railing/can_climb(var/mob/living/user, post_climb_check=0) - . = ..() - if(. && get_turf(user) == get_turf(src)) +/obj/structure/railing/can_climb(mob/living/user, post_climb_check = FALSE, silent = FALSE) + if((. = ..()) && get_turf(user) == get_turf(src)) var/turf/T = get_step(src, dir) if(T.turf_is_crowded(user)) - to_chat(user, "You can't climb there, the way is blocked.") - return 0 + if(!silent) + to_chat(user, SPAN_WARNING("You can't climb there, the way is blocked.")) + return FALSE /obj/structure/railing/do_climb(var/mob/living/user) . = ..() diff --git a/code/game/turfs/flooring/_flooring.dm b/code/game/turfs/flooring/_flooring.dm index f5f8083873f..10aa426edbb 100644 --- a/code/game/turfs/flooring/_flooring.dm +++ b/code/game/turfs/flooring/_flooring.dm @@ -26,6 +26,7 @@ var/global/list/flooring_cache = list() var/damage_temperature var/icon_edge_layer = FLOOR_EDGE_NONE var/has_environment_proc + var/can_conceal_hazards = FALSE /// Unbuildable if not set. Must be /obj/item/stack. var/build_type diff --git a/code/game/turfs/flooring/flooring_concrete.dm b/code/game/turfs/flooring/flooring_concrete.dm index e5d6edd5f17..89ed297a1f7 100644 --- a/code/game/turfs/flooring/flooring_concrete.dm +++ b/code/game/turfs/flooring/flooring_concrete.dm @@ -7,6 +7,7 @@ force_material = /decl/material/solid/stone/concrete constructed = TRUE uid = "floor_concrete" + can_conceal_hazards = TRUE /decl/flooring/concrete/reinforced name = "reinforced concrete" diff --git a/code/game/turfs/flooring/flooring_grass.dm b/code/game/turfs/flooring/flooring_grass.dm index dc53aaf4680..aa2396b3ba0 100644 --- a/code/game/turfs/flooring/flooring_grass.dm +++ b/code/game/turfs/flooring/flooring_grass.dm @@ -14,6 +14,8 @@ force_material = /decl/material/solid/organic/plantmatter/grass growth_value = 1.2 // Shouldn't really matter since you can't plant on grass, it turns to dirt first. uid = "floor_grass" + can_conceal_hazards = TRUE + var/harvestable = FALSE /decl/flooring/grass/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume) diff --git a/code/game/turfs/flooring/flooring_mud.dm b/code/game/turfs/flooring/flooring_mud.dm index bdce5b2859e..ea49cccd030 100644 --- a/code/game/turfs/flooring/flooring_mud.dm +++ b/code/game/turfs/flooring/flooring_mud.dm @@ -67,6 +67,7 @@ force_material = /decl/material/solid/soil growth_value = 1 uid = "floor_dirt" + can_conceal_hazards = TRUE /decl/flooring/dirt/fluid_act(turf/floor/target, datum/reagents/fluids) if(target.get_topmost_flooring() == src) diff --git a/code/game/turfs/flooring/flooring_snow.dm b/code/game/turfs/flooring/flooring_snow.dm index 881da81bdcc..b806c89f5d5 100644 --- a/code/game/turfs/flooring/flooring_snow.dm +++ b/code/game/turfs/flooring/flooring_snow.dm @@ -12,6 +12,7 @@ print_type = /obj/effect/footprints drop_material_on_remove = TRUE uid = "floor_snow" + can_conceal_hazards = TRUE /decl/flooring/snow/get_movement_delay(var/travel_dir, var/mob/mover) . = ..() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 33828543cd5..026732283b8 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -7,6 +7,9 @@ temperature_sensitive = TRUE atom_flags = ATOM_FLAG_OPEN_CONTAINER + // Linear lazylist of weakrefs to dangerous things on this turf. + var/list/dangerous_objects + /// Will participate in ZAS, join zones, etc. var/zone_membership_candidate = FALSE /// Will participate in external atmosphere simulation if the turf is outside and no zone is set. @@ -929,3 +932,24 @@ /turf/take_vaporized_reagent(reagent, amount) return assume_gas(reagent, round(amount / REAGENT_UNITS_PER_GAS_MOLE)) + +// Tells the turf that it currently contains something that automated movement should consider if planning to enter the tile. +// This uses lazy list macros to reduce memory footprint, since for 99% of turfs the list would've been empty anyways. +/turf/proc/register_dangerous_object(atom/thing) + if(!istype(thing)) + return FALSE + LAZYDISTINCTADD(dangerous_objects, weakref(thing)) + +// Similar to above, for when the dangerous object stops being dangerous/gets deleted/moved/etc. +/turf/proc/unregister_dangerous_object(atom/thing) + if(!istype(thing)) + return FALSE + LAZYREMOVE(dangerous_objects, weakref(thing)) + +/turf/proc/is_safe_to_enter(mob/living/stepper) + if(LAZYLEN(dangerous_objects)) + for(var/weakref/ref in dangerous_objects) + var/atom/thing = ref.resolve() + if(istype(thing) && !QDELETED(thing) && !thing.is_safe_to_step(stepper)) + return FALSE + return TRUE diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index 5c849feec9a..ee3311a90cb 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -80,6 +80,7 @@ var/old_ambient_light_old_r = ambient_light_old_r var/old_ambient_light_old_g = ambient_light_old_g var/old_ambient_light_old_b = ambient_light_old_b + var/old_dangerous_objects = dangerous_objects var/old_zone_membership_candidate = zone_membership_candidate @@ -104,6 +105,7 @@ // Set our observation bookkeeping lists back. changed_turf.event_listeners = old_event_listeners changed_turf._listening_to = old_listening_to + changed_turf.dangerous_objects = old_dangerous_objects changed_turf.affecting_heat_sources = old_affecting_heat_sources diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 589a7f0d79e..8b90dd6119a 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -17,6 +17,7 @@ fallback_slot = slot_shoes_str _base_attack_force = 5 + var/rock_climbing = FALSE var/can_fit_under_magboots = TRUE var/can_add_cuffs = TRUE var/obj/item/handcuffs/attached_cuffs = null diff --git a/code/modules/fabrication/designs/general/designs_arms_ammo.dm b/code/modules/fabrication/designs/general/designs_arms_ammo.dm index eb92c1ef0f3..2fd82b73938 100644 --- a/code/modules/fabrication/designs/general/designs_arms_ammo.dm +++ b/code/modules/fabrication/designs/general/designs_arms_ammo.dm @@ -81,4 +81,8 @@ /datum/fabricator_recipe/arms_ammo/hidden/speedloader_laser name = "ammunition (speedloader, laserbulb)" - path = /obj/item/ammo_magazine/speedloader/laser_revolver \ No newline at end of file + path = /obj/item/ammo_magazine/speedloader/laser_revolver + +/datum/fabricator_recipe/arms_ammo/hidden/mine_assembly + name = "mine assembly" + path = /obj/item/mine/assembly diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 956ae903000..36a2184fdf0 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2001,3 +2001,12 @@ default behaviour is: /mob/living/is_cloaked() return has_mob_modifier(/decl/mob_modifier/cloaked) + +/mob/living/proc/apply_random_mutation(radiation_amount) + set_unique_enzymes(num2text(random_id(/mob, 1000000, 9999999))) + if(prob(98)) + add_genetic_condition(pick(decls_repository.get_decls_of_type(/decl/genetic_condition/disability))) + else + add_genetic_condition(pick(decls_repository.get_decls_of_type(/decl/genetic_condition/superpower))) + if(radiation_amount) + apply_damage(radiation_amount, IRRADIATE, armor_pen = 100) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 27ae2d426d9..360f26b7555 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -5,6 +5,16 @@ if(DoMove(direction, src) & MOVEMENT_HANDLED) return TRUE // Doesn't necessarily mean the atom physically moved +/mob/living/SelfMove(var/direction) + // If on walk intent, don't willingly step into hazardous tiles. + // Unless the walker is confused. + var/turf/destination = get_step(src, direction) + if(istype(destination) && MOVING_DELIBERATELY(src) && !HAS_STATUS(src, STAT_CONFUSE)) + if(!destination.is_safe_to_enter(src)) + to_chat(src, SPAN_WARNING("\The [destination] is dangerous to move into.")) + return FALSE // In case any code wants to know if movement happened. + return ..() // Parent call should make the mob move. + /mob/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) . = current_posture.prone || ..() || !mover.density diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 4240ed507b2..923bfe97a84 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -48,29 +48,27 @@ /mob/proc/can_overcome_gravity() return FALSE -/mob/living/human/can_overcome_gravity() +/mob/living/can_overcome_gravity() //First do species check - if(species && species.can_overcome_gravity(src)) - return 1 - else - var/turf/T = loc - if(((T.get_physical_height() + T.get_fluid_depth()) >= FLUID_DEEP) || T.get_fluid_depth() >= FLUID_MAX_DEPTH) - if(can_float()) - return 1 - - for(var/atom/a in src.loc) - if(a.atom_flags & ATOM_FLAG_CLIMBABLE) - return 1 - - //Last check, list of items that could plausibly be used to climb but aren't climbable themselves - var/list/objects_to_stand_on = list( - /obj/item/stool, - /obj/structure/bed, - ) - for(var/type in objects_to_stand_on) - if(locate(type) in src.loc) - return 1 - return 0 + var/decl/species/my_species = get_species() + if(my_species?.can_overcome_gravity(src)) + return TRUE + var/turf/T = loc + if(((T.get_physical_height() + T.get_fluid_depth()) >= FLUID_DEEP) || T.get_fluid_depth() >= FLUID_MAX_DEPTH) + if(can_float()) + return TRUE + for(var/atom/climbable in src.loc) + if((climbable.atom_flags & ATOM_FLAG_CLIMBABLE) && climbable.can_climb(src, silent = TRUE)) + return TRUE + //Last check, list of items that could plausibly be used to climb but aren't climbable themselves + var/static/list/objects_to_stand_on = list( + /obj/item/stool, + /obj/structure/bed, + ) + for(var/type in objects_to_stand_on) + if(locate(type) in src.loc) + return TRUE + return FALSE //FALLING STUFF diff --git a/code/modules/reagents/chems/chems_compounds.dm b/code/modules/reagents/chems/chems_compounds.dm index cb305d78e23..f080406738f 100644 --- a/code/modules/reagents/chems/chems_compounds.dm +++ b/code/modules/reagents/chems/chems_compounds.dm @@ -263,12 +263,7 @@ if(!M.has_genetic_information()) return if(prob(removed * 0.1)) // Approx. one mutation per 10 injected/20 ingested/30 touching units - M.set_unique_enzymes(num2text(random_id(/mob, 1000000, 9999999))) - if(prob(98)) - M.add_genetic_condition(pick(decls_repository.get_decls_of_type(/decl/genetic_condition/disability))) - else - M.add_genetic_condition(pick(decls_repository.get_decls_of_type(/decl/genetic_condition/superpower))) - M.apply_damage(10 * removed, IRRADIATE, armor_pen = 100) + M.apply_random_mutation(10 * removed) /decl/material/liquid/lactate name = "lactate" diff --git a/icons/obj/mine.dmi b/icons/obj/mine.dmi new file mode 100644 index 0000000000000000000000000000000000000000..1c28f5775952936c83bc532c23f90cf9acda535b GIT binary patch literal 403 zcmeAS@N?(olHy`uVBq!ia0vp^2|(|NlQTEjQ~KP$OeWkY6x^!?PP{Ku&j6 zNJNQCYH@N=WKhlO#F@nvH#g*lHV9hnrO5Ugo#tRLFhZLGR^g~SQdCy#uzz0UZyZU_`P`doa; zGr{GXEDU+uXF7y0S@KLJtVw2J^E%y)8s?_08nvgm*461Hyk}x)4|h%Q_<2bl=&V{# z7sn8f&g29M*2N9W92y!sC#vwaaq%7c@kElfwYQgf0!z708wx}yMIPK`qSe4?o-pM_z@<5sqVt7#)Fo%PwF#}S6X|IRG~jY$G)!PN v@06;+-u6{1-oD!M literal 0 HcmV?d00001 diff --git a/icons/obj/structures/cliffs.dmi b/icons/obj/structures/cliffs.dmi new file mode 100644 index 0000000000000000000000000000000000000000..4713360313f725719630a372a313110bb1e03d3d GIT binary patch literal 73393 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 literal 0 HcmV?d00001 diff --git a/nebula.dme b/nebula.dme index 5cffd8b3216..34cdd86342d 100644 --- a/nebula.dme +++ b/nebula.dme @@ -1033,7 +1033,6 @@ #include "code\game\objects\effects\landmarks.dm" #include "code\game\objects\effects\landmarks_endgame.dm" #include "code\game\objects\effects\landmarks_latejoin.dm" -#include "code\game\objects\effects\mines.dm" #include "code\game\objects\effects\misc.dm" #include "code\game\objects\effects\overlays.dm" #include "code\game\objects\effects\portals.dm" @@ -1055,6 +1054,18 @@ #include "code\game\objects\effects\decals\Cleanable\misc.dm" #include "code\game\objects\effects\decals\Cleanable\robots.dm" #include "code\game\objects\effects\decals\Cleanable\tracks.dm" +#include "code\game\objects\effects\mines\_mine.dm" +#include "code\game\objects\effects\mines\_mine_payload.dm" +#include "code\game\objects\effects\mines\mine_assembly.dm" +#include "code\game\objects\effects\mines\mine_emp.dm" +#include "code\game\objects\effects\mines\mine_frag.dm" +#include "code\game\objects\effects\mines\mine_incendiary.dm" +#include "code\game\objects\effects\mines\mine_kick.dm" +#include "code\game\objects\effects\mines\mine_napalm.dm" +#include "code\game\objects\effects\mines\mine_radiation.dm" +#include "code\game\objects\effects\mines\mine_sleeping.dm" +#include "code\game\objects\effects\mines\mine_stun.dm" +#include "code\game\objects\effects\mines\mine_training.dm" #include "code\game\objects\effects\spawners\bombspawner.dm" #include "code\game\objects\effects\spawners\gibspawner.dm" #include "code\game\objects\items\__item.dm" @@ -1403,6 +1414,7 @@ #include "code\game\objects\structures\bookcase.dm" #include "code\game\objects\structures\catwalk.dm" #include "code\game\objects\structures\charge_pylon.dm" +#include "code\game\objects\structures\cliffs.dm" #include "code\game\objects\structures\coathanger.dm" #include "code\game\objects\structures\compost.dm" #include "code\game\objects\structures\crematorium.dm" diff --git a/sound/effects/break_stone.ogg b/sound/effects/break_stone.ogg new file mode 100644 index 0000000000000000000000000000000000000000..711fd50d482cb6d493396ede7776635e03a5c797 GIT binary patch literal 35871 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%0AGq0*XTUW6+!AZa-u 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 Lc;pP=H_#^l)@fHG literal 0 HcmV?d00001 From a4a86a09a28d65f2eca97add0cd7d3ebeceee753 Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sun, 28 Dec 2025 15:02:15 -0500 Subject: [PATCH 005/149] Move 'helping hands' out of augments module --- code/{modules/augment => game/objects/items}/helping_hands.dm | 0 nebula.dme | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename code/{modules/augment => game/objects/items}/helping_hands.dm (100%) diff --git a/code/modules/augment/helping_hands.dm b/code/game/objects/items/helping_hands.dm similarity index 100% rename from code/modules/augment/helping_hands.dm rename to code/game/objects/items/helping_hands.dm diff --git a/nebula.dme b/nebula.dme index 6e5ed0bad9c..abb0ae344ea 100644 --- a/nebula.dme +++ b/nebula.dme @@ -1077,6 +1077,7 @@ #include "code\game\objects\items\documents.dm" #include "code\game\objects\items\fleece.dm" #include "code\game\objects\items\glassjar.dm" +#include "code\game\objects\items\helping_hands.dm" #include "code\game\objects\items\holosign_creator.dm" #include "code\game\objects\items\horseshoe.dm" #include "code\game\objects\items\hourglass.dm" @@ -1780,7 +1781,6 @@ #include "code\modules\atmospherics\components\unary\vent_scrubber.dm" #include "code\modules\augment\active.dm" #include "code\modules\augment\augment.dm" -#include "code\modules\augment\helping_hands.dm" #include "code\modules\augment\simple.dm" #include "code\modules\augment\active\armblades.dm" #include "code\modules\augment\active\cyberbrain.dm" From fd05aa71841683711c71829adede9ca57b7ded0a Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sun, 28 Dec 2025 16:34:21 -0500 Subject: [PATCH 006/149] Move augments into a modpack --- code/__defines/mobs.dm | 15 -------- code/_onclick/hud/action.dm | 3 -- code/game/objects/structures/mineral_bath.dm | 7 +++- code/modules/augment/passive/armor.dm | 12 ------ .../bodytype/bodytype_prosthetic_models.dm | 7 +--- .../preference_setup/loadout/_defines.dm | 6 --- .../preference_setup/loadout/loadout.dm | 7 ++++ .../definitions/modifiers_nanoswarm.dm | 34 ----------------- .../ailments/faults/fault_locking_thumbs.dm | 20 +++++----- .../faults/fault_visual_impairment.dm | 5 +-- .../organs/external/_external_damage.dm | 32 +++++++--------- code/modules/organs/external/diagnostics.dm | 3 -- code/modules/surgery/organs_internal.dm | 14 ++++--- code/modules/surgery/robotics.dm | 8 ++-- maps/exodus/exodus.dm | 1 + maps/ministation/ministation.dm | 1 + maps/modpack_testing/modpack_testing.dm | 1 + maps/tradeship/tradeship.dm | 1 + mods/content/augments/_augments.dm | 13 +++++++ mods/content/augments/_augments.dme | 24 ++++++++++++ .../content/augments}/active.dm | 3 ++ .../content/augments}/active/armblades.dm | 2 +- .../content/augments}/active/cyberbrain.dm | 0 .../content/augments}/active/polytool.dm | 0 .../augments}/active/tool/engineering.dm | 12 +++--- .../content/augments}/active/tool/surgical.dm | 0 .../content/augments/augment_loadout.dm | 11 ++++-- .../content/augments/augment_organ.dm | 12 +++++- mods/content/augments/bodytype_augment.dm | 4 ++ .../content/augments}/designs_augments.dm | 0 .../content/augments/icons}/augment.dmi | Bin .../content/augments/icons}/augment_tools.dmi | Bin .../content/augments/icons}/welder_finger.dmi | Bin mods/content/augments/overrides.dm | 32 ++++++++++++++++ mods/content/augments/passive/armor.dm | 26 +++++++++++++ .../content/augments}/passive/boost.dm | 0 .../content/augments}/passive/boost/muscle.dm | 0 .../content/augments}/passive/boost/reflex.dm | 0 .../augments}/passive/boost/shooting.dm | 0 .../content/augments}/passive/nanoaura.dm | 36 ++++++++++++++++++ .../content/augments}/simple.dm | 0 .../_integrated_electronics.dme | 1 - .../fabricator_designs.dm | 3 -- mods/~compatibility/patches/circuits.dm | 4 ++ .../patches/circuits/augment_circuits.dm} | 6 ++- nebula.dme | 18 --------- 46 files changed, 227 insertions(+), 157 deletions(-) delete mode 100644 code/modules/augment/passive/armor.dm delete mode 100644 code/modules/client/preference_setup/loadout/_defines.dm delete mode 100644 code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm create mode 100644 mods/content/augments/_augments.dm create mode 100644 mods/content/augments/_augments.dme rename {code/modules/augment => mods/content/augments}/active.dm (87%) rename {code/modules/augment => mods/content/augments}/active/armblades.dm (97%) rename {code/modules/augment => mods/content/augments}/active/cyberbrain.dm (100%) rename {code/modules/augment => mods/content/augments}/active/polytool.dm (100%) rename {code/modules/augment => mods/content/augments}/active/tool/engineering.dm (84%) rename {code/modules/augment => mods/content/augments}/active/tool/surgical.dm (100%) rename code/modules/client/preference_setup/loadout/lists/augmentations.dm => mods/content/augments/augment_loadout.dm (79%) rename code/modules/augment/augment.dm => mods/content/augments/augment_organ.dm (85%) create mode 100644 mods/content/augments/bodytype_augment.dm rename {code/modules/fabrication/designs/robotics => mods/content/augments}/designs_augments.dm (100%) rename {icons/obj => mods/content/augments/icons}/augment.dmi (100%) rename {icons/obj => mods/content/augments/icons}/augment_tools.dmi (100%) rename {icons/obj/items/tool/welders => mods/content/augments/icons}/welder_finger.dmi (100%) create mode 100644 mods/content/augments/overrides.dm create mode 100644 mods/content/augments/passive/armor.dm rename {code/modules/augment => mods/content/augments}/passive/boost.dm (100%) rename {code/modules/augment => mods/content/augments}/passive/boost/muscle.dm (100%) rename {code/modules/augment => mods/content/augments}/passive/boost/reflex.dm (100%) rename {code/modules/augment => mods/content/augments}/passive/boost/shooting.dm (100%) rename {code/modules/augment => mods/content/augments}/passive/nanoaura.dm (58%) rename {code/modules/augment => mods/content/augments}/simple.dm (100%) rename mods/{content/integrated_electronics/assemblies/circuit_augment.dm => ~compatibility/patches/circuits/augment_circuits.dm} (90%) diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 75c9ac6ef8c..77b1dae70dd 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -160,21 +160,6 @@ // Robo Organs. #define BP_VOICE "vocal synthesiser" -//Augmetations -#define BP_AUGMENT_R_ARM "right arm augment" -#define BP_AUGMENT_L_ARM "left arm augment" -#define BP_AUGMENT_R_HAND "right hand augment" -#define BP_AUGMENT_L_HAND "left hand augment" -#define BP_AUGMENT_R_LEG "right leg augment" -#define BP_AUGMENT_L_LEG "left leg augment" -#define BP_AUGMENT_CHEST_ARMOUR "chest armor augment" -#define BP_AUGMENT_CHEST_ACTIVE "active chest augment" -#define BP_AUGMENT_HEAD "head augment" - -//Augment flags -#define AUGMENTATION_MECHANIC 1 -#define AUGMENTATION_ORGANIC 2 - // Prosthetic helpers. #define BP_IS_PROSTHETIC(org) (!QDELETED(org) && (org.organ_properties & ORGAN_PROP_PROSTHETIC)) #define BP_IS_ROBOTIC(org) (!QDELETED(org) && (org.bodytype?.is_robotic)) diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index e6599e5ac2b..70cc620cb20 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -162,9 +162,6 @@ if(istype(O)) O.refresh_action_button() -/datum/action/item_action/organ/augment - button_icon = 'icons/obj/augment.dmi' - #undef AB_WEST_OFFSET #undef AB_NORTH_OFFSET #undef AB_MAX_COLUMNS \ No newline at end of file diff --git a/code/game/objects/structures/mineral_bath.dm b/code/game/objects/structures/mineral_bath.dm index 1ed4d581c72..1ff9947a566 100644 --- a/code/game/objects/structures/mineral_bath.dm +++ b/code/game/objects/structures/mineral_bath.dm @@ -137,7 +137,7 @@ for(var/obj/item/organ/external/limb in occupant.get_external_organs()) if(BP_IS_PROSTHETIC(limb)) for(var/obj/implanted_object in limb.implants) - if(!istype(implanted_object,/obj/item/implant) && !istype(implanted_object,/obj/item/organ/internal/augment) && prob(25)) // We don't want to remove REAL implants. Just shrapnel etc. + if(!should_dissolve_implant(implanted_object)) // We don't want to remove REAL implants. Just shrapnel etc. LAZYREMOVE(limb.implants, implanted_object) to_chat(occupant, SPAN_NOTICE("The mineral-rich bath dissolves the [implanted_object.name].")) qdel(implanted_object) @@ -149,3 +149,8 @@ limb.status |= ORGAN_BRITTLE to_chat(occupant, SPAN_WARNING("It feels a bit brittle, though...")) break + +/obj/structure/mineral_bath/proc/should_dissolve_implant(obj/implanted_object) + if(istype(implanted_object, /obj/item/implant)) + return FALSE + return prob(25) diff --git a/code/modules/augment/passive/armor.dm b/code/modules/augment/passive/armor.dm deleted file mode 100644 index 306de571064..00000000000 --- a/code/modules/augment/passive/armor.dm +++ /dev/null @@ -1,12 +0,0 @@ -/obj/item/organ/internal/augment/armor - name = "subdermal armor" - allowed_organs = list(BP_AUGMENT_CHEST_ARMOUR) - icon_state = "armor-chest" - desc = "A flexible composite mesh designed to prevent tearing and puncturing of underlying tissue." - material = /decl/material/solid/metal/steel - origin_tech = @'{"materials":4,"engineering":2,"biotech":3}' - var/brute_mult = 0.8 - var/burn_mult = 1 - -/obj/item/organ/internal/augment/armor/reset_matter() - matter = list(/decl/material/solid/fiberglass = MATTER_AMOUNT_REINFORCEMENT) \ No newline at end of file diff --git a/code/modules/bodytype/bodytype_prosthetic_models.dm b/code/modules/bodytype/bodytype_prosthetic_models.dm index d7156bf6bdc..6d6f47ff139 100644 --- a/code/modules/bodytype/bodytype_prosthetic_models.dm +++ b/code/modules/bodytype/bodytype_prosthetic_models.dm @@ -19,9 +19,4 @@ required_map_tech = MAP_TECH_LEVEL_MEDIEVAL uid = "bodytype_prosthetic_wooden" -DEFINE_ROBOLIMB_MODEL_TRAITS(/decl/bodytype/prosthetic/wooden, pirate, 0, "wooden") - -// Dummy/stub prosthetic type for augment implants. -/decl/bodytype/prosthetic/augment - name = "Augment" - uid = "bodytype_prosthetic_augment" +DEFINE_ROBOLIMB_MODEL_TRAITS(/decl/bodytype/prosthetic/wooden, pirate, 0, "wooden") \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/_defines.dm b/code/modules/client/preference_setup/loadout/_defines.dm deleted file mode 100644 index c98f5c4d313..00000000000 --- a/code/modules/client/preference_setup/loadout/_defines.dm +++ /dev/null @@ -1,6 +0,0 @@ -#define GEAR_HAS_COLOR_SELECTION BITFLAG(0) -#define GEAR_HAS_TYPE_SELECTION BITFLAG(1) -#define GEAR_HAS_SUBTYPE_SELECTION BITFLAG(2) -#define GEAR_HAS_CUSTOM_SELECTION BITFLAG(3) -#define GEAR_NO_EQUIP BITFLAG(4) -#define GEAR_NO_FINGERPRINTS BITFLAG(5) diff --git a/code/modules/client/preference_setup/loadout/loadout.dm b/code/modules/client/preference_setup/loadout/loadout.dm index ceb5eaaeac5..d8b2da85e07 100644 --- a/code/modules/client/preference_setup/loadout/loadout.dm +++ b/code/modules/client/preference_setup/loadout/loadout.dm @@ -406,6 +406,13 @@ var/list/allowed_branches /// Skills required to spawn with this item. var/list/allowed_skills + // The various valid values for loadout_flags. + var/const/GEAR_HAS_COLOR_SELECTION = BITFLAG(0) + var/const/GEAR_HAS_TYPE_SELECTION = BITFLAG(1) + var/const/GEAR_HAS_SUBTYPE_SELECTION = BITFLAG(2) + var/const/GEAR_HAS_CUSTOM_SELECTION = BITFLAG(3) + var/const/GEAR_NO_EQUIP = BITFLAG(4) + var/const/GEAR_NO_FINGERPRINTS = BITFLAG(5) /// Special tweaks in new var/loadout_flags /// Special tweak in New diff --git a/code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm b/code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm deleted file mode 100644 index ddb6d6023ea..00000000000 --- a/code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm +++ /dev/null @@ -1,34 +0,0 @@ -//This handy augment protects you to a degree, keeping it online after critical damage however is bad -/decl/mob_modifier/nanoswarm - name = "Defensive Nanoswarm" - desc = "You are surrounded by nanomachines that harden in response to projectiles." - hud_icon_state = "nanomachines" - on_add_message_1p = SPAN_NOTICE("Your skin tingles as the nanites spread over your body.") - on_end_message_1p = SPAN_WARNING("The nanites dissolve!") - -/decl/mob_modifier/nanoswarm/on_modifier_datum_added(mob/living/_owner, decl/mob_modifier/modifier) - . = ..() - playsound(_owner.loc,'sound/weapons/flash.ogg',35,1) - -/decl/mob_modifier/nanoswarm/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) - if(attack_type != MM_ATTACK_TYPE_PROJECTILE) - return ..() - - var/obj/item/organ/internal/augment/active/nanounit/unit - for(var/datum/mob_modifier/modifier in modifiers) - var/obj/item/organ/internal/augment/active/nanounit/implant = modifier.source?.resolve() - if(istype(implant) && implant.active && implant.charges >= 0) // active with 0 charges means it's about to critically fail. - unit = implant - break - - if(!istype(unit)) - return ..() - - _owner.visible_message(SPAN_WARNING("The nanomachines harden as a response to physical trauma!")) - playsound(_owner, 'sound/effects/basscannon.ogg',35,1) - unit.charges-- - if(unit.charges <= 0) - to_chat(_owner, SPAN_DANGER("Warning: Critical damage threshold passed. Shut down unit to avoid further damage.")) - else - unit.catastrophic_failure() - return MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED diff --git a/code/modules/organs/ailments/faults/fault_locking_thumbs.dm b/code/modules/organs/ailments/faults/fault_locking_thumbs.dm index c689d9c477d..61678c157ea 100644 --- a/code/modules/organs/ailments/faults/fault_locking_thumbs.dm +++ b/code/modules/organs/ailments/faults/fault_locking_thumbs.dm @@ -5,20 +5,18 @@ BP_L_ARM, BP_L_HAND, BP_R_ARM, - BP_R_HAND, - BP_AUGMENT_R_ARM, - BP_AUGMENT_L_ARM, - BP_AUGMENT_R_HAND, - BP_AUGMENT_L_HAND + BP_R_HAND ) +/datum/ailment/fault/locking_thumbs/proc/resolve_tag_to_slot(organ_tag) + switch(organ_tag) + if(BP_L_ARM, BP_L_HAND) + return BP_L_HAND + if(BP_R_ARM, BP_R_HAND) + return BP_R_HAND + /datum/ailment/fault/locking_thumbs/on_ailment_event() - var/slot = null - switch (organ.organ_tag) - if (BP_L_ARM, BP_L_HAND, BP_AUGMENT_L_HAND, BP_AUGMENT_L_ARM) - slot = BP_L_HAND - if (BP_R_ARM, BP_R_HAND, BP_AUGMENT_R_HAND, BP_AUGMENT_R_ARM) - slot = BP_R_HAND + var/slot = resolve_tag_to_slot(organ.organ_tag) var/obj/item/thing = organ.owner.get_equipped_item(slot) if(thing && organ.owner.try_unequip(thing)) var/decl/pronouns/pronouns = organ.owner.get_pronouns() diff --git a/code/modules/organs/ailments/faults/fault_visual_impairment.dm b/code/modules/organs/ailments/faults/fault_visual_impairment.dm index 3d54995fc28..c7b1c8fe87e 100644 --- a/code/modules/organs/ailments/faults/fault_visual_impairment.dm +++ b/code/modules/organs/ailments/faults/fault_visual_impairment.dm @@ -1,10 +1,9 @@ /datum/ailment/fault/visual_impair name = "visual impairment" applies_to_organ = list( - BP_HEAD, - BP_AUGMENT_HEAD + BP_HEAD, ) - + /datum/ailment/fault/visual_impair/New() ..() if(organ?.owner) diff --git a/code/modules/organs/external/_external_damage.dm b/code/modules/organs/external/_external_damage.dm index 6ca145d4336..2431326554d 100644 --- a/code/modules/organs/external/_external_damage.dm +++ b/code/modules/organs/external/_external_damage.dm @@ -11,8 +11,11 @@ if(!owner) return ..() - var/brute = damage_type == BRUTE ? round(damage * get_brute_mod(damage_flags), 0.1) : 0 - var/burn = damage_type == BURN ? round(damage * get_burn_mod(damage_flags), 0.1) : 0 + var/final_brute_mod = get_brute_mod(damage_flags) + (0.2 * burn_dam/max_damage) // extra brute taken if you have burn damage. why? ask whoever originally coded it. + var/final_burn_mod = get_burn_mod(damage_flags) + + var/brute = damage_type == BRUTE ? round(damage * final_brute_mod, 0.1) : 0 + var/burn = damage_type == BURN ? round(damage * final_burn_mod, 0.1) : 0 if((brute <= 0) && (burn <= 0)) return 0 @@ -318,29 +321,20 @@ return FALSE /obj/item/organ/external/proc/get_brute_mod(var/damage_flags) - var/obj/item/organ/internal/augment/armor/A = owner?.get_organ(BP_AUGMENT_CHEST_ARMOUR, /obj/item/organ/internal/augment/armor) - var/B = 1 - if(A) - B = A.brute_mult + . = 1 if(!BP_IS_PROSTHETIC(src)) - B *= species.get_brute_mod(owner) - var/blunt = !(damage_flags & DAM_EDGE|DAM_SHARP) - if(blunt && BP_IS_BRITTLE(src)) - B *= 1.5 + . *= species.get_brute_mod(owner) + if(!(damage_flags & DAM_EDGE|DAM_SHARP) && BP_IS_BRITTLE(src)) + . *= 1.5 if(BP_IS_CRYSTAL(src)) - B *= 0.8 - return B + (0.2 * burn_dam/max_damage) //burns make you take more brute damage + . *= 0.8 /obj/item/organ/external/proc/get_burn_mod(var/damage_flags) - var/obj/item/organ/internal/augment/armor/A = owner?.get_organ(BP_AUGMENT_CHEST_ARMOUR, /obj/item/organ/internal/augment/armor) - var/B = 1 - if(A) - B = A.burn_mult + . = 1 if(!BP_IS_PROSTHETIC(src)) - B *= species.get_burn_mod(owner) + . *= species.get_burn_mod(owner) if(BP_IS_CRYSTAL(src)) - B *= 0.1 - return B + . *= 0.1 //organs can come off in three cases //1. If the damage source is edge_eligible and the brute damage dealt exceeds the edge threshold, then the organ is cut off. diff --git a/code/modules/organs/external/diagnostics.dm b/code/modules/organs/external/diagnostics.dm index b78c313b71c..d7047a14aa8 100644 --- a/code/modules/organs/external/diagnostics.dm +++ b/code/modules/organs/external/diagnostics.dm @@ -107,9 +107,6 @@ unknown_body++ if(unknown_body) . += "Unknown body present" - for(var/obj/item/organ/internal/augment/aug in internal_organs) - if(istype(aug) && aug.known) - . += "[capitalize(aug.name)] implanted" var/obj/item/organ/internal/lungs/L = locate() in src if( L && L.is_bruised()) . += "Lung ruptured" diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 1ed731ee454..4d25ab85a85 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -328,6 +328,9 @@ else return ..() +/obj/item/organ/internal/proc/get_attachment_failure_reason(obj/item/organ/external/affected, robotic = FALSE) + return FALSE + /decl/surgery_step/internal/attach_organ/pre_surgery_step(mob/living/user, mob/living/target, target_zone, obj/item/tool) var/list/attachable_organs @@ -342,7 +345,7 @@ if(!LAZYLEN(attachable_organs)) return FALSE - var/obj/item/organ/organ_to_replace = show_radial_menu(user, tool, attachable_organs, radius = 42, require_near = TRUE, use_labels = RADIAL_LABELS_OFFSET, check_locs = list(tool)) + var/obj/item/organ/internal/organ_to_replace = show_radial_menu(user, tool, attachable_organs, radius = 42, require_near = TRUE, use_labels = RADIAL_LABELS_OFFSET, check_locs = list(tool)) if(!organ_to_replace) return FALSE @@ -350,11 +353,10 @@ to_chat(user, SPAN_WARNING("You can't find anywhere to attach \the [organ_to_replace] to!")) return FALSE - if(istype(organ_to_replace, /obj/item/organ/internal/augment)) - var/obj/item/organ/internal/augment/A = organ_to_replace - if(!(A.augment_flags & AUGMENTATION_ORGANIC)) - to_chat(user, SPAN_WARNING("\The [A] cannot function within a non-robotic limb.")) - return FALSE + var/attach_failure_reason = organ_to_replace.get_attachment_failure_reason(affected, robotic = FALSE) // if this returns FALSE, it can attach + if(attach_failure_reason) + to_chat(user, attach_failure_reason) + return FALSE var/decl/species/species = target.get_species() if(!species) diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 07dd1eb2d65..ce4bd511bd6 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -463,12 +463,12 @@ var/image/radial_button = image(icon = I.icon, icon_state = I.icon_state) radial_button.name = "Reattach \the [I]" LAZYSET(removable_organs, I.organ_tag, radial_button) - var/organ_to_replace = show_radial_menu(user, tool, removable_organs, radius = 42, require_near = TRUE, use_labels = RADIAL_LABELS_OFFSET, check_locs = list(tool)) + var/obj/item/organ/internal/organ_to_replace = show_radial_menu(user, tool, removable_organs, radius = 42, require_near = TRUE, use_labels = RADIAL_LABELS_OFFSET, check_locs = list(tool)) if(!organ_to_replace) return FALSE - var/obj/item/organ/internal/augment/A = organ_to_replace - if(istype(A) && !(A.augment_flags & AUGMENTATION_MECHANIC)) - to_chat(user, SPAN_WARNING("\The [A] cannot function within a robotic limb.")) + var/attach_failure_reason = organ_to_replace.get_attachment_failure_reason(affected, robotic = TRUE) // if this returns FALSE, it can attach + if(attach_failure_reason) + to_chat(user, attach_failure_reason) return FALSE return organ_to_replace diff --git a/maps/exodus/exodus.dm b/maps/exodus/exodus.dm index 4308072cd47..43dcd862a40 100644 --- a/maps/exodus/exodus.dm +++ b/maps/exodus/exodus.dm @@ -3,6 +3,7 @@ #include "../../mods/content/mundane.dm" #include "../../mods/content/scaling_descriptors.dm" + #include "../../mods/content/augments/_augments.dme" #include "../../mods/content/beekeeping/_beekeeping.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/blob/_blob.dme" diff --git a/maps/ministation/ministation.dm b/maps/ministation/ministation.dm index f4aafdce320..19b9c46bc30 100644 --- a/maps/ministation/ministation.dm +++ b/maps/ministation/ministation.dm @@ -20,6 +20,7 @@ Twice... #include "../../mods/content/mundane.dm" #include "../../mods/content/scaling_descriptors.dm" + #include "../../mods/content/augments/_augments.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/blob/_blob.dme" #include "../../mods/content/corporate/_corporate.dme" diff --git a/maps/modpack_testing/modpack_testing.dm b/maps/modpack_testing/modpack_testing.dm index 505bf42e894..59029054760 100644 --- a/maps/modpack_testing/modpack_testing.dm +++ b/maps/modpack_testing/modpack_testing.dm @@ -7,6 +7,7 @@ #include "../../mods/content/mundane.dm" #include "../../mods/content/scaling_descriptors.dm" + #include "../../mods/content/augments/_augments.dme" #include "../../mods/content/beekeeping/_beekeeping.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/biomods/_biomods.dme" diff --git a/maps/tradeship/tradeship.dm b/maps/tradeship/tradeship.dm index 542a6dcb22f..d7c622f2a55 100644 --- a/maps/tradeship/tradeship.dm +++ b/maps/tradeship/tradeship.dm @@ -16,6 +16,7 @@ #include "../../mods/content/plant_dissection/_plant_dissection.dme" + #include "../../mods/content/augments/_augments.dme" #include "../../mods/content/beekeeping/_beekeeping.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/blob/_blob.dme" diff --git a/mods/content/augments/_augments.dm b/mods/content/augments/_augments.dm new file mode 100644 index 00000000000..702d94917fa --- /dev/null +++ b/mods/content/augments/_augments.dm @@ -0,0 +1,13 @@ +//Augmentation organ tag defines +#define BP_AUGMENT_R_ARM "right arm augment" +#define BP_AUGMENT_L_ARM "left arm augment" +#define BP_AUGMENT_R_HAND "right hand augment" +#define BP_AUGMENT_L_HAND "left hand augment" +#define BP_AUGMENT_R_LEG "right leg augment" +#define BP_AUGMENT_L_LEG "left leg augment" +#define BP_AUGMENT_CHEST_ARMOUR "chest armor augment" +#define BP_AUGMENT_CHEST_ACTIVE "active chest augment" +#define BP_AUGMENT_HEAD "head augment" + +/decl/modpack/augments + name = "Augmentation Content" diff --git a/mods/content/augments/_augments.dme b/mods/content/augments/_augments.dme new file mode 100644 index 00000000000..ec0fba60a72 --- /dev/null +++ b/mods/content/augments/_augments.dme @@ -0,0 +1,24 @@ +#ifndef CONTENT_PACK_AUGMENTS +#define CONTENT_PACK_AUGMENTS +// BEGIN_INCLUDE +#include "_augments.dm" +#include "active.dm" +#include "augment_loadout.dm" +#include "augment_organ.dm" +#include "bodytype_augment.dm" +#include "designs_augments.dm" +#include "overrides.dm" +#include "simple.dm" +#include "active\armblades.dm" +#include "active\cyberbrain.dm" +#include "active\polytool.dm" +#include "active\tool\engineering.dm" +#include "active\tool\surgical.dm" +#include "passive\armor.dm" +#include "passive\boost.dm" +#include "passive\nanoaura.dm" +#include "passive\boost\muscle.dm" +#include "passive\boost\reflex.dm" +#include "passive\boost\shooting.dm" +// END_INCLUDE +#endif \ No newline at end of file diff --git a/code/modules/augment/active.dm b/mods/content/augments/active.dm similarity index 87% rename from code/modules/augment/active.dm rename to mods/content/augments/active.dm index e338d1e763c..773215a8fa6 100644 --- a/code/modules/augment/active.dm +++ b/mods/content/augments/active.dm @@ -22,3 +22,6 @@ if(. && istype(action)) action.button_icon_state = icon_state action.button?.update_icon() + +/datum/action/item_action/organ/augment + button_icon = 'mods/content/augments/icons/augment.dmi' \ No newline at end of file diff --git a/code/modules/augment/active/armblades.dm b/mods/content/augments/active/armblades.dm similarity index 97% rename from code/modules/augment/active/armblades.dm rename to mods/content/augments/active/armblades.dm index 8e40dc7c43e..38d043f9a32 100644 --- a/code/modules/augment/active/armblades.dm +++ b/mods/content/augments/active/armblades.dm @@ -2,7 +2,7 @@ icon_state = "armblade" item_state = null name = "armblade" - icon = 'icons/obj/augment.dmi' + icon = 'mods/content/augments/icons/augment.dmi' desc = "A handy utility blade for the discerning augmentee. Warranty void if used for cutting." base_parry_chance = 30 sharp = TRUE diff --git a/code/modules/augment/active/cyberbrain.dm b/mods/content/augments/active/cyberbrain.dm similarity index 100% rename from code/modules/augment/active/cyberbrain.dm rename to mods/content/augments/active/cyberbrain.dm diff --git a/code/modules/augment/active/polytool.dm b/mods/content/augments/active/polytool.dm similarity index 100% rename from code/modules/augment/active/polytool.dm rename to mods/content/augments/active/polytool.dm diff --git a/code/modules/augment/active/tool/engineering.dm b/mods/content/augments/active/tool/engineering.dm similarity index 84% rename from code/modules/augment/active/tool/engineering.dm rename to mods/content/augments/active/tool/engineering.dm index 20fec8cfe1a..2aff3eedd2a 100644 --- a/code/modules/augment/active/tool/engineering.dm +++ b/mods/content/augments/active/tool/engineering.dm @@ -19,13 +19,13 @@ /obj/item/weldingtool/finger name = "digital welder" desc = "A precise, high quality welding tool." - icon = 'icons/obj/items/tool/welders/welder_finger.dmi' + icon = 'mods/content/augments/icons/welder_finger.dmi' /obj/item/wirecutters/finger name = "digital splicer" desc = "A small embedded cutter in your finger." icon_state = "wirecutter_finger" - icon = 'icons/obj/augment_tools.dmi' + icon = 'mods/content/augments/icons/augment_tools.dmi' /obj/item/wirecutters/finger/on_update_icon() SHOULD_CALL_PARENT(FALSE) @@ -35,7 +35,7 @@ name = "digital screwdriver" desc = "A nifty power tool at your literal fingertips." icon_state = "screwdriver_finger" - icon = 'icons/obj/augment_tools.dmi' + icon = 'mods/content/augments/icons/augment_tools.dmi' /obj/item/screwdriver/finger/on_update_icon() SHOULD_CALL_PARENT(FALSE) @@ -45,7 +45,7 @@ name = "digital prybar" desc = "A somewhat awkward to use prybar. It doubles as a bottle opener." icon_state = "prybar_finger" - icon = 'icons/obj/augment_tools.dmi' + icon = 'mods/content/augments/icons/augment_tools.dmi' /obj/item/crowbar/finger/on_update_icon() SHOULD_CALL_PARENT(FALSE) @@ -55,7 +55,7 @@ name = "digital wrench" desc = "A rotating wrench. Don't get your hair caught in it." icon_state = "wrench_finger" - icon = 'icons/obj/augment_tools.dmi' + icon = 'mods/content/augments/icons/augment_tools.dmi' /obj/item/wrench/finger/on_update_icon() SHOULD_CALL_PARENT(FALSE) @@ -65,4 +65,4 @@ name = "digital multitool" desc = "A multitool inside of a multitool. Doubletool?" icon_state = "multitool_finger" - icon = 'icons/obj/augment_tools.dmi' + icon = 'mods/content/augments/icons/augment_tools.dmi' diff --git a/code/modules/augment/active/tool/surgical.dm b/mods/content/augments/active/tool/surgical.dm similarity index 100% rename from code/modules/augment/active/tool/surgical.dm rename to mods/content/augments/active/tool/surgical.dm diff --git a/code/modules/client/preference_setup/loadout/lists/augmentations.dm b/mods/content/augments/augment_loadout.dm similarity index 79% rename from code/modules/client/preference_setup/loadout/lists/augmentations.dm rename to mods/content/augments/augment_loadout.dm index e2f387cd6ec..3fd9d8efa98 100644 --- a/code/modules/client/preference_setup/loadout/lists/augmentations.dm +++ b/mods/content/augments/augment_loadout.dm @@ -27,9 +27,14 @@ if(!istype(organ_to_implant_into)) return ..() - if(augment_flags == AUGMENTATION_MECHANIC && !BP_IS_PROSTHETIC(organ_to_implant_into)) - to_chat(user, SPAN_DANGER("Your [organ_to_implant_into.name] is not prosthetic, and therefore \the [src] can not be installed!")) - return ..() + if(BP_IS_PROSTHETIC(organ_to_implant_into)) + if(!(augment_flags & AUGMENTATION_MECHANIC)) + to_chat(user, SPAN_DANGER("Your [organ_to_implant_into.name] is not organic, and therefore \the [src] can not be installed!")) + return ..() + else + if(!(augment_flags & AUGMENTATION_ORGANIC)) + to_chat(user, SPAN_DANGER("Your [organ_to_implant_into.name] is not prosthetic, and therefore \the [src] can not be installed!")) + return ..() user.add_organ(src, organ_to_implant_into) to_chat(user, SPAN_NOTICE("Your [organ_to_implant_into.name] has been replaced with \the [src].")) diff --git a/code/modules/augment/augment.dm b/mods/content/augments/augment_organ.dm similarity index 85% rename from code/modules/augment/augment.dm rename to mods/content/augments/augment_organ.dm index 63105dc6e02..8f097a8874b 100644 --- a/code/modules/augment/augment.dm +++ b/mods/content/augments/augment_organ.dm @@ -1,7 +1,7 @@ /obj/item/organ/internal/augment name = "embedded augment" desc = "An embedded augment." - icon = 'icons/obj/augment.dmi' + icon = 'mods/content/augments/icons/augment.dmi' w_class = ITEM_SIZE_TINY // Need to be tiny to fit inside limbs. //By default these fit on both flesh and robotic organs and are robotic organ_properties = ORGAN_PROP_PROSTHETIC @@ -12,6 +12,8 @@ var/descriptor = "" var/known = TRUE + var/const/AUGMENTATION_MECHANIC = BITFLAG(0) + var/const/AUGMENTATION_ORGANIC = BITFLAG(1) var/augment_flags = AUGMENTATION_MECHANIC | AUGMENTATION_ORGANIC var/list/allowed_organs = list(BP_AUGMENT_R_ARM, BP_AUGMENT_L_ARM) @@ -36,6 +38,14 @@ parent_organ = affected.organ_tag update_parent_organ() +/obj/item/organ/internal/augment/get_attachment_failure_reason(obj/item/organ/external/affected, robotic = FALSE) + if(robotic) + if(!(augment_flags & AUGMENTATION_ORGANIC)) + return SPAN_WARNING("\The [src] cannot function within a non-robotic limb.") + else if(!(augment_flags & AUGMENTATION_MECHANIC)) + return SPAN_WARNING("\The [src] cannot function within a robotic limb.") + return ..() + /obj/item/organ/internal/augment/proc/update_parent_organ() //This tries to match a parent organ to an augment slot //This is intended to match the possible positions to a parent organ diff --git a/mods/content/augments/bodytype_augment.dm b/mods/content/augments/bodytype_augment.dm new file mode 100644 index 00000000000..4fd09ed6a0e --- /dev/null +++ b/mods/content/augments/bodytype_augment.dm @@ -0,0 +1,4 @@ +// Dummy/stub prosthetic type for augment implants. +/decl/bodytype/prosthetic/augment + name = "Augment" + uid = "bodytype_prosthetic_augment" diff --git a/code/modules/fabrication/designs/robotics/designs_augments.dm b/mods/content/augments/designs_augments.dm similarity index 100% rename from code/modules/fabrication/designs/robotics/designs_augments.dm rename to mods/content/augments/designs_augments.dm diff --git a/icons/obj/augment.dmi b/mods/content/augments/icons/augment.dmi similarity index 100% rename from icons/obj/augment.dmi rename to mods/content/augments/icons/augment.dmi diff --git a/icons/obj/augment_tools.dmi b/mods/content/augments/icons/augment_tools.dmi similarity index 100% rename from icons/obj/augment_tools.dmi rename to mods/content/augments/icons/augment_tools.dmi diff --git a/icons/obj/items/tool/welders/welder_finger.dmi b/mods/content/augments/icons/welder_finger.dmi similarity index 100% rename from icons/obj/items/tool/welders/welder_finger.dmi rename to mods/content/augments/icons/welder_finger.dmi diff --git a/mods/content/augments/overrides.dm b/mods/content/augments/overrides.dm new file mode 100644 index 00000000000..296d4c33706 --- /dev/null +++ b/mods/content/augments/overrides.dm @@ -0,0 +1,32 @@ + +/obj/structure/mineral_bath/should_dissolve_implant(obj/implanted_object) + if(istype(implanted_object, /obj/item/organ/internal/augment)) + return FALSE + return ..() + +// Cause arm and hand augments to trigger fault ailments. +/datum/ailment/fault/locking_thumbs/New(obj/item/organ/_organ) + var/static/did_injection = FALSE + if(!did_injection) + did_injection = TRUE + applies_to_organ |= list( + BP_AUGMENT_R_ARM, + BP_AUGMENT_L_ARM, + BP_AUGMENT_R_HAND, + BP_AUGMENT_L_HAND + ) + . = ..() + +/datum/ailment/fault/locking_thumbs/resolve_tag_to_slot(organ_tag) + switch(organ_tag) + if(BP_AUGMENT_L_ARM, BP_AUGMENT_L_HAND) + return BP_L_HAND + if(BP_AUGMENT_R_ARM, BP_AUGMENT_R_HAND) + return BP_R_HAND + return ..() + +// Add augments to scan results +/obj/item/organ/external/get_scan_results() + for(var/obj/item/organ/internal/augment/aug in internal_organs) + if(istype(aug) && aug.known) + . += "[capitalize(aug.name)] implanted" \ No newline at end of file diff --git a/mods/content/augments/passive/armor.dm b/mods/content/augments/passive/armor.dm new file mode 100644 index 00000000000..2dff1139cba --- /dev/null +++ b/mods/content/augments/passive/armor.dm @@ -0,0 +1,26 @@ +/obj/item/organ/internal/augment/armor + name = "subdermal armor" + allowed_organs = list(BP_AUGMENT_CHEST_ARMOUR) + icon_state = "armor-chest" + desc = "A flexible composite mesh designed to prevent tearing and puncturing of underlying tissue." + material = /decl/material/solid/metal/steel + origin_tech = @'{"materials":4,"engineering":2,"biotech":3}' + var/brute_mult = 0.8 + var/burn_mult = 1 + +/obj/item/organ/internal/augment/armor/reset_matter() + matter = list(/decl/material/solid/fiberglass = MATTER_AMOUNT_REINFORCEMENT) + +// override to add armor augment damage mods +/obj/item/organ/external/get_brute_mod(var/damage_flags) + . = ..() + var/obj/item/organ/internal/augment/armor/armor_augment = owner?.get_organ(BP_AUGMENT_CHEST_ARMOUR, /obj/item/organ/internal/augment/armor) + if(armor_augment) + . *= armor_augment.brute_mult + +// override to add armor augment damage mods +/obj/item/organ/external/get_burn_mod(var/damage_flags) + . = ..() + var/obj/item/organ/internal/augment/armor/armor_augment = owner?.get_organ(BP_AUGMENT_CHEST_ARMOUR, /obj/item/organ/internal/augment/armor) + if(armor_augment) + . *= armor_augment.burn_mult \ No newline at end of file diff --git a/code/modules/augment/passive/boost.dm b/mods/content/augments/passive/boost.dm similarity index 100% rename from code/modules/augment/passive/boost.dm rename to mods/content/augments/passive/boost.dm diff --git a/code/modules/augment/passive/boost/muscle.dm b/mods/content/augments/passive/boost/muscle.dm similarity index 100% rename from code/modules/augment/passive/boost/muscle.dm rename to mods/content/augments/passive/boost/muscle.dm diff --git a/code/modules/augment/passive/boost/reflex.dm b/mods/content/augments/passive/boost/reflex.dm similarity index 100% rename from code/modules/augment/passive/boost/reflex.dm rename to mods/content/augments/passive/boost/reflex.dm diff --git a/code/modules/augment/passive/boost/shooting.dm b/mods/content/augments/passive/boost/shooting.dm similarity index 100% rename from code/modules/augment/passive/boost/shooting.dm rename to mods/content/augments/passive/boost/shooting.dm diff --git a/code/modules/augment/passive/nanoaura.dm b/mods/content/augments/passive/nanoaura.dm similarity index 58% rename from code/modules/augment/passive/nanoaura.dm rename to mods/content/augments/passive/nanoaura.dm index 751ed5541ab..e22f8331cd6 100644 --- a/code/modules/augment/passive/nanoaura.dm +++ b/mods/content/augments/passive/nanoaura.dm @@ -1,3 +1,4 @@ +//This handy augment protects you to a degree, keeping it online after critical damage however is bad /obj/item/organ/internal/augment/active/nanounit name = "nanite MCU" allowed_organs = list(BP_AUGMENT_CHEST_ACTIVE) @@ -55,3 +56,38 @@ if(owner && modifier_archetype) owner.remove_mob_modifier(modifier_archetype, source = src) . = ..() + +// The modifier applied by the above implant. +/decl/mob_modifier/nanoswarm + name = "Defensive Nanoswarm" + desc = "You are surrounded by nanomachines that harden in response to projectiles." + hud_icon_state = "nanomachines" + on_add_message_1p = SPAN_NOTICE("Your skin tingles as the nanites spread over your body.") + on_end_message_1p = SPAN_WARNING("The nanites dissolve!") + +/decl/mob_modifier/nanoswarm/on_modifier_datum_added(mob/living/_owner, decl/mob_modifier/modifier) + . = ..() + playsound(_owner.loc,'sound/weapons/flash.ogg',35,1) + +/decl/mob_modifier/nanoswarm/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + if(attack_type != MM_ATTACK_TYPE_PROJECTILE) + return ..() + + var/obj/item/organ/internal/augment/active/nanounit/unit + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/organ/internal/augment/active/nanounit/implant = modifier.source?.resolve() + if(istype(implant) && implant.active && implant.charges >= 0) // active with 0 charges means it's about to critically fail. + unit = implant + break + + if(!istype(unit)) + return ..() + + _owner.visible_message(SPAN_WARNING("The nanomachines harden as a response to physical trauma!")) + playsound(_owner, 'sound/effects/basscannon.ogg',35,1) + unit.charges-- + if(unit.charges <= 0) + to_chat(_owner, SPAN_DANGER("Warning: Critical damage threshold passed. Shut down unit to avoid further damage.")) + else + unit.catastrophic_failure() + return MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED diff --git a/code/modules/augment/simple.dm b/mods/content/augments/simple.dm similarity index 100% rename from code/modules/augment/simple.dm rename to mods/content/augments/simple.dm diff --git a/mods/content/integrated_electronics/_integrated_electronics.dme b/mods/content/integrated_electronics/_integrated_electronics.dme index 7a5c2529036..725bb52ed49 100644 --- a/mods/content/integrated_electronics/_integrated_electronics.dme +++ b/mods/content/integrated_electronics/_integrated_electronics.dme @@ -10,7 +10,6 @@ #include "random.dm" #include "toggle_circuits_secret.dm" #include "assemblies\_assemblies.dm" -#include "assemblies\circuit_augment.dm" #include "components\_integrated_circuit.dm" #include "components\access.dm" #include "components\arithmetic.dm" diff --git a/mods/content/integrated_electronics/fabricator_designs.dm b/mods/content/integrated_electronics/fabricator_designs.dm index 2018e9d5bae..0b6dc3289f5 100644 --- a/mods/content/integrated_electronics/fabricator_designs.dm +++ b/mods/content/integrated_electronics/fabricator_designs.dm @@ -15,6 +15,3 @@ /datum/fabricator_recipe/protolathe/integrated_printer_upgrade_clone path = /obj/item/disk/integrated_circuit/upgrade/clone - -/datum/fabricator_recipe/robotics/augment/circuit - path = /obj/item/organ/internal/augment/active/simple/circuit diff --git a/mods/~compatibility/patches/circuits.dm b/mods/~compatibility/patches/circuits.dm index 457c3b4f855..afa15ae3f36 100644 --- a/mods/~compatibility/patches/circuits.dm +++ b/mods/~compatibility/patches/circuits.dm @@ -5,4 +5,8 @@ // Add circuit items to dungeon loot. #ifdef MODPACK_DUNGEON_LOOT #include "circuits/loot_circuits.dm" +#endif +// Add augment assembly for circuits. +#ifdef CONTENT_PACK_AUGMENTS +#include "circuits/augment_circuits.dm" #endif \ No newline at end of file diff --git a/mods/content/integrated_electronics/assemblies/circuit_augment.dm b/mods/~compatibility/patches/circuits/augment_circuits.dm similarity index 90% rename from mods/content/integrated_electronics/assemblies/circuit_augment.dm rename to mods/~compatibility/patches/circuits/augment_circuits.dm index cc3b522aa6e..842d89dad23 100644 --- a/mods/content/integrated_electronics/assemblies/circuit_augment.dm +++ b/mods/~compatibility/patches/circuits/augment_circuits.dm @@ -35,4 +35,8 @@ holding.canremove = 0 playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) return TRUE - return ..() \ No newline at end of file + return ..() + +// And add a fabricator design +/datum/fabricator_recipe/robotics/augment/circuit + path = /obj/item/organ/internal/augment/active/simple/circuit \ No newline at end of file diff --git a/nebula.dme b/nebula.dme index abb0ae344ea..7a8e35932e6 100644 --- a/nebula.dme +++ b/nebula.dme @@ -1779,20 +1779,6 @@ #include "code\modules\atmospherics\components\unary\unary_base.dm" #include "code\modules\atmospherics\components\unary\vent_pump.dm" #include "code\modules\atmospherics\components\unary\vent_scrubber.dm" -#include "code\modules\augment\active.dm" -#include "code\modules\augment\augment.dm" -#include "code\modules\augment\simple.dm" -#include "code\modules\augment\active\armblades.dm" -#include "code\modules\augment\active\cyberbrain.dm" -#include "code\modules\augment\active\polytool.dm" -#include "code\modules\augment\active\tool\engineering.dm" -#include "code\modules\augment\active\tool\surgical.dm" -#include "code\modules\augment\passive\armor.dm" -#include "code\modules\augment\passive\boost.dm" -#include "code\modules\augment\passive\nanoaura.dm" -#include "code\modules\augment\passive\boost\muscle.dm" -#include "code\modules\augment\passive\boost\reflex.dm" -#include "code\modules\augment\passive\boost\shooting.dm" #include "code\modules\backgrounds\_background.dm" #include "code\modules\backgrounds\background_categories.dm" #include "code\modules\backgrounds\citizenship\_citizenship.dm" @@ -1898,11 +1884,9 @@ #include "code\modules\client\preference_setup\global\05_settings.dm" #include "code\modules\client\preference_setup\global\preferences.dm" #include "code\modules\client\preference_setup\global\prefixes.dm" -#include "code\modules\client\preference_setup\loadout\_defines.dm" #include "code\modules\client\preference_setup\loadout\gear_tweaks.dm" #include "code\modules\client\preference_setup\loadout\loadout.dm" #include "code\modules\client\preference_setup\loadout\lists\accessories.dm" -#include "code\modules\client\preference_setup\loadout\lists\augmentations.dm" #include "code\modules\client\preference_setup\loadout\lists\clothing.dm" #include "code\modules\client\preference_setup\loadout\lists\earwear.dm" #include "code\modules\client\preference_setup\loadout\lists\eyegear.dm" @@ -2402,7 +2386,6 @@ #include "code\modules\fabrication\designs\protolathe\designs_weapons.dm" #include "code\modules\fabrication\designs\replicator\designs_food.dm" #include "code\modules\fabrication\designs\robotics\_designs_robotics.dm" -#include "code\modules\fabrication\designs\robotics\designs_augments.dm" #include "code\modules\fabrication\designs\robotics\designs_misc.dm" #include "code\modules\fabrication\designs\robotics\designs_organs.dm" #include "code\modules\fabrication\designs\robotics\designs_prosthetics.dm" @@ -3111,7 +3094,6 @@ #include "code\modules\mob_modifiers\definitions\modifiers_cloaked.dm" #include "code\modules\mob_modifiers\definitions\modifiers_light.dm" #include "code\modules\mob_modifiers\definitions\modifiers_mech_shields.dm" -#include "code\modules\mob_modifiers\definitions\modifiers_nanoswarm.dm" #include "code\modules\mob_modifiers\definitions\modifiers_object.dm" #include "code\modules\mob_modifiers\definitions\modifiers_prone.dm" #include "code\modules\mob_modifiers\definitions\modifiers_regeneration.dm" From e563b3ffe5313b18a3a7edb4602fe87f8ba4a6c1 Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sat, 20 Dec 2025 22:15:25 -0500 Subject: [PATCH 007/149] Make power debug objects not use the power subtype --- code/modules/power/debug_items.dm | 30 ++++++++++--------- code/modules/power/power.dm | 2 ++ maps/example/example-1.dmm | 2 +- maps/example/example-2.dmm | 2 +- maps/example/example-3.dmm | 2 +- mods/species/ascent/machines/ship_machines.dm | 12 ++++---- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/code/modules/power/debug_items.dm b/code/modules/power/debug_items.dm index dcb428ebdf8..35a6efc1207 100644 --- a/code/modules/power/debug_items.dm +++ b/code/modules/power/debug_items.dm @@ -1,17 +1,18 @@ -/obj/machinery/power/debug_items - abstract_type = /obj/machinery/power/debug_items +/obj/machinery/debug_items + abstract_type = /obj/machinery/debug_items icon = 'icons/obj/power.dmi' icon_state = "tracker" anchored = TRUE density = TRUE var/show_extended_information = 1 // Set to 0 to disable extra information on examining (for example, when used on admin events) -/obj/machinery/power/debug_items/examined_by(mob/user) +/obj/machinery/debug_items/examined_by(mob/user) . = ..() if(show_extended_information) show_info(user) -/obj/machinery/power/debug_items/proc/show_info(var/mob/user) +/obj/machinery/debug_items/proc/show_info(var/mob/user) + var/datum/powernet/powernet = get_powernet() if(!powernet) to_chat(user, "This device is not connected to a powernet.") return @@ -25,42 +26,43 @@ // An infinite power generator. Adds energy to connected cable. -/obj/machinery/power/debug_items/infinite_generator +/obj/machinery/debug_items/infinite_generator name = "Fractal Energy Reactor" desc = "An experimental power generator" var/power_generation_rate = 1000000 -/obj/machinery/power/debug_items/infinite_generator/Process() - add_avail(power_generation_rate) +/obj/machinery/debug_items/infinite_generator/Process() + generate_power(power_generation_rate) -/obj/machinery/power/debug_items/infinite_generator/show_info(var/mob/user) +/obj/machinery/debug_items/infinite_generator/show_info(var/mob/user) ..() to_chat(user, "Generator is providing [num2text(power_generation_rate, 20)] W") // A cable powersink, without the explosion/network alarms normal powersink causes. -/obj/machinery/power/debug_items/infinite_cable_powersink +/obj/machinery/debug_items/infinite_cable_powersink name = "Null Point Core" desc = "An experimental device that disperses energy, used for grid testing purposes." var/power_usage_rate = 0 var/last_used = 0 -/obj/machinery/power/debug_items/infinite_cable_powersink/Process() - last_used = draw_power(power_usage_rate) +/obj/machinery/debug_items/infinite_cable_powersink/Process() + var/datum/powernet/powernet = get_powernet() + last_used = powernet.draw_power(power_usage_rate) -/obj/machinery/power/debug_items/infinite_cable_powersink/show_info(var/mob/user) +/obj/machinery/debug_items/infinite_cable_powersink/show_info(var/mob/user) ..() to_chat(user, "Power sink is demanding [num2text(power_usage_rate, 20)] W") to_chat(user, "[num2text(last_used, 20)] W was actually used last tick") -/obj/machinery/power/debug_items/infinite_apc_powersink +/obj/machinery/debug_items/infinite_apc_powersink name = "APC Dummy Load" desc = "A dummy load that connects to an APC, used for load testing purposes." use_power = POWER_USE_ACTIVE active_power_usage = 0 -/obj/machinery/power/debug_items/infinite_apc_powersink/show_info(var/mob/user) +/obj/machinery/debug_items/infinite_apc_powersink/show_info(var/mob/user) ..() to_chat(user, "Dummy load is using [num2text(active_power_usage, 20)] W") to_chat(user, "Powered: [!(stat & NOPOWER) ? "YES" : "NO"]") diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index ff6d5274e98..8cf99bdbeb2 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -2,6 +2,8 @@ // POWER MACHINERY BASE CLASS // This subtype is for machinery which needs to be directly referenced by its parent powernet during powernet processing. // This subtype does not encompass all power generating machinery, or machinery that needs to draw from a powernet in general. +// If you try using this, make sure you can't just use get_powernet() instead. Ideally either the powernet needs to know about it (APCs) +// or we need to run logic when we connect or disconnect from a powernet (solar panels/trackers). ////////////////////////////// ///////////////////////////// diff --git a/maps/example/example-1.dmm b/maps/example/example-1.dmm index 129c5b08e97..500a16664c7 100644 --- a/maps/example/example-1.dmm +++ b/maps/example/example-1.dmm @@ -334,7 +334,7 @@ /turf/floor/tiled/dark/monotile, /area/example/first) "qR" = ( -/obj/machinery/power/debug_items/infinite_generator, +/obj/machinery/debug_items/infinite_generator, /obj/structure/cable/yellow, /turf/floor, /area/example/first) diff --git a/maps/example/example-2.dmm b/maps/example/example-2.dmm index f1bf69ddda7..51b091fc0d0 100644 --- a/maps/example/example-2.dmm +++ b/maps/example/example-2.dmm @@ -436,7 +436,7 @@ /turf/floor/tiled/steel_grid, /area/example/second) "Ci" = ( -/obj/machinery/power/debug_items/infinite_generator, +/obj/machinery/debug_items/infinite_generator, /obj/structure/cable/yellow, /turf/floor/tiled/white, /area/example/second) diff --git a/maps/example/example-3.dmm b/maps/example/example-3.dmm index 7dda2d9ff4c..018cb124270 100644 --- a/maps/example/example-3.dmm +++ b/maps/example/example-3.dmm @@ -198,7 +198,7 @@ /turf/floor/tiled/steel_grid, /area/example/third) "GA" = ( -/obj/machinery/power/debug_items/infinite_generator, +/obj/machinery/debug_items/infinite_generator, /obj/structure/cable/yellow{ icon_state = "0-2" }, diff --git a/mods/species/ascent/machines/ship_machines.dm b/mods/species/ascent/machines/ship_machines.dm index 44746798706..b761299d513 100644 --- a/mods/species/ascent/machines/ship_machines.dm +++ b/mods/species/ascent/machines/ship_machines.dm @@ -149,7 +149,7 @@ MANTIDIFY(/obj/item/chems/chem_disp_cartridge, "canister", "chemical storage") // This is an absolutely stupid machine. Basically the same as the debug one with some alterations. // It is a placeholder for a proper reactor setup (probably a RUST descendant) -/obj/machinery/power/ascent_reactor +/obj/machinery/ascent_reactor name = "mantid fusion stack" desc = "A tall, gleaming assemblage of advanced alien machinery. It hums and crackles with restrained power." icon = 'icons/obj/machines/power/fusion_core.dmi' @@ -159,7 +159,7 @@ MANTIDIFY(/obj/item/chems/chem_disp_cartridge, "canister", "chemical storage") var/output_power = 9000 KILOWATTS var/image/field_image -/obj/machinery/power/ascent_reactor/attack_hand(mob/user) +/obj/machinery/ascent_reactor/attack_hand(mob/user) if(!user.check_dexterity(DEXTERITY_COMPLEX_TOOLS, TRUE)) return ..() if(ishuman(user)) @@ -175,7 +175,7 @@ MANTIDIFY(/obj/item/chems/chem_disp_cartridge, "canister", "chemical storage") update_icon() return TRUE -/obj/machinery/power/ascent_reactor/on_update_icon() +/obj/machinery/ascent_reactor/on_update_icon() . = ..() if(!field_image) @@ -198,13 +198,13 @@ MANTIDIFY(/obj/item/chems/chem_disp_cartridge, "canister", "chemical storage") set_light(0) icon_state = "core0" -/obj/machinery/power/ascent_reactor/Initialize() +/obj/machinery/ascent_reactor/Initialize() . = ..() update_icon() -/obj/machinery/power/ascent_reactor/Process() +/obj/machinery/ascent_reactor/Process() if(on) - add_avail(output_power) + generate_power(output_power) /obj/machinery/power/smes/buildable/power_shuttle/ascent name = "mantid battery" From fcf694b6c216e25415fcf9eda77a1f714f72ec19 Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sat, 20 Dec 2025 20:18:56 -0500 Subject: [PATCH 008/149] Clean up cable/power helper procs --- code/modules/power/cable.dm | 16 ++++++++-------- code/modules/power/power.dm | 33 ++++++++++----------------------- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index b18e5bd1681..4db55490556 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -418,9 +418,9 @@ var/global/list/obj/structure/cable/all_cables = list() . += C if(cable_dir & (cable_dir - 1)) // Diagonal, check for /\/\/\ style cables along cardinal directions for(var/pair in list(NORTH|SOUTH, EAST|WEST)) - T = get_step_resolving_mimic(src, cable_dir & pair) + T = get_step_resolving_mimic(src, cable_dir & pair) // move either vertically or horizontally if(T) - var/req_dir = cable_dir ^ pair + var/req_dir = cable_dir ^ pair // flip along the direction we moved, so if we're NORTHEAST we want a cable to our east that's NORTHWEST for(var/obj/structure/cable/C in T) if(C.d1 == req_dir || C.d2 == req_dir) . += C @@ -452,10 +452,10 @@ var/global/list/obj/structure/cable/all_cables = list() var/turf/T1 = loc if(!T1) return - var/list/powerlist = power_list(T1,src,0,0) //find the other cables that ended in the centre of the turf, with or without a powernet - if(powerlist.len>0) + var/list/cablelist = cable_list(T1, src, 0) //find the other cables that ended in the centre of the turf, with or without a powernet + if(length(cablelist)) var/datum/powernet/PN = new() - propagate_network(powerlist[1],PN) //propagates the new powernet beginning at the source cable + propagate_network(cablelist[1],PN) //propagates the new powernet beginning at the source cable if(PN.is_empty()) //can happen with machines made nodeless when smoothing cables qdel(PN) @@ -467,12 +467,12 @@ var/global/list/obj/structure/cable/all_cables = list() if(!T1) return if(d1) T1 = get_zstep_resolving_mimic(T1, d1) - P_list = power_list(T1, src, turn(d1,180),0,cable_only = 1) // what adjacently joins on to cut cable... + P_list = cable_list(T1, src, d1) // what adjacently joins on to cut cable... - P_list += power_list(loc, src, d1, 0, cable_only = 1)//... and on turf + P_list += cable_list(loc, src, d1)//... and on turf - if(P_list.len == 0)//if nothing in both list, then the cable was a lone cable, just delete it and its powernet + if(!length(P_list))//if nothing in both list, then the cable was a lone cable, just delete it and its powernet powernet.remove_cable(src) for(var/obj/machinery/power/P in T1)//check if it was powering a machine diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index ff6d5274e98..ebae7df01a3 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -100,30 +100,17 @@ // GLOBAL PROCS for powernets handling ////////////////////////////////////////// - -// returns a list of all power-related objects (nodes, cable, junctions) in turf, -// excluding source, that match the direction d -// if unmarked==1, only return those with no powernet -/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0, var/cable_only = 0) +/// Returns all cables in target_turf matching target_direction, excluding excluded_cable. +/// If only_no_powernet is TRUE, only cables with no powernet will be returned. +/proc/cable_list(var/turf/target_turf, var/obj/structure/cable/excluded_cable = null, var/target_direction, only_no_powernet = FALSE) . = list() - - var/reverse = d ? global.reverse_dir[d] : 0 - for(var/AM in T) - if(AM == source) continue //we don't want to return source - - if(!cable_only && istype(AM,/obj/machinery/power)) - var/obj/machinery/power/P = AM - if(!unmarked || !P.powernet) //if unmarked=1 we only return things with no powernet - if(d == 0) - . += P - - else if(istype(AM,/obj/structure/cable)) - var/obj/structure/cable/C = AM - - if(!unmarked || !C.powernet) - if(C.d1 == d || C.d2 == d || C.d1 == reverse || C.d2 == reverse ) - . += C - return . + var/reverse_direction = target_direction ? global.reverse_dir[target_direction] : 0 + for(var/obj/structure/cable/other_cable in target_turf) + if(other_cable == excluded_cable) + continue + if(!only_no_powernet || !other_cable.powernet) + if(other_cable.d1 == target_direction || other_cable.d2 == target_direction || other_cable.d1 == reverse_direction || other_cable.d2 == reverse_direction) + . += other_cable //remove the old powernet and replace it with a new one throughout the network. /proc/propagate_network(var/obj/structure/cable/cable, var/datum/powernet/PN) From 9936c12c095d9de2d826a695b8a01b5b8c24ffcf Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sat, 20 Dec 2025 20:49:18 -0500 Subject: [PATCH 009/149] Clean up length checks in powernet code --- code/modules/admin/verbs/atmosdebug.dm | 12 ++++++------ code/modules/power/powernet.dm | 7 +++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm index 19916f831e9..2c7947e4a9b 100644 --- a/code/modules/admin/verbs/atmosdebug.dm +++ b/code/modules/admin/verbs/atmosdebug.dm @@ -7,14 +7,14 @@ SSstatistics.add_field_details("admin_verb","CPOW") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! for (var/datum/powernet/PN in SSmachines.powernets) - if (!PN.nodes || !PN.nodes.len) + if (!LAZYLEN(PN.nodes)) if(PN.cables && (PN.cables.len > 1)) var/obj/structure/cable/C = PN.cables[1] var/area/A = get_area(C.loc) to_chat(usr, "Powernet with no nodes! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [A?.proper_name]") - if (!PN.cables || (PN.cables.len < 10)) - if(PN.cables && (PN.cables.len > 1)) - var/obj/structure/cable/C = PN.cables[1] - var/area/A = get_area(C.loc) - to_chat(usr, "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [A?.proper_name]") + var/cable_count = LAZYLEN(PN.cables) + if (cable_count > 1 && cable_count < 10) + var/obj/structure/cable/C = PN.cables[1] + var/area/A = get_area(C.loc) + to_chat(usr, "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [A?.proper_name]") diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm index 6220dc117d2..6727118ba2f 100644 --- a/code/modules/power/powernet.dm +++ b/code/modules/power/powernet.dm @@ -101,10 +101,9 @@ if(problem > 0) problem = max(problem - 1, 0) - if(LAZYLEN(nodes)) // Added to fix a bad list bug -- TLE - for(var/obj/machinery/power/terminal/term in nodes) - if( istype( term.master_machine(), /obj/machinery/apc ) ) - numapc++ + for(var/obj/machinery/power/terminal/term in nodes) + if( istype( term.master_machine(), /obj/machinery/apc ) ) + numapc++ netexcess = avail - load From bfbca927d7c478cf39bd1b5297e6db29e394355a Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sat, 20 Dec 2025 22:33:51 -0500 Subject: [PATCH 010/149] Avoid unnecessary list allocation in powernet code --- code/modules/power/cable.dm | 18 +++++++++--------- code/modules/power/power.dm | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 4db55490556..c1ad6452b56 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -452,10 +452,10 @@ var/global/list/obj/structure/cable/all_cables = list() var/turf/T1 = loc if(!T1) return - var/list/cablelist = cable_list(T1, src, 0) //find the other cables that ended in the centre of the turf, with or without a powernet - if(length(cablelist)) + var/obj/structure/cable/other_cable = get_matching_cable(T1, src, 0) // find a cable to start a replacement network from, if it exists + if(other_cable) var/datum/powernet/PN = new() - propagate_network(cablelist[1],PN) //propagates the new powernet beginning at the source cable + propagate_network(other_cable,PN) //propagates the new powernet beginning at the source cable if(PN.is_empty()) //can happen with machines made nodeless when smoothing cables qdel(PN) @@ -463,16 +463,16 @@ var/global/list/obj/structure/cable/all_cables = list() // cut the cable's powernet at this cable and updates the powergrid /obj/structure/cable/proc/cut_cable_from_powernet() var/turf/T1 = loc - var/list/P_list + var/obj/structure/cable/other_cable if(!T1) return if(d1) T1 = get_zstep_resolving_mimic(T1, d1) - P_list = cable_list(T1, src, d1) // what adjacently joins on to cut cable... + other_cable = get_matching_cable(T1, src, d1) // check our adjacent turf for connecting cables first + if(!other_cable) + other_cable = get_matching_cable(loc, src, d1) // and fall back to our own turf if we don't find one - P_list += cable_list(loc, src, d1)//... and on turf - - if(!length(P_list))//if nothing in both list, then the cable was a lone cable, just delete it and its powernet + if(!other_cable) // if we didn't find another cable, then the cable was a lone cable, just delete it and its powernet powernet.remove_cable(src) for(var/obj/machinery/power/P in T1)//check if it was powering a machine @@ -485,7 +485,7 @@ var/global/list/obj/structure/cable/all_cables = list() powernet.remove_cable(src) //remove the cut cable from its powernet var/datum/powernet/newPN = new()// creates a new powernet... - propagate_network(P_list[1], newPN)//... and propagates it to the other side of the cable + propagate_network(other_cable, newPN)//... and propagates it to the other side of the cable // Disconnect machines connected to nodes if(d1 == 0) // if we cut a node (O-X) cable diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index ebae7df01a3..43fcffe4c68 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -102,15 +102,24 @@ /// Returns all cables in target_turf matching target_direction, excluding excluded_cable. /// If only_no_powernet is TRUE, only cables with no powernet will be returned. -/proc/cable_list(var/turf/target_turf, var/obj/structure/cable/excluded_cable = null, var/target_direction, only_no_powernet = FALSE) +/// Unused, because get_maching_cable or get_connected_cables is usually preferable, but kept just in case. +/proc/cable_list(var/turf/target_turf, var/obj/structure/cable/excluded_cable = null, var/target_direction) . = list() var/reverse_direction = target_direction ? global.reverse_dir[target_direction] : 0 for(var/obj/structure/cable/other_cable in target_turf) if(other_cable == excluded_cable) continue - if(!only_no_powernet || !other_cable.powernet) - if(other_cable.d1 == target_direction || other_cable.d2 == target_direction || other_cable.d1 == reverse_direction || other_cable.d2 == reverse_direction) - . += other_cable + if(other_cable.d1 == target_direction || other_cable.d2 == target_direction || other_cable.d1 == reverse_direction || other_cable.d2 == reverse_direction) + . += other_cable + +/// Like cable_list, but only returns the first cable, since that's all most uses of it check. +/proc/get_matching_cable(var/turf/target_turf, var/obj/structure/cable/excluded_cable = null, var/target_direction) + var/reverse_direction = target_direction ? global.reverse_dir[target_direction] : 0 + for(var/obj/structure/cable/other_cable in target_turf) + if(other_cable == excluded_cable) + continue + if(other_cable.d1 == target_direction || other_cable.d2 == target_direction || other_cable.d1 == reverse_direction || other_cable.d2 == reverse_direction) + return other_cable //remove the old powernet and replace it with a new one throughout the network. /proc/propagate_network(var/obj/structure/cable/cable, var/datum/powernet/PN) From aad616bcadc1f06a90a6c56ba40f0697364facfb Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Tue, 21 Jan 2025 12:29:58 -0500 Subject: [PATCH 011/149] Add support for saltwater turfs --- code/controllers/subsystems/fluids.dm | 5 +++- code/game/turfs/floors/_floor.dm | 9 +++++-- .../turfs/floors/subtypes/floor_concrete.dm | 4 ++++ .../turfs/floors/subtypes/floor_natural.dm | 24 +++++++++++++++++++ code/game/turfs/open/_open.dm | 5 ++++ code/game/turfs/turf.dm | 8 +++++++ code/game/turfs/unsimulated/mask.dm | 5 ++++ code/game/turfs/walls/wall_natural.dm | 4 ++++ code/modules/fluids/fluid_flood.dm | 2 ++ code/modules/multiz/turf_mimic_edge.dm | 4 ++++ code/modules/reagents/Chemistry-Holder.dm | 10 ++++++++ 11 files changed, 77 insertions(+), 3 deletions(-) diff --git a/code/controllers/subsystems/fluids.dm b/code/controllers/subsystems/fluids.dm index b05b4ed11f8..e0248091c4e 100644 --- a/code/controllers/subsystems/fluids.dm +++ b/code/controllers/subsystems/fluids.dm @@ -71,7 +71,10 @@ SUBSYSTEM_DEF(fluids) continue checked_targets[neighbor] = TRUE flooded_a_neighbor = TRUE - neighbor.add_to_reagents(current_fluid_holder.flooded, FLUID_MAX_DEPTH) + if(current_fluid_holder.contaminant_reagent_type && current_fluid_holder.contaminant_proportion) + neighbor.add_to_reagents_contaminated(current_fluid_holder.flooded, FLUID_MAX_DEPTH, contaminant_type = current_fluid_holder.contaminant_reagent_type, contaminant_proportion = current_fluid_holder.contaminant_proportion) + else + neighbor.add_to_reagents(current_fluid_holder.flooded, FLUID_MAX_DEPTH) if(!flooded_a_neighbor) REMOVE_ACTIVE_FLUID_SOURCE(current_fluid_holder) diff --git a/code/game/turfs/floors/_floor.dm b/code/game/turfs/floors/_floor.dm index 3982c3dab82..515dcaca81d 100644 --- a/code/game/turfs/floors/_floor.dm +++ b/code/game/turfs/floors/_floor.dm @@ -11,7 +11,7 @@ zone_membership_candidate = TRUE open_turf_type = /turf/open/airless - // Reagent to use to fill the turf. + /// Reagent to use to refill trenches to capacity automatically. var/fill_reagent_type var/can_engrave = TRUE @@ -69,7 +69,12 @@ var/my_height = get_physical_height() if(fill_reagent_type && my_height < 0 && (!reagents || !QDELING(reagents)) && REAGENT_TOTAL_VOLUME(reagents) < abs(my_height)) var/reagents_to_add = abs(my_height) - REAGENT_TOTAL_VOLUME(reagents) - add_to_reagents(fill_reagent_type, reagents_to_add, phase = MAT_PHASE_LIQUID) + var/contaminant_to_add = 0 + if(contaminant_reagent_type) + contaminant_to_add = CHEMS_QUANTIZE(reagents_to_add * contaminant_proportion) + add_to_reagents(fill_reagent_type, reagents_to_add - contaminant_to_add, phase = MAT_PHASE_LIQUID, defer_update = !!contaminant_to_add) + if(contaminant_to_add) + add_to_reagents(contaminant_reagent_type, contaminant_to_add, phase = MAT_PHASE_LIQUID) /turf/floor/can_climb_from_below(var/mob/climber) return TRUE diff --git a/code/game/turfs/floors/subtypes/floor_concrete.dm b/code/game/turfs/floors/subtypes/floor_concrete.dm index 60303ef1ee7..f52e6614450 100644 --- a/code/game/turfs/floors/subtypes/floor_concrete.dm +++ b/code/game/turfs/floors/subtypes/floor_concrete.dm @@ -13,6 +13,10 @@ flooded = /decl/material/liquid/water color = COLOR_LIQUID_WATER +/turf/floor/concrete/flooded/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water, NOT 10% salt + /turf/floor/concrete/reinforced name = "reinforced concrete" icon_state = "hexacrete" diff --git a/code/game/turfs/floors/subtypes/floor_natural.dm b/code/game/turfs/floors/subtypes/floor_natural.dm index ae735053580..43d7b34ac45 100644 --- a/code/game/turfs/floors/subtypes/floor_natural.dm +++ b/code/game/turfs/floors/subtypes/floor_natural.dm @@ -85,13 +85,25 @@ height = -(FLUID_SHALLOW) fill_reagent_type = /decl/material/liquid/water +/turf/floor/mud/water/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water, NOT 10% salt + /turf/floor/mud/water/deep color = COLOR_BLUE height = -(FLUID_DEEP) +/turf/floor/mud/water/deep/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water + /turf/floor/mud/flooded flooded = /decl/material/liquid/water +/turf/floor/mud/flooded/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water + /turf/floor/dry name = "dry mud" icon = 'icons/turf/flooring/seafloor.dmi' @@ -117,10 +129,18 @@ height = -(FLUID_SHALLOW) fill_reagent_type = /decl/material/liquid/water +/turf/floor/rock/sand/water/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water + /turf/floor/rock/sand/water/deep color = COLOR_BLUE height = -(FLUID_DEEP) +/turf/floor/rock/sand/water/deep/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water + /turf/floor/seafloor name = "sea floor" icon = 'icons/turf/flooring/seafloor.dmi' @@ -131,6 +151,10 @@ flooded = /decl/material/liquid/water color = COLOR_LIQUID_WATER +/turf/floor/seafloor/flooded/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water + /turf/floor/shrouded name = "packed sand" icon = 'icons/turf/flooring/shrouded.dmi' diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index abbcfecc695..186c84cb264 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -27,6 +27,11 @@ name = "open water" flooded = /decl/material/liquid/water +/turf/open/flooded/salt + name = "open saltwater" // alt. ver: open ocean? + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water, NOT 10% salt + /turf/open/Entered(var/atom/movable/mover, var/atom/oldloc) ..() mover.fall(oldloc) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 33828543cd5..fdc9684e137 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -38,6 +38,14 @@ var/footstep_type var/open_turf_type = /turf/open // Which open turf type to use by default above this turf in a multiz context. Overridden by area. + // If you ever need to refill or flood a turf with more than two reagents, this should be rewritten entirely. + // The reason it's written like this is to avoid creating a new list for every turf with contaminants + // and that should still hold up even if you have turfs with three or more liquids in the mixture. + /// Reagent to contaminate refilled or flooded reagents. + var/contaminant_reagent_type + /// What fraction of the refilled/flooded liquid should be the contaminant? If zero, no contaminant is added. + var/contaminant_proportion + var/tmp/changing_turf var/tmp/prev_type // Previous type of the turf, prior to turf translation. diff --git a/code/game/turfs/unsimulated/mask.dm b/code/game/turfs/unsimulated/mask.dm index 1b82356696e..a380cfa054d 100644 --- a/code/game/turfs/unsimulated/mask.dm +++ b/code/game/turfs/unsimulated/mask.dm @@ -9,6 +9,11 @@ icon_state = "rockvault" color = COLOR_SILVER +// Why do these exist? Are they just for typechecks when generating random maps? Does the flooding code even run for unsim turfs? /turf/unsimulated/mask/flooded flooded = /decl/material/liquid/water color = COLOR_LIQUID_WATER + +/turf/unsimulated/mask/flooded/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water, NOT 10% salt \ No newline at end of file diff --git a/code/game/turfs/walls/wall_natural.dm b/code/game/turfs/walls/wall_natural.dm index 4710e89e562..8b8fdab5908 100644 --- a/code/game/turfs/walls/wall_natural.dm +++ b/code/game/turfs/walls/wall_natural.dm @@ -20,6 +20,10 @@ var/global/_wall_chisel_skill = SKILL_CONSTRUCTION flooded = /decl/material/liquid/water color = COLOR_LIQUID_WATER +/turf/wall/natural/flooded/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water, NOT 10% salt + /turf/wall/natural/get_paint_examine_message() return SPAN_NOTICE("It has been noticeably discoloured by the elements.") diff --git a/code/modules/fluids/fluid_flood.dm b/code/modules/fluids/fluid_flood.dm index 47a48f0f5e9..7b3f2a33384 100644 --- a/code/modules/fluids/fluid_flood.dm +++ b/code/modules/fluids/fluid_flood.dm @@ -1,5 +1,7 @@ // Permaflood overlay. var/global/list/flood_type_overlay_cache = list() +// TODO: does this need to also take contaminant type as an argument? flooding contaminants are totally untested +// also, do flooded turfs even apply fluid_act and touch effects? /proc/get_flood_overlay(fluid_type) if(!ispath(fluid_type, /decl/material)) return null diff --git a/code/modules/multiz/turf_mimic_edge.dm b/code/modules/multiz/turf_mimic_edge.dm index df31a9f6bdf..512b1f7fd62 100644 --- a/code/modules/multiz/turf_mimic_edge.dm +++ b/code/modules/multiz/turf_mimic_edge.dm @@ -208,6 +208,10 @@ /turf/mimic_edge/transition/flooded flooded = /decl/material/liquid/water +/turf/mimic_edge/transition/flooded/salt + contaminant_reagent_type = /decl/material/solid/sodiumchloride + contaminant_proportion = 0.10 // 1:10 salt:water, NOT 10% salt + //////////////////////////////// // Loop Edges //////////////////////////////// diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 629091fd109..a9c135a0b29 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -10,6 +10,16 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new /atom/proc/remove_any_reagents(amount = 1, defer_update = FALSE, removed_phases = (MAT_PHASE_LIQUID | MAT_PHASE_SOLID), skip_reagents = null) return reagents?.remove_any(amount, defer_update, removed_phases, skip_reagents) +/// Adds reagents, but contaminated. A fraction of `amount` is replaced with `contaminant_type` according to `contaminant_proportion`. +/// Handles null contaminant_type and zero contaminant_proportion, but it's probably faster to check before you call this. +/atom/proc/add_to_reagents_contaminated(reagent_type, amount, data, contaminant_type = null, contaminant_proportion = 0, safety = FALSE, defer_update = FALSE, phase = null) + var/contaminant_to_add = 0 + if(contaminant_type) + contaminant_to_add = CHEMS_QUANTIZE(amount * contaminant_proportion) + add_to_reagents(reagent_type, amount - contaminant_to_add, data, safety = safety, defer_update = !!contaminant_to_add, phase = MAT_PHASE_LIQUID) + if(contaminant_to_add) + add_to_reagents(contaminant_type, contaminant_to_add, phase = MAT_PHASE_LIQUID) + /atom/proc/get_reagent_space() if(!REAGENT_MAXIMUM_VOLUME(reagents)) return 0 From c999bdb6dc95d6e4d896f60186100a335bd51417 Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Fri, 26 Sep 2025 13:37:09 -0400 Subject: [PATCH 012/149] Add flavor strings to flooded turfs --- code/game/turfs/floors/_floor.dm | 5 +++++ code/game/turfs/floors/floor_icon.dm | 3 +++ 2 files changed, 8 insertions(+) diff --git a/code/game/turfs/floors/_floor.dm b/code/game/turfs/floors/_floor.dm index 515dcaca81d..6739729434c 100644 --- a/code/game/turfs/floors/_floor.dm +++ b/code/game/turfs/floors/_floor.dm @@ -76,6 +76,11 @@ if(contaminant_to_add) add_to_reagents(contaminant_reagent_type, contaminant_to_add, phase = MAT_PHASE_LIQUID) +/turf/floor/get_examine_strings(mob/user, distance, infix, suffix) + . = ..() + if(check_fluid_depth(FLUID_SHALLOW)) + . += SPAN_NOTICE("It has a pool of [get_fluid_name()].") + /turf/floor/can_climb_from_below(var/mob/climber) return TRUE diff --git a/code/game/turfs/floors/floor_icon.dm b/code/game/turfs/floors/floor_icon.dm index 2b799313b9b..9e9fac1ac32 100644 --- a/code/game/turfs/floors/floor_icon.dm +++ b/code/game/turfs/floors/floor_icon.dm @@ -128,6 +128,9 @@ else SetName(initial(name)) desc = initial(desc) + // do this once name and desc have been updated + if(check_fluid_depth(FLUID_SHALLOW)) + SetName(get_fluid_name()) // just entirely overwrite name, but keep desc /turf/floor/proc/update_floor_icon() var/decl/flooring/use_flooring = get_topmost_flooring() From eecb58cc26261b666f7f6cac7676290cc3b284f6 Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Fri, 26 Sep 2025 13:37:22 -0400 Subject: [PATCH 013/149] Readd missing update_turf_strings call --- code/game/turfs/floors/floor_icon.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/game/turfs/floors/floor_icon.dm b/code/game/turfs/floors/floor_icon.dm index 9e9fac1ac32..531fa45d125 100644 --- a/code/game/turfs/floors/floor_icon.dm +++ b/code/game/turfs/floors/floor_icon.dm @@ -123,8 +123,7 @@ /turf/floor/proc/update_floor_strings() var/decl/flooring/flooring = get_topmost_flooring() if(istype(flooring)) - SetName(flooring.name) - desc = flooring.desc + flooring.update_turf_strings(src) else SetName(initial(name)) desc = initial(desc) From 89f529aad510545372bbfef6b61fdc955a09833b Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Fri, 26 Sep 2025 13:43:45 -0400 Subject: [PATCH 014/149] Fix get_fluid_name() for flooded turfs --- code/game/turfs/turf_fluids.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/turfs/turf_fluids.dm b/code/game/turfs/turf_fluids.dm index fe248f68977..21227d330c3 100644 --- a/code/game/turfs/turf_fluids.dm +++ b/code/game/turfs/turf_fluids.dm @@ -75,8 +75,8 @@ . = (get_fluid_depth() >= min) /turf/proc/get_fluid_name() - var/decl/material/mat = reagents?.get_primary_reagent_decl() - return mat.get_reagent_name(reagents, MAT_PHASE_LIQUID) || "liquid" + var/decl/material/mat = reagents?.get_primary_reagent_decl() || RESOLVE_TO_DECL(flooded) + return mat?.get_reagent_name(reagents, MAT_PHASE_LIQUID) || "liquid" /turf/get_fluid_depth() if(is_flooded(absolute=1)) From 75af494ac8aa5eee5dc2260cf9f6773e0e5a20cc Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Fri, 26 Sep 2025 14:18:18 -0400 Subject: [PATCH 015/149] Fix base rock and path turfs runtiming in init --- code/game/turfs/flooring/flooring_path.dm | 2 +- code/game/turfs/flooring/flooring_rock.dm | 2 +- code/game/turfs/floors/subtypes/floor_path.dm | 4 +++- code/game/turfs/floors/subtypes/floor_rock.dm | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/code/game/turfs/flooring/flooring_path.dm b/code/game/turfs/flooring/flooring_path.dm index 6a934d5c5eb..1f08b1719eb 100644 --- a/code/game/turfs/flooring/flooring_path.dm +++ b/code/game/turfs/flooring/flooring_path.dm @@ -16,7 +16,7 @@ var/paver_noun = "stones" /decl/flooring/path/update_turf_strings(turf/floor/target) - var/decl/material/floor_material = target?.get_material() + var/decl/material/floor_material = RESOLVE_TO_DECL(target?.get_material()) ASSERT(floor_material?.adjective_name) ASSERT(paver_noun) target.SetName("[floor_material.adjective_name] [name]") diff --git a/code/game/turfs/flooring/flooring_rock.dm b/code/game/turfs/flooring/flooring_rock.dm index 13836a0a7da..ba6caee762a 100644 --- a/code/game/turfs/flooring/flooring_rock.dm +++ b/code/game/turfs/flooring/flooring_rock.dm @@ -10,7 +10,7 @@ uid = "floor_reinf_shuttle_rock" /decl/flooring/rock/update_turf_strings(turf/floor/target) - var/decl/material/turf_material = target?.get_material() + var/decl/material/turf_material = RESOLVE_TO_DECL(target?.get_material()) ASSERT(turf_material?.adjective_name) target.SetName("[turf_material.adjective_name] [name]") target.desc = "An expanse of bare [turf_material.solid_name]." diff --git a/code/game/turfs/floors/subtypes/floor_path.dm b/code/game/turfs/floors/subtypes/floor_path.dm index b67e06bf1b7..bded9334f69 100644 --- a/code/game/turfs/floors/subtypes/floor_path.dm +++ b/code/game/turfs/floors/subtypes/floor_path.dm @@ -11,8 +11,10 @@ _base_flooring = /decl/flooring/dirt /turf/floor/path/Initialize(mapload, no_update_icon) + // Take advantage of the set_turf_materials call in ..() + // to avoid doing pointless work + material ||= get_strata_material_type() || /decl/material/solid/stone/sandstone . = ..() - set_turf_materials(material || get_strata_material_type() || /decl/material/solid/stone/sandstone, skip_update = no_update_icon) if(mapload && is_outside() && prob(20)) var/image/moss = image('icons/effects/decals/plant_remains.dmi', "leafy_bits", DECAL_LAYER) moss.pixel_x = rand(-6, 6) diff --git a/code/game/turfs/floors/subtypes/floor_rock.dm b/code/game/turfs/floors/subtypes/floor_rock.dm index a0e1194fda7..704fd1ad594 100644 --- a/code/game/turfs/floors/subtypes/floor_rock.dm +++ b/code/game/turfs/floors/subtypes/floor_rock.dm @@ -5,8 +5,9 @@ _base_flooring = /decl/flooring/rock /turf/floor/rock/Initialize(mapload, no_update_icon) + // Take advantage of the set_turf_materials call in ..() + material ||= get_strata_material_type() || /decl/material/solid/stone/sandstone . = ..() - set_turf_materials(material || get_strata_material_type() || /decl/material/solid/stone/sandstone, skip_update = no_update_icon) /turf/floor/rock/volcanic name = "volcanic floor" From d786fd141a71e0e52f62bb1843fb6d296b309b36 Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sun, 28 Dec 2025 18:52:43 -0500 Subject: [PATCH 016/149] Make maint_all_access defined on map --- code/game/jobs/access.dm | 2 +- maps/~mapsystem/maps.dm | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 20cd9d5a395..4acbcff8b72 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -66,7 +66,7 @@ if(!istype(supplied_access, /list)) return FALSE - if(maint_all_access) + if(global.using_map.maint_all_access) // todo: movable -> loc -> area -> map datum, to allow separate maps? supplied_access = supplied_access.Copy() supplied_access |= access_maint_tunnels diff --git a/maps/~mapsystem/maps.dm b/maps/~mapsystem/maps.dm index 04ce37b278c..3a161bc41ea 100644 --- a/maps/~mapsystem/maps.dm +++ b/maps/~mapsystem/maps.dm @@ -207,6 +207,9 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also toggleable var/default_ui_style + /// Is maint currently all-access? + var/maint_all_access = FALSE + /datum/map/New() ..() default_ui_style ||= DEFAULT_UI_STYLE @@ -475,11 +478,11 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also toggleable return /datum/map/proc/make_maint_all_access(var/radstorm = 0) - maint_all_access = 1 + maint_all_access = TRUE priority_announcement.Announce("The maintenance access requirement has been revoked on all maintenance airlocks.", "Attention!") /datum/map/proc/revoke_maint_all_access(var/radstorm = 0) - maint_all_access = 0 + maint_all_access = FALSE priority_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.", "Attention!") /datum/map/proc/show_titlescreen(client/C) From e3b546ddbfef4eff78969009b7b53c0a5a7542be Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sun, 28 Dec 2025 18:55:22 -0500 Subject: [PATCH 017/149] Make keycard auth device use decls --- .../security_levels/keycard_authentication.dm | 76 ++++----------- .../keycard_authentication_events.dm | 96 +++++++++++++++++++ nebula.dme | 1 + 3 files changed, 115 insertions(+), 58 deletions(-) create mode 100644 code/modules/security_levels/keycard_authentication_events.dm diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index eca9534b53c..cb91e3c505c 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -65,6 +65,13 @@ interact(user) return TRUE +/obj/machinery/keycard_auth/proc/get_event_options(mob/user) + . = list() + for(var/decl/keycard_auth_event/event in global.decls_repository.get_decls_of_subtype_unassociated(/decl/keycard_auth_event)) + if(!event.is_available(src, user)) + continue + . += event.get_option(src, user) + /obj/machinery/keycard_auth/interact(mob/user) user.set_machine(src) @@ -74,27 +81,12 @@ dat += "